Asterisk - The Open Source Telephony Project  18.5.0
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 - must remain in sync with fake_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  fake_context
 
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 MORE(s)   (*candidate_exten_advance(s))
 
#define NEW_MATCHER_CHK_MATCH
 
#define NEW_MATCHER_RECURSE
 
#define SAY_STUBS   /* generate declarations and stubs for say methods */
 
#define STATUS_NO_CONTEXT   1
 
#define STATUS_NO_EXTENSION   2
 
#define STATUS_NO_LABEL   4
 
#define STATUS_NO_PRIORITY   3
 
#define STATUS_SUCCESS   5
 
#define SWITCH_DATA_LENGTH   256
 
#define VAR_HARDTRAN   3
 
#define VAR_NORMAL   1
 
#define VAR_SOFTTRAN   2
 

Functions

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

Variables

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

Detailed Description

Core PBX routines.

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

Definition in file pbx.c.

Macro Definition Documentation

◆ ADVANCE

#define ADVANCE (   s)    candidate_exten_advance(s)

Definition at line 1229 of file pbx.c.

◆ BITS_PER

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

Referenced by ext_cmp_pattern_pos().

◆ EXT_DATA_SIZE

#define EXT_DATA_SIZE   8192
Note
I M P O R T A N T :

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

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

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

Definition at line 216 of file pbx.c.

Referenced by pbx_extension_helper().

◆ HASH_EXTENHINT_SIZE

#define HASH_EXTENHINT_SIZE   563

Definition at line 358 of file pbx.c.

Referenced by ast_pbx_init().

◆ HINTDEVICE_DATA_LENGTH

#define HINTDEVICE_DATA_LENGTH   16

Definition at line 351 of file pbx.c.

◆ INC_DST_OVERFLOW_CHECK

#define INC_DST_OVERFLOW_CHECK

Referenced by get_pattern_node().

◆ MORE

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

Definition at line 1228 of file pbx.c.

◆ NEW_MATCHER_CHK_MATCH

#define NEW_MATCHER_CHK_MATCH

Referenced by new_find_extension().

◆ NEW_MATCHER_RECURSE

#define NEW_MATCHER_RECURSE

Referenced by new_find_extension().

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

Referenced by pbx_extension_helper(), and pbx_find_extension().

◆ STATUS_NO_EXTENSION

#define STATUS_NO_EXTENSION   2

Definition at line 2468 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

◆ STATUS_NO_LABEL

#define STATUS_NO_LABEL   4

Definition at line 2470 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

◆ STATUS_NO_PRIORITY

#define STATUS_NO_PRIORITY   3

Definition at line 2469 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

◆ STATUS_SUCCESS

#define STATUS_SUCCESS   5

Definition at line 2471 of file pbx.c.

Referenced by pbx_find_extension().

◆ SWITCH_DATA_LENGTH

#define SWITCH_DATA_LENGTH   256

Definition at line 219 of file pbx.c.

◆ VAR_HARDTRAN

#define VAR_HARDTRAN   3

Definition at line 223 of file pbx.c.

◆ VAR_NORMAL

#define VAR_NORMAL   1

Definition at line 221 of file pbx.c.

◆ VAR_SOFTTRAN

#define VAR_SOFTTRAN   2

Definition at line 222 of file pbx.c.

Function Documentation

◆ __ast_context_destroy()

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

Definition at line 8095 of file pbx.c.

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

Referenced by ast_context_destroy(), and ast_context_set_autohints().

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

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

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

Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().

8773 {
8774  int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
8775 
8776  if (!chan)
8777  return -2;
8778 
8779  if (context == NULL)
8780  context = ast_channel_context(chan);
8781  if (exten == NULL)
8782  exten = ast_channel_exten(chan);
8783 
8784  goto_func = (async) ? ast_async_goto : ast_explicit_goto;
8785  if (ast_exists_extension(chan, context, exten, priority,
8786  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)))
8787  return goto_func(chan, context, exten, priority);
8788  else {
8789  return AST_PBX_GOTO_FAILED;
8790  }
8791 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:6987
#define NULL
Definition: resample.c:96
static int priority
Number structure.
Definition: app_followme.c:154
#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:85
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:4179
const char * ast_channel_exten(const struct ast_channel *chan)
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:7011
#define AST_PBX_GOTO_FAILED
Definition: pbx.h:42
const char * ast_channel_context(const struct ast_channel *chan)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ __ast_internal_context_destroy()

static void __ast_internal_context_destroy ( struct ast_context con)
static

Definition at line 8050 of file pbx.c.

References ast_context::alts, ast_free, ast_hashtab_destroy(), ast_mutex_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_context::macrolock, ast_exten::next, NULL, ast_context::pattern_tree, ast_exten::peer, ast_context::registrar, ast_context::root, ast_context::root_table, sw_free(), and tmp().

Referenced by __ast_context_destroy(), and ast_merge_contexts_and_delete().

8051 {
8052  struct ast_exten *e, *el, *en;
8053  struct ast_context *tmp = con;
8054 
8055  /* Free includes */
8057  AST_VECTOR_FREE(&tmp->includes);
8058 
8059  /* Free ignorepats */
8061  AST_VECTOR_FREE(&tmp->ignorepats);
8062 
8063  /* Free switches */
8065  AST_VECTOR_FREE(&tmp->alts);
8066 
8067  if (tmp->registrar)
8068  ast_free(tmp->registrar);
8069 
8070  /* destroy the hash tabs */
8071  if (tmp->root_table) {
8073  }
8074  /* and destroy the pattern tree */
8075  if (tmp->pattern_tree)
8077 
8078  for (e = tmp->root; e;) {
8079  for (en = e->peer; en;) {
8080  el = en;
8081  en = en->peer;
8082  destroy_exten(el);
8083  }
8084  el = e;
8085  e = e->next;
8086  destroy_exten(el);
8087  }
8088  tmp->root = NULL;
8089  ast_rwlock_destroy(&tmp->lock);
8091  ast_free(tmp);
8092 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
struct ast_ignorepats ignorepats
Definition: pbx.c:291
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
struct ast_exten * root
Definition: pbx.c:286
void include_free(struct ast_include *inc)
Definition: pbx_include.c:106
#define ast_rwlock_destroy(rwlock)
Definition: lock.h:231
static int tmp()
Definition: bt_open.c:389
static EditLine * el
Definition: asterisk.c:340
#define NULL
Definition: resample.c:96
void ignorepat_free(struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:77
ast_mutex_t macrolock
Definition: pbx.c:296
struct ast_exten * next
Definition: pbx.c:256
struct ast_exten * peer
Definition: pbx.c:250
char * registrar
Definition: pbx.c:293
struct ast_includes includes
Definition: pbx.c:290
ast_rwlock_t lock
Definition: pbx.c:285
#define ast_free(a)
Definition: astmm.h:182
static void destroy_pattern_tree(struct match_char *pattern_tree)
Definition: pbx.c:1779
void sw_free(struct ast_sw *sw)
Definition: pbx_sw.c:101
struct ast_hashtab * root_table
Definition: pbx.c:287
#define ast_mutex_destroy(a)
Definition: lock.h:186
struct ast_sws alts
Definition: pbx.c:292
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
struct match_char * pattern_tree
Definition: pbx.c:288
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition: vector.h:865
static void destroy_exten(struct ast_exten *e)
Definition: pbx.c:4678
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

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

References 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, collect_digits(), digit, ast_pbx::dtimeoutms, error(), indicate_busy(), indicate_congestion(), LOG_WARNING, ast_pbx_args::no_hangup_chan, NULL, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_destroy(), raise_exception(), ast_pbx::rtimeoutms, S_COR, set_ext_pri(), status, and timeout.

Referenced by ast_pbx_run_args(), and pbx_thread().

4312 {
4313  int found = 0; /* set if we find at least one match */
4314  int res = 0;
4315  int autoloopflag;
4316  int error = 0; /* set an error conditions */
4317  struct ast_pbx *pbx;
4318  ast_callid callid;
4319 
4320  /* A little initial setup here */
4321  if (ast_channel_pbx(c)) {
4322  ast_log(LOG_WARNING, "%s already has PBX structure??\n", ast_channel_name(c));
4323  /* XXX and now what ? */
4325  }
4326  if (!(pbx = ast_calloc(1, sizeof(*pbx)))) {
4327  return AST_PBX_FAILED;
4328  }
4329 
4330  callid = ast_read_threadstorage_callid();
4331  /* If the thread isn't already associated with a callid, we should create that association. */
4332  if (!callid) {
4333  /* Associate new PBX thread with the channel call id if it is availble.
4334  * If not, create a new one instead.
4335  */
4336  callid = ast_channel_callid(c);
4337  if (!callid) {
4338  callid = ast_create_callid();
4339  if (callid) {
4340  ast_channel_lock(c);
4341  ast_channel_callid_set(c, callid);
4342  ast_channel_unlock(c);
4343  }
4344  }
4346  callid = 0;
4347  }
4348 
4349  ast_channel_pbx_set(c, pbx);
4350  /* Set reasonable defaults */
4351  ast_channel_pbx(c)->rtimeoutms = 10000;
4352  ast_channel_pbx(c)->dtimeoutms = 5000;
4353 
4354  ast_channel_lock(c);
4355  autoloopflag = ast_test_flag(ast_channel_flags(c), AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */
4357  ast_channel_unlock(c);
4358 
4360  /* If not successful fall back to 's' - but only if there is no given exten */
4361  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));
4362  /* XXX the original code used the existing priority in the call to
4363  * ast_exists_extension(), and reset it to 1 afterwards.
4364  * I believe the correct thing is to set it to 1 immediately.
4365  */
4366  set_ext_pri(c, "s", 1);
4367  }
4368 
4369  for (;;) {
4370  char dst_exten[256]; /* buffer to accumulate digits */
4371  int pos = 0; /* XXX should check bounds */
4372  int digit = 0;
4373  int invalid = 0;
4374  int timeout = 0;
4375 
4376  /* No digits pressed yet */
4377  dst_exten[pos] = '\0';
4378 
4379  /* loop on priorities in this context/exten */
4381  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL),
4382  &found, 1))) {
4383 
4384  if (!ast_check_hangup(c)) {
4386  continue;
4387  }
4388 
4389  /* Check softhangup flags. */
4391  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
4392  continue;
4393  }
4395  if (ast_exists_extension(c, ast_channel_context(c), "T", 1,
4396  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4397  set_ext_pri(c, "T", 1);
4398  /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4399  memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
4400  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
4401  continue;
4402  } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4403  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4404  raise_exception(c, "ABSOLUTETIMEOUT", 1);
4405  /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4406  memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
4407  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
4408  continue;
4409  }
4410 
4411  /* Call timed out with no special extension to jump to. */
4412  error = 1;
4413  break;
4414  }
4415  ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
4417  error = 1;
4418  break;
4419  } /* end while - from here on we can use 'break' to go out */
4420  if (found && res) {
4421  /* Something bad happened, or a hangup has been requested. */
4422  if (strchr("0123456789ABCDEF*#", res)) {
4423  ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
4424  pos = 0;
4425  dst_exten[pos++] = digit = res;
4426  dst_exten[pos] = '\0';
4427  } else if (res == AST_PBX_INCOMPLETE) {
4428  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));
4429  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));
4430 
4431  /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
4433  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4434  invalid = 1;
4435  } else {
4436  ast_copy_string(dst_exten, ast_channel_exten(c), sizeof(dst_exten));
4437  digit = 1;
4438  pos = strlen(dst_exten);
4439  }
4440  } else {
4441  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));
4442  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));
4443 
4444  if ((res == AST_PBX_ERROR)
4445  && ast_exists_extension(c, ast_channel_context(c), "e", 1,
4446  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4447  /* if we are already on the 'e' exten, don't jump to it again */
4448  if (!strcmp(ast_channel_exten(c), "e")) {
4449  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));
4450  error = 1;
4451  } else {
4452  raise_exception(c, "ERROR", 1);
4453  continue;
4454  }
4455  }
4456 
4457  if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_ASYNCGOTO) {
4458  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
4459  continue;
4460  }
4461  if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_TIMEOUT) {
4462  if (ast_exists_extension(c, ast_channel_context(c), "T", 1,
4463  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4464  set_ext_pri(c, "T", 1);
4465  /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4466  memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
4467  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
4468  continue;
4469  } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4470  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4471  raise_exception(c, "ABSOLUTETIMEOUT", 1);
4472  /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4473  memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
4474  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
4475  continue;
4476  }
4477  /* Call timed out with no special extension to jump to. */
4478  }
4479  error = 1;
4480  break;
4481  }
4482  }
4483  if (error)
4484  break;
4485 
4486  /*!\note
4487  * We get here on a failure of some kind: non-existing extension or
4488  * hangup. We have options, here. We can either catch the failure
4489  * and continue, or we can drop out entirely. */
4490 
4491  if (invalid
4492  || (ast_strlen_zero(dst_exten) &&
4494  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL)))) {
4495  /*!\note
4496  * If there is no match at priority 1, it is not a valid extension anymore.
4497  * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
4498  * neither exist.
4499  */
4500  if (ast_exists_extension(c, ast_channel_context(c), "i", 1,
4501  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4502  ast_verb(3, "Channel '%s' sent to invalid extension: context,exten,priority=%s,%s,%d\n",
4504  pbx_builtin_setvar_helper(c, "INVALID_EXTEN", ast_channel_exten(c));
4505  set_ext_pri(c, "i", 1);
4506  } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4507  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4508  raise_exception(c, "INVALID", 1);
4509  } else {
4510  ast_log(LOG_WARNING, "Channel '%s' sent to invalid extension but no invalid handler: context,exten,priority=%s,%s,%d\n",
4512  error = 1; /* we know what to do with it */
4513  break;
4514  }
4515  } else if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_TIMEOUT) {
4516  /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
4517  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
4518  } else { /* keypress received, get more digits for a full extension */
4519  int waittime = 0;
4520  if (digit)
4521  waittime = ast_channel_pbx(c)->dtimeoutms;
4522  else if (!autofallthrough)
4523  waittime = ast_channel_pbx(c)->rtimeoutms;
4524  if (!waittime) {
4525  const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
4526  if (!status)
4527  status = "UNKNOWN";
4528  ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", ast_channel_name(c), status);
4529  if (!strcasecmp(status, "CONGESTION"))
4530  res = indicate_congestion(c, "10");
4531  else if (!strcasecmp(status, "CHANUNAVAIL"))
4532  res = indicate_congestion(c, "10");
4533  else if (!strcasecmp(status, "BUSY"))
4534  res = indicate_busy(c, "10");
4535  error = 1; /* XXX disable message */
4536  break; /* exit from the 'for' loop */
4537  }
4538 
4539  if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
4540  break;
4541  if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
4542  timeout = 1;
4543  if (!timeout
4544  && ast_exists_extension(c, ast_channel_context(c), dst_exten, 1,
4545  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) { /* Prepare the next cycle */
4546  set_ext_pri(c, dst_exten, 1);
4547  } else {
4548  /* No such extension */
4549  if (!timeout && !ast_strlen_zero(dst_exten)) {
4550  /* An invalid extension */
4551  if (ast_exists_extension(c, ast_channel_context(c), "i", 1,
4552  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4553  ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, ast_channel_context(c), ast_channel_name(c));
4554  pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
4555  set_ext_pri(c, "i", 1);
4556  } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4557  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4558  raise_exception(c, "INVALID", 1);
4559  } else {
4561  "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
4562  dst_exten, ast_channel_context(c));
4563  found = 1; /* XXX disable message */
4564  break;
4565  }
4566  } else {
4567  /* A simple timeout */
4568  if (ast_exists_extension(c, ast_channel_context(c), "t", 1,
4569  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4570  ast_verb(3, "Timeout on %s\n", ast_channel_name(c));
4571  set_ext_pri(c, "t", 1);
4572  } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4573  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4574  raise_exception(c, "RESPONSETIMEOUT", 1);
4575  } else {
4577  "Timeout, but no rule 't' or 'e' in context '%s'\n",
4578  ast_channel_context(c));
4579  found = 1; /* XXX disable message */
4580  break;
4581  }
4582  }
4583  }
4584  }
4585  }
4586 
4587  if (!found && !error) {
4588  ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", ast_channel_name(c));
4589  }
4590 
4591  if (!args || !args->no_hangup_chan) {
4594  && ast_exists_extension(c, ast_channel_context(c), "h", 1,
4595  S_COR(ast_channel_caller(c)->id.number.valid,
4596  ast_channel_caller(c)->id.number.str, NULL))) {
4598  }
4600  }
4601 
4602  ast_channel_lock(c);
4604  ast_clear_flag(ast_channel_flags(c), AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
4605  ast_channel_unlock(c);
4608 
4609  if (!args || !args->no_hangup_chan) {
4610  ast_hangup(c);
4611  }
4612 
4613  return AST_PBX_SUCCESS;
4614 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
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:4204
char digit
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:274
static int autofallthrough
Definition: pbx.c:763
static int timeout
Definition: cdr_mysql.c:86
unsigned int ast_callid
Definition: logger.h:87
#define NULL
Definition: resample.c:96
int ast_channel_priority(const struct ast_channel *chan)
#define ast_verb(level,...)
Definition: logger.h:463
static void pbx_destroy(struct ast_pbx *p)
Definition: pbx.c:985
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
ast_callid ast_read_threadstorage_callid(void)
extracts the callerid from the thread
Definition: logger.c:1962
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct timeval * ast_channel_whentohangup(struct ast_channel *chan)
Number structure.
Definition: app_followme.c:154
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition: logger.c:1984
int indicate_congestion(struct ast_channel *chan, const char *data)
Definition: pbx_builtins.c:757
Definition: pbx.h:211
#define AST_PBX_ERROR
Definition: pbx.h:50
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int raise_exception(struct ast_channel *chan, const char *reason, int priority)
Definition: pbx.c:2806
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition: channel.c:2437
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
#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:85
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2476
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:4179
int indicate_busy(struct ast_channel *chan, const char *data)
Definition: pbx_builtins.c:739
const char * ast_channel_exten(const struct ast_channel *chan)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
#define AST_PBX_INCOMPLETE
Definition: pbx.h:51
void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
Definition: pbx.c:4268
ast_callid ast_create_callid(void)
factory function to create a new uniquely identifying callid.
Definition: logger.c:1957
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:4283
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
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:4199
void ast_channel_pbx_set(struct ast_channel *chan, struct ast_pbx *value)
#define ast_clear_flag(p, flag)
Definition: utils.h:77
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
int ast_pbx_hangup_handler_run(struct ast_channel *chan)
Run all hangup handlers on the channel.
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...
int ast_channel_softhangup_internal_flag(struct ast_channel *chan)
int dtimeoutms
Definition: pbx.h:212
void ast_pbx_h_exten_run(struct ast_channel *chan, const char *context)
Run the h exten from the given context.
Definition: pbx.c:4209
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_channel_name(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
int error(const char *format,...)
Definition: utils/frame.c:999
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
void ast_channel_priority_set(struct ast_channel *chan, int value)
unsigned int no_hangup_chan
Definition: pbx.h:398
ast_callid ast_channel_callid(const struct ast_channel *chan)
jack_status_t status
Definition: app_jack.c:146
int rtimeoutms
Definition: pbx.h:213

◆ __init_extensionstate_buf()

static void __init_extensionstate_buf ( void  )
static

Definition at line 229 of file pbx.c.

237 {

◆ __init_hintdevice_data()

static void __init_hintdevice_data ( void  )
static

Definition at line 352 of file pbx.c.

369 {

◆ __init_switch_data()

static void __init_switch_data ( void  )
static

Definition at line 228 of file pbx.c.

237 {

◆ _extension_match_core()

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

Definition at line 2209 of file pbx.c.

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

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

◆ acf_exception_read()

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

Definition at line 2832 of file pbx.c.

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

2833 {
2835  struct pbx_exception *exception = NULL;
2836  if (!ds || !ds->data)
2837  return -1;
2838  exception = ds->data;
2839  if (!strcasecmp(data, "REASON"))
2840  ast_copy_string(buf, exception->reason, buflen);
2841  else if (!strcasecmp(data, "CONTEXT"))
2842  ast_copy_string(buf, exception->context, buflen);
2843  else if (!strncasecmp(data, "EXTEN", 5))
2844  ast_copy_string(buf, exception->exten, buflen);
2845  else if (!strcasecmp(data, "PRIORITY"))
2846  snprintf(buf, buflen, "%d", exception->priority);
2847  else
2848  return -1;
2849  return 0;
2850 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
const ast_string_field exten
Definition: pbx.c:625
Structure for a data store object.
Definition: datastore.h:68
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:2404
#define NULL
Definition: resample.c:96
const ast_string_field reason
Definition: pbx.c:625
int priority
Definition: pbx.c:627
static const struct ast_datastore_info exception_store_info
Definition: pbx.c:2790
void * data
Definition: datastore.h:70
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const ast_string_field context
Definition: pbx.c:625

◆ action_extensionstatelist()

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

Definition at line 8383 of file pbx.c.

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

8384 {
8385  const char *action_id = astman_get_header(m, "ActionID");
8386  struct ast_hint *hint;
8387  struct ao2_iterator it_hints;
8388  int hint_count = 0;
8389 
8390  if (!hints) {
8391  astman_send_error(s, m, "No dialplan hints are available");
8392  return 0;
8393  }
8394 
8395  astman_send_listack(s, m, "Extension Statuses will follow", "start");
8396 
8397  ao2_lock(hints);
8398  it_hints = ao2_iterator_init(hints, 0);
8399  for (; (hint = ao2_iterator_next(&it_hints)); ao2_ref(hint, -1)) {
8400 
8401  ao2_lock(hint);
8402 
8403  /* Ignore pattern matching hints; they are stored in the
8404  * hints container but aren't real from the perspective of
8405  * an AMI user
8406  */
8407  if (hint->exten->exten[0] == '_') {
8408  ao2_unlock(hint);
8409  continue;
8410  }
8411 
8412  ++hint_count;
8413 
8414  astman_append(s, "Event: ExtensionStatus\r\n");
8415  if (!ast_strlen_zero(action_id)) {
8416  astman_append(s, "ActionID: %s\r\n", action_id);
8417  }
8418  astman_append(s,
8419  "Exten: %s\r\n"
8420  "Context: %s\r\n"
8421  "Hint: %s\r\n"
8422  "Status: %d\r\n"
8423  "StatusText: %s\r\n\r\n",
8424  hint->exten->exten,
8425  hint->exten->parent->name,
8426  hint->exten->app,
8427  hint->laststate,
8429  ao2_unlock(hint);
8430  }
8431 
8432  ao2_iterator_destroy(&it_hints);
8433  ao2_unlock(hints);
8434 
8435  astman_send_list_complete_start(s, m, "ExtensionStateListComplete", hint_count);
8437 
8438  return 0;
8439 }
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
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:3237
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_exten * exten
Hint extension.
Definition: pbx.c:331
char * exten
Definition: pbx.c:238
int laststate
Definition: pbx.c:335
char name[0]
Definition: pbx.c:297
Structure for dial plan hints.
Definition: pbx.c:324
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
const char * app
Definition: pbx.c:246
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
struct ast_context * parent
Definition: pbx.c:245
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
const char * ast_extension_state2str(int extension_state)
Return extension_state as string.
Definition: pbx.c:3126
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:3201

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

References add_pattern_node(), already_in_tree(), ARRAY_LEN, ast_copy_string(), ast_debug, ast_log, buf, pattern_node::buf, ast_exten::cidmatch, match_char::deleted, ast_exten::exten, match_char::exten, get_pattern_node(), LOG_ERROR, LOG_WARNING, ast_exten::matchcid, 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().

1658 {
1659  struct match_char *m1 = NULL;
1660  struct match_char *m2 = NULL;
1661  struct match_char **m0;
1662  const char *pos;
1663  int already;
1664  int pattern = 0;
1665  int idx_cur;
1666  int idx_next;
1667  char extenbuf[512];
1668  struct pattern_node pat_node[2];
1669 
1670  if (e1->matchcid) {
1671  if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) {
1673  "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n",
1674  e1->exten, e1->cidmatch);
1675  return NULL;
1676  }
1677  sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe. We just checked. */
1678  } else {
1679  ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf));
1680  }
1681 
1682 #ifdef NEED_DEBUG
1683  ast_debug(1, "Adding exten %s to tree\n", extenbuf);
1684 #endif
1685  m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
1686  m0 = &con->pattern_tree;
1687  already = 1;
1688 
1689  pos = extenbuf;
1690  if (*pos == '_') {
1691  pattern = 1;
1692  ++pos;
1693  }
1694  idx_cur = 0;
1695  pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf);
1696  for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) {
1697  idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node);
1698  pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf);
1699 
1700  /* See about adding node to tree. */
1701  m2 = NULL;
1702  if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern))
1703  && m2->next_char) {
1704  if (!pat_node[idx_next].buf[0]) {
1705  /*
1706  * This is the end of the pattern, but not the end of the tree.
1707  * Mark this node with the exten... a shorter pattern might win
1708  * if the longer one doesn't match.
1709  */
1710  if (findonly) {
1711  return m2;
1712  }
1713  if (m2->exten) {
1714  ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
1715  m2->deleted ? "(deleted/invalid)" : m2->exten->name, e1->name);
1716  }
1717  m2->exten = e1;
1718  m2->deleted = 0;
1719  }
1720  m1 = m2->next_char; /* m1 points to the node to compare against */
1721  m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */
1722  } else { /* not already OR not m2 OR nor m2->next_char */
1723  if (m2) {
1724  if (findonly) {
1725  return m2;
1726  }
1727  m1 = m2; /* while m0 stays the same */
1728  } else {
1729  if (findonly) {
1730  return m1;
1731  }
1732  m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0);
1733  if (!m1) { /* m1 is the node just added */
1734  return NULL;
1735  }
1736  m0 = &m1->next_char;
1737  }
1738  if (!pat_node[idx_next].buf[0]) {
1739  if (m2 && m2->exten) {
1740  ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
1741  m2->deleted ? "(deleted/invalid)" : m2->exten->name, e1->name);
1742  }
1743  m1->deleted = 0;
1744  m1->exten = e1;
1745  }
1746 
1747  /* The 'already' variable is a mini-optimization designed to make it so that we
1748  * don't have to call already_in_tree when we know it will return false.
1749  */
1750  already = 0;
1751  }
1752  }
1753  return m1;
1754 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
struct ast_exten * exten
Definition: pbx.c:268
char * name
Definition: pbx.c:239
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
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:1459
#define NULL
Definition: resample.c:96
int matchcid
Definition: pbx.c:240
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static struct match_char * already_in_tree(struct match_char *current, char *pat, int is_pattern)
Definition: pbx.c:1397
char * exten
Definition: pbx.c:238
#define LOG_ERROR
Definition: logger.h:285
const char * cidmatch
Definition: pbx.c:241
static const char * get_pattern_node(struct pattern_node *node, const char *src, int pattern, const char *extenbuf)
Definition: pbx.c:1513
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
struct match_char * next_char
Definition: pbx.c:267
struct match_char * pattern_tree
Definition: pbx.c:288
int deleted
Definition: pbx.c:264
match_char: forms a syntax tree for quick matching of extension patterns
Definition: pbx.c:261

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

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_hintdevice::hint, ast_hintdevice::hintdevice, hintdevice_data, hintdevice_destroy(), parse(), str, and strsep().

Referenced by ast_add_hint(), and ast_change_hint().

553 {
554  struct ast_str *str;
555  char *parse;
556  char *cur;
557  struct ast_hintdevice *device;
558  int devicelength;
559 
560  if (!hint || !devicelist) {
561  /* Trying to add garbage? Don't bother. */
562  return 0;
563  }
564  if (!(str = ast_str_thread_get(&hintdevice_data, 16))) {
565  return -1;
566  }
567  ast_str_set(&str, 0, "%s", devicelist);
568  parse = ast_str_buffer(str);
569 
570  /* Spit on '&' and ',' to handle presence hints as well */
571  while ((cur = strsep(&parse, "&,"))) {
572  char *device_name;
573 
574  devicelength = strlen(cur);
575  if (!devicelength) {
576  continue;
577  }
578 
579  device_name = ast_strdup(cur);
580  if (!device_name) {
581  return -1;
582  }
583 
584  device = ao2_t_alloc(sizeof(*device) + devicelength, hintdevice_destroy,
585  "allocating a hintdevice structure");
586  if (!device) {
587  ast_free(device_name);
588  return -1;
589  }
590  strcpy(device->hintdevice, cur);
591  ao2_ref(hint, +1);
592  device->hint = hint;
593  if (AST_VECTOR_APPEND(&hint->devices, device_name)) {
594  ast_free(device_name);
595  ao2_ref(device, -1);
596  return -1;
597  }
598  ao2_t_link(hintdevices, device, "Linking device into hintdevice container.");
599  ao2_t_ref(device, -1, "hintdevice is linked so we can unref");
600  }
601 
602  return 0;
603 }
#define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:463
static void hintdevice_destroy(void *obj)
Definition: pbx.c:540
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Definition: astobj2.h:409
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
static struct ao2_container * hintdevices
Container for hint devices.
Definition: pbx.c:363
#define ao2_t_link(container, obj, tag)
Add an object to a container.
Definition: astobj2.h:1547
struct ast_hint * hint
Hint this hintdevice belongs to.
Definition: pbx.c:374
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
const char * str
Definition: app_jack.c:147
char hintdevice[1]
Definition: pbx.c:376
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:1065
#define ao2_ref(o, delta)
Definition: astobj2.h:464
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define ast_free(a)
Definition: astmm.h:182
static struct ast_threadstorage hintdevice_data
Definition: pbx.c:352
Structure for dial plan hint devices.
Definition: pbx.c:369
char * strsep(char **str, const char *delims)
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:861

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

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

Referenced by add_exten_to_pattern_tree().

1460 {
1461  struct match_char *m;
1462 
1463  if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) {
1464  return NULL;
1465  }
1466 
1467  /* strcpy is safe here since we know its size and have allocated
1468  * just enough space for when we allocated m
1469  */
1470  strcpy(m->x, pattern->buf);
1471 
1472  /* the specificity scores are the same as used in the old
1473  pattern matcher. */
1474  m->is_pattern = is_pattern;
1475  if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') {
1476  m->specificity = 0x0832;
1477  } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') {
1478  m->specificity = 0x0931;
1479  } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') {
1480  m->specificity = 0x0a30;
1481  } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') {
1482  m->specificity = 0x18000;
1483  } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') {
1484  m->specificity = 0x28000;
1485  } else {
1486  m->specificity = pattern->specif;
1487  }
1488 
1489  if (!con->pattern_tree) {
1491  } else {
1492  if (already) { /* switch to the new regime (traversing vs appending)*/
1493  insert_in_next_chars_alt_char_list(nextcharptr, m);
1494  } else {
1496  }
1497  }
1498 
1499  return m;
1500 }
int specificity
Definition: pbx.c:265
#define NULL
Definition: resample.c:96
char x[1]
Definition: pbx.c:269
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
int is_pattern
Definition: pbx.c:263
struct match_char * next_char
Definition: pbx.c:267
int specif
Definition: pbx.c:1454
char buf[256]
Definition: pbx.c:1456
struct match_char * pattern_tree
Definition: pbx.c:288
match_char: forms a syntax tree for quick matching of extension patterns
Definition: pbx.c:261
static void insert_in_next_chars_alt_char_list(struct match_char **parent_ptr, struct match_char *node)
Definition: pbx.c:1418

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

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, match_char::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, ast_context::root, ast_context::root_table, tmp(), and match_char::x.

Referenced by ast_add_extension2_lockopt().

7111 {
7112  struct ast_exten *ep;
7113  struct ast_exten *eh=e;
7114  int repeated_label = 0; /* Track if this label is a repeat, assume no. */
7115 
7116  for (ep = NULL; e ; ep = e, e = e->peer) {
7117  if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
7118  if (strcmp(e->name, tmp->name)) {
7120  "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n",
7121  tmp->name, tmp->priority, con->name, tmp->label, e->name, e->priority);
7122  } else {
7124  "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n",
7125  tmp->name, tmp->priority, con->name, tmp->label, e->priority);
7126  }
7127  repeated_label = 1;
7128  }
7129  if (e->priority >= tmp->priority) {
7130  break;
7131  }
7132  }
7133 
7134  if (repeated_label) { /* Discard the label since it's a repeat. */
7135  tmp->label = NULL;
7136  }
7137 
7138  if (!e) { /* go at the end, and ep is surely set because the list is not empty */
7140 
7141  if (tmp->label) {
7143  }
7144  ep->peer = tmp;
7145  return 0; /* success */
7146  }
7147  if (e->priority == tmp->priority) {
7148  /* Can't have something exactly the same. Is this a
7149  replacement? If so, replace, otherwise, bonk. */
7150  if (!replace) {
7151  if (strcmp(e->name, tmp->name)) {
7153  "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n",
7154  tmp->name, tmp->priority, con->name, e->name);
7155  } else {
7157  "Unable to register extension '%s' priority %d in '%s', already in use\n",
7158  tmp->name, tmp->priority, con->name);
7159  }
7160 
7161  return -1;
7162  }
7163  /* we are replacing e, so copy the link fields and then update
7164  * whoever pointed to e to point to us
7165  */
7166  tmp->next = e->next; /* not meaningful if we are not first in the peer list */
7167  tmp->peer = e->peer; /* always meaningful */
7168  if (ep) { /* We're in the peer list, just insert ourselves */
7170 
7171  if (e->label) {
7173  }
7174 
7176  if (tmp->label) {
7178  }
7179 
7180  ep->peer = tmp;
7181  } else if (el) { /* We're the first extension. Take over e's functions */
7182  struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
7183  tmp->peer_table = e->peer_table;
7184  tmp->peer_label_table = e->peer_label_table;
7187  if (e->label) {
7189  }
7190  if (tmp->label) {
7192  }
7193 
7196  el->next = tmp;
7197  /* The pattern trie points to this exten; replace the pointer,
7198  and all will be well */
7199  if (x) { /* if the trie isn't formed yet, don't sweat this */
7200  if (x->exten) { /* this test for safety purposes */
7201  x->exten = tmp; /* replace what would become a bad pointer */
7202  } else {
7203  ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
7204  }
7205  }
7206  } else { /* We're the very first extension. */
7207  struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
7210  tmp->peer_table = e->peer_table;
7211  tmp->peer_label_table = e->peer_label_table;
7214  if (e->label) {
7216  }
7217  if (tmp->label) {
7219  }
7220 
7223  con->root = tmp;
7224  /* The pattern trie points to this exten; replace the pointer,
7225  and all will be well */
7226  if (x) { /* if the trie isn't formed yet; no problem */
7227  if (x->exten) { /* this test for safety purposes */
7228  x->exten = tmp; /* replace what would become a bad pointer */
7229  } else {
7230  ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
7231  }
7232  }
7233  }
7234  if (tmp->priority == PRIORITY_HINT)
7235  ast_change_hint(e,tmp);
7236  /* Destroy the old one */
7237  if (e->datad)
7238  e->datad(e->data);
7239  ast_free(e);
7240  } else { /* Slip ourselves in just before e */
7241  tmp->peer = e;
7242  tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
7243  if (ep) { /* Easy enough, we're just in the peer list */
7244  if (tmp->label) {
7246  }
7248  ep->peer = tmp;
7249  } else { /* we are the first in some peer list, so link in the ext list */
7250  tmp->peer_table = e->peer_table;
7251  tmp->peer_label_table = e->peer_label_table;
7252  e->peer_table = 0;
7253  e->peer_label_table = 0;
7255  if (tmp->label) {
7257  }
7260  if (el)
7261  el->next = tmp; /* in the middle... */
7262  else
7263  con->root = tmp; /* ... or at the head */
7264  e->next = NULL; /* e is no more at the head, so e->next must be reset */
7265  }
7266  /* And immediately return success. */
7267  if (tmp->priority == PRIORITY_HINT) {
7268  ast_add_hint(tmp);
7269  }
7270  }
7271  return 0;
7272 }
const char * label
Definition: pbx.c:244
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
static int ast_add_hint(struct ast_exten *e)
Add hint to hint list, check initial extension state.
Definition: pbx.c:3982
static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
Change hint for an extension.
Definition: pbx.c:4096
struct ast_exten * exten
Definition: pbx.c:268
struct ast_exten * root
Definition: pbx.c:286
char * name
Definition: pbx.c:239
static struct match_char * add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
Definition: pbx.c:1657
#define LOG_WARNING
Definition: logger.h:274
static int tmp()
Definition: bt_open.c:389
#define NULL
Definition: resample.c:96
struct ast_hashtab * peer_table
Definition: pbx.c:251
char x[1]
Definition: pbx.c:269
#define ast_hashtab_insert_safe(tab, obj)
Definition: hashtab.h:315
struct ast_exten * next
Definition: pbx.c:256
int priority
Definition: pbx.c:243
#define ast_log
Definition: astobj2.c:42
struct ast_exten * peer
Definition: pbx.c:250
#define PRIORITY_HINT
Definition: pbx.h:54
struct ast_hashtab * peer_label_table
Definition: pbx.c:252
#define LOG_ERROR
Definition: logger.h:285
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
char name[0]
Definition: pbx.c:297
#define ast_free(a)
Definition: astmm.h:182
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:790
struct ast_hashtab * root_table
Definition: pbx.c:287
match_char: forms a syntax tree for quick matching of extension patterns
Definition: pbx.c:261

◆ alloc_device_state_info()

static struct ao2_container* alloc_device_state_info ( void  )
static

Definition at line 3076 of file pbx.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_container_alloc_list, and NULL.

Referenced by ast_extension_state_extended(), and device_state_notify_callbacks().

3077 {
3079 }
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1335
#define NULL
Definition: resample.c:96

◆ already_in_tree()

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

Definition at line 1397 of file pbx.c.

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

Referenced by add_exten_to_pattern_tree().

1398 {
1399  struct match_char *t;
1400 
1401  if (!current) {
1402  return 0;
1403  }
1404 
1405  for (t = current; t; t = t->alt_char) {
1406  if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */
1407  return t;
1408  }
1409  }
1410 
1411  return 0;
1412 }
struct match_char * alt_char
Definition: pbx.c:266
char x[1]
Definition: pbx.c:269
int is_pattern
Definition: pbx.c:263
match_char: forms a syntax tree for quick matching of extension patterns
Definition: pbx.c:261

◆ ast_active_calls()

int ast_active_calls ( void  )

Retrieve the number of active calls.

Definition at line 4764 of file pbx.c.

References countcalls.

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

4765 {
4766  return countcalls;
4767 }
static int countcalls
Definition: pbx.c:773

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

References ast_add_extension2(), ast_unlock_contexts(), c, ast_exten::datad, find_context_locked(), and NULL.

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

6973 {
6974  int ret = -1;
6975  struct ast_context *c;
6976 
6978  if (c) {
6979  ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
6980  application, data, datad, registrar, NULL, 0);
6982  }
6983 
6984  return ret;
6985 }
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:7299
static struct test_val c
#define NULL
Definition: resample.c:96
static int priority
structure to hold extensions
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
static char * registrar
Definition: pbx_ael.c:78
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4818
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:790
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

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

References ast_add_extension2_lockopt(), and ast_exten::datad.

Referenced by ast_add_extension(), and context_merge().

7303 {
7304  return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
7305  application, data, datad, registrar, registrar_file, registrar_line, 1);
7306 }
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:7325
static int priority
structure to hold extensions
static char * registrar
Definition: pbx_ael.c:78
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:790

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

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, match_char::deleted, el, errno, ext_cmp(), ext_fluff_count(), ext_strncpy(), ast_exten::exten, match_char::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, ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, ast_exten::registrar_file, ast_exten::registrar_line, ast_context::root, ast_context::root_table, ast_exten::stuff, tmp(), VAR_BUF_SIZE, and match_char::x.

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

7329 {
7330  /*
7331  * Sort extensions (or patterns) according to the rules indicated above.
7332  * These are implemented by the function ext_cmp()).
7333  * All priorities for the same ext/pattern/cid are kept in a list,
7334  * using the 'peer' field as a link field..
7335  */
7336  struct ast_exten *tmp, *tmp2, *e, *el = NULL;
7337  int res;
7338  int length;
7339  char *p;
7340  char expand_buf[VAR_BUF_SIZE];
7341  struct ast_exten dummy_exten = {0};
7342  char dummy_name[1024];
7343  int exten_fluff;
7344  int callerid_fluff;
7345 
7346  if (ast_strlen_zero(extension)) {
7347  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",
7348  con->name);
7349  /* We always need to deallocate 'data' on failure */
7350  if (datad) {
7351  datad(data);
7352  }
7353  return -1;
7354  }
7355 
7356  /* If we are adding a hint evalulate in variables and global variables */
7357  if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') {
7358  int inhibited;
7360 
7361  if (c) {
7363  ast_channel_context_set(c, con->name);
7364  }
7365 
7366  /*
7367  * We can allow dangerous functions when adding a hint since
7368  * altering dialplan is itself a privileged activity. Otherwise,
7369  * we could never execute dangerous functions.
7370  */
7371  inhibited = ast_thread_inhibit_escalations_swap(0);
7372  pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
7373  if (0 < inhibited) {
7375  }
7376 
7377  application = expand_buf;
7378  if (c) {
7379  ast_channel_unref(c);
7380  }
7381  }
7382 
7383  exten_fluff = ext_fluff_count(extension);
7384  callerid_fluff = callerid ? ext_fluff_count(callerid) : 0;
7385 
7386  length = sizeof(struct ast_exten);
7387  length += strlen(extension) + 1;
7388  if (exten_fluff) {
7389  length += strlen(extension) + 1 - exten_fluff;
7390  }
7391  length += strlen(application) + 1;
7392  if (label) {
7393  length += strlen(label) + 1;
7394  }
7395  if (callerid) {
7396  length += strlen(callerid) + 1;
7397  if (callerid_fluff) {
7398  length += strlen(callerid) + 1 - callerid_fluff;
7399  }
7400  } else {
7401  length ++; /* just the '\0' */
7402  }
7403  if (registrar_file) {
7404  length += strlen(registrar_file) + 1;
7405  }
7406 
7407  /* Be optimistic: Build the extension structure first */
7408  tmp = ast_calloc(1, length);
7409  if (!tmp) {
7410  /* We always need to deallocate 'data' on failure */
7411  if (datad) {
7412  datad(data);
7413  }
7414  return -1;
7415  }
7416 
7417  if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
7418  label = 0;
7419 
7420  /* use p as dst in assignments, as the fields are const char * */
7421  p = tmp->stuff;
7422  if (label) {
7423  tmp->label = p;
7424  strcpy(p, label);
7425  p += strlen(label) + 1;
7426  }
7427  tmp->name = p;
7428  p += ext_strncpy(p, extension, strlen(extension) + 1, 0);
7429  if (exten_fluff) {
7430  tmp->exten = p;
7431  p += ext_strncpy(p, extension, strlen(extension) + 1 - exten_fluff, 1);
7432  } else {
7433  /* no fluff, we don't need a copy. */
7434  tmp->exten = tmp->name;
7435  }
7436  tmp->priority = priority;
7437  tmp->cidmatch_display = tmp->cidmatch = p; /* but use p for assignments below */
7438 
7439  /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */
7440  if (callerid) {
7441  p += ext_strncpy(p, callerid, strlen(callerid) + 1, 0);
7442  if (callerid_fluff) {
7443  tmp->cidmatch = p;
7444  p += ext_strncpy(p, callerid, strlen(callerid) + 1 - callerid_fluff, 1);
7445  }
7447  } else {
7448  *p++ = '\0';
7450  }
7451 
7452  if (registrar_file) {
7453  tmp->registrar_file = p;
7454  strcpy(p, registrar_file);
7455  p += strlen(registrar_file) + 1;
7456  } else {
7457  tmp->registrar_file = NULL;
7458  }
7459 
7460  tmp->app = p;
7461  strcpy(p, application);
7462  tmp->parent = con;
7463  tmp->data = data;
7464  tmp->datad = datad;
7465  tmp->registrar = registrar;
7467 
7468  if (lock_context) {
7469  ast_wrlock_context(con);
7470  }
7471 
7472  if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
7473  an extension, and the trie exists, then we need to incrementally add this pattern to it. */
7474  ext_strncpy(dummy_name, tmp->exten, sizeof(dummy_name), 1);
7475  dummy_exten.exten = dummy_name;
7476  dummy_exten.matchcid = AST_EXT_MATCHCID_OFF;
7477  dummy_exten.cidmatch = 0;
7478  tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
7479  if (!tmp2) {
7480  /* hmmm, not in the trie; */
7481  add_exten_to_pattern_tree(con, tmp, 0);
7482  ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
7483  }
7484  }
7485  res = 0; /* some compilers will think it is uninitialized otherwise */
7486  for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */
7487  res = ext_cmp(e->exten, tmp->exten);
7488  if (res == 0) { /* extension match, now look at cidmatch */
7490  res = 0;
7491  else if (tmp->matchcid == AST_EXT_MATCHCID_ON && e->matchcid == AST_EXT_MATCHCID_OFF)
7492  res = 1;
7493  else if (e->matchcid == AST_EXT_MATCHCID_ON && tmp->matchcid == AST_EXT_MATCHCID_OFF)
7494  res = -1;
7495  else
7496  res = ext_cmp(e->cidmatch, tmp->cidmatch);
7497  }
7498  if (res >= 0)
7499  break;
7500  }
7501  if (e && res == 0) { /* exact match, insert in the priority chain */
7502  res = add_priority(con, tmp, el, e, replace);
7503  if (res < 0) {
7504  if (con->pattern_tree) {
7505  struct match_char *x = add_exten_to_pattern_tree(con, tmp, 1);
7506 
7507  if (x->exten) {
7508  x->deleted = 1;
7509  x->exten = 0;
7510  }
7511 
7513  }
7514 
7515  if (tmp->datad) {
7516  tmp->datad(tmp->data);
7517  /* if you free this, null it out */
7518  tmp->data = NULL;
7519  }
7520 
7521  ast_free(tmp);
7522  }
7523  if (lock_context) {
7524  ast_unlock_context(con);
7525  }
7526  if (res < 0) {
7527  errno = EEXIST;
7528  return -1;
7529  }
7530  } else {
7531  /*
7532  * not an exact match, this is the first entry with this pattern,
7533  * so insert in the main list right before 'e' (if any)
7534  */
7535  tmp->next = e;
7536  tmp->peer_table = ast_hashtab_create(13,
7541  0);
7547  0);
7548 
7549  if (el) { /* there is another exten already in this context */
7550  el->next = tmp;
7551  } else { /* this is the first exten in this context */
7552  if (!con->root_table) {
7553  con->root_table = ast_hashtab_create(27,
7558  0);
7559  }
7560  con->root = tmp;
7561  }
7562  if (label) {
7564  }
7567 
7568  if (lock_context) {
7569  ast_unlock_context(con);
7570  }
7571  if (tmp->priority == PRIORITY_HINT) {
7572  ast_add_hint(tmp);
7573  }
7574  }
7575  if (DEBUG_ATLEAST(1)) {
7576  if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
7577  ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
7578  tmp->name, tmp->priority, tmp->cidmatch_display, con->name, con);
7579  } else {
7580  ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s (%p)\n",
7581  tmp->name, tmp->priority, con->name, con);
7582  }
7583  }
7584 
7585  return 0;
7586 }
const char * label
Definition: pbx.c:244
Main Channel structure associated with a channel.
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition: hashtab.c:486
int ast_hashtab_newsize_java(struct ast_hashtab *tab)
Create a prime number roughly 2x the current table size.
Definition: hashtab.c:127
static unsigned int ext_strncpy(char *dst, const char *src, size_t dst_size, int nofluff)
Definition: pbx.c:7068
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8530
static int ast_add_hint(struct ast_exten *e)
Add hint to hint list, check initial extension state.
Definition: pbx.c:3982
struct ast_exten * exten
Definition: pbx.c:268
struct ast_exten * root
Definition: pbx.c:286
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
char * name
Definition: pbx.c:239
static struct match_char * add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
Definition: pbx.c:1657
int registrar_line
Definition: pbx.c:255
static int tmp()
Definition: bt_open.c:389
static int hashtab_compare_extens(const void *ha_a, const void *ah_b)
Definition: pbx.c:693
static EditLine * el
Definition: asterisk.c:340
static struct test_val c
static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b)
Definition: pbx.c:728
#define NULL
Definition: resample.c:96
static unsigned int hashtab_hash_labels(const void *obj)
Definition: pbx.c:757
char stuff[0]
Definition: pbx.c:257
#define LOG_DEBUG
Definition: logger.h:241
struct ast_hashtab * peer_table
Definition: pbx.c:251
static int priority
char x[1]
Definition: pbx.c:269
const char * registrar
Definition: pbx.c:253
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 ast_hashtab_insert_safe(tab, obj)
Definition: hashtab.h:315
#define ast_strlen_zero(foo)
Definition: strings.h:52
int matchcid
Definition: pbx.c:240
struct ast_exten * next
Definition: pbx.c:256
const char * registrar_file
Definition: pbx.c:254
int priority
Definition: pbx.c:243
#define ast_log
Definition: astobj2.c:42
static int ext_cmp(const char *left, const char *right)
Definition: pbx.c:2126
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1283
structure to hold extensions
void(* datad)(void *)
Definition: pbx.c:249
#define PRIORITY_HINT
Definition: pbx.h:54
struct ast_hashtab * peer_label_table
Definition: pbx.c:252
static int ext_fluff_count(const char *exten)
Definition: pbx.c:2148
static unsigned int hashtab_hash_priority(const void *obj)
Definition: pbx.c:751
char * exten
Definition: pbx.c:238
#define LOG_ERROR
Definition: logger.h:285
char name[0]
Definition: pbx.c:297
int errno
int ast_thread_inhibit_escalations_swap(int inhibit)
Swap the current thread escalation inhibit setting.
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition: pbx.c:8520
static char * registrar
Definition: pbx_ael.c:78
static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b)
Definition: pbx.c:721
#define VAR_BUF_SIZE
Definition: pbx_private.h:68
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:790
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
const char * cidmatch
Definition: pbx.c:241
const char * app
Definition: pbx.c:246
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: ael_main.c:211
int ast_thread_inhibit_escalations(void)
Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations...
static unsigned int hashtab_hash_extens(const void *obj)
Definition: pbx.c:741
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:7109
const char * cidmatch_display
Definition: pbx.c:242
struct ast_hashtab * root_table
Definition: pbx.c:287
#define ast_hashtab_create(initial_buckets, compare, resize, newsize, hash, do_locking)
Definition: hashtab.h:261
struct ast_context * parent
Definition: pbx.c:245
void * data
Definition: pbx.c:248
#define DEBUG_ATLEAST(level)
Definition: logger.h:441
struct match_char * pattern_tree
Definition: pbx.c:288
int deleted
Definition: pbx.c:264
match_char: forms a syntax tree for quick matching of extension patterns
Definition: pbx.c:261
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

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

References ast_add_extension2_lockopt(), and ast_exten::datad.

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

7312 {
7313  return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
7314  application, data, datad, registrar, registrar_file, registrar_line, 0);
7315 }
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:7325
static int priority
structure to hold extensions
static char * registrar
Definition: pbx_ael.c:78
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:790

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

References ast_add_extension2_lockopt(), c, ast_exten::datad, find_context(), and NULL.

Referenced by ast_merge_contexts_and_delete().

6953 {
6954  int ret = -1;
6955  struct ast_context *c;
6956 
6957  c = find_context(context);
6958  if (c) {
6959  ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
6960  application, data, datad, registrar, NULL, 0, 1);
6961  }
6962 
6963  return ret;
6964 }
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:7325
static struct test_val c
#define NULL
Definition: resample.c:96
static int priority
structure to hold extensions
static char * registrar
Definition: pbx_ael.c:78
static struct ast_context * find_context(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4804
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:790
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

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

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

Referenced by add_priority(), and ast_add_extension2_lockopt().

3983 {
3984  struct ast_hint *hint_new;
3985  struct ast_hint *hint_found;
3986  char *message = NULL;
3987  char *subtype = NULL;
3988  int presence_state;
3989 
3990  if (!e) {
3991  return -1;
3992  }
3993 
3994  /*
3995  * We must create the hint we wish to add before determining if
3996  * it is already in the hints container to avoid possible
3997  * deadlock when getting the current extension state.
3998  */
3999  hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint);
4000  if (!hint_new) {
4001  return -1;
4002  }
4003  AST_VECTOR_INIT(&hint_new->devices, 8);
4004 
4005  /* Initialize new hint. */
4007  if (!hint_new->callbacks) {
4008  ao2_ref(hint_new, -1);
4009  return -1;
4010  }
4011  hint_new->exten = e;
4012  if (strstr(e->app, "${") && e->exten[0] == '_') {
4013  /* The hint is dynamic and hasn't been evaluted yet */
4014  hint_new->laststate = AST_DEVICE_INVALID;
4016  } else {
4017  hint_new->laststate = ast_extension_state2(e, NULL);
4018  if ((presence_state = extension_presence_state_helper(e, &subtype, &message)) > 0) {
4019  hint_new->last_presence_state = presence_state;
4020  hint_new->last_presence_subtype = subtype;
4021  hint_new->last_presence_message = message;
4022  }
4023  }
4024 
4025  /* Prevent multiple add hints from adding the same hint at the same time. */
4026  ao2_lock(hints);
4027 
4028  /* Search if hint exists, do nothing */
4029  hint_found = ao2_find(hints, e, 0);
4030  if (hint_found) {
4031  ao2_ref(hint_found, -1);
4032  ao2_unlock(hints);
4033  ao2_ref(hint_new, -1);
4034  ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n",
4036  return -1;
4037  }
4038 
4039  /* Add new hint to the hints container */
4040  ast_debug(2, "HINTS: Adding hint %s: %s\n",
4042  ao2_link(hints, hint_new);
4043  if (add_hintdevice(hint_new, ast_get_extension_app(e))) {
4044  ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
4047  }
4048 
4049  /* if not dynamic */
4050  if (!(strstr(e->app, "${") && e->exten[0] == '_')) {
4051  struct ast_state_cb *state_cb;
4052  struct ao2_iterator cb_iter;
4053 
4054  /* For general callbacks */
4055  cb_iter = ao2_iterator_init(statecbs, 0);
4056  for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
4060  state_cb->data,
4062  hint_new,
4063  NULL);
4064  }
4065  ao2_iterator_destroy(&cb_iter);
4066  }
4067  ao2_unlock(hints);
4068  ao2_ref(hint_new, -1);
4069 
4070  return 0;
4071 }
struct ast_context * ast_get_extension_context(struct ast_exten *exten)
Definition: pbx.c:8543
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
void * data
Definition: pbx.c:305
static int extension_presence_state_helper(struct ast_exten *e, char **subtype, char **message)
Definition: pbx.c:3200
#define LOG_WARNING
Definition: logger.h:274
static int add_hintdevice(struct ast_hint *hint, const char *devicelist)
add hintdevice structure and link it into the container.
Definition: pbx.c:552
ast_state_cb: An extension state notify register item
Definition: pbx.c:301
static void destroy_hint(void *obj)
Definition: pbx.c:3907
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1335
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
ast_state_cb_type change_cb
Definition: pbx.c:309
int last_presence_state
Definition: pbx.c:338
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
static int ast_extension_state2(struct ast_exten *e, struct ao2_container *device_state_info)
Check state of extension by using hints.
Definition: pbx.c:3113
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_exten * exten
Hint extension.
Definition: pbx.c:331
char * exten
Definition: pbx.c:238
int laststate
Definition: pbx.c:335
Structure for dial plan hints.
Definition: pbx.c:324
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct ao2_container * callbacks
Definition: pbx.c:332
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
const char * app
Definition: pbx.c:246
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8596
static struct ao2_container * statecbs
Definition: pbx.c:803
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
char * last_presence_message
Definition: pbx.c:340
static int execute_state_callback(ast_state_cb_type cb, const char *context, const char *exten, void *data, enum ast_state_cb_update_reason reason, struct ast_hint *hint, struct ao2_container *device_state_info)
Definition: pbx.c:3250
char * last_presence_subtype
Definition: pbx.c:339
static int hint_id_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:3891
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ ast_async_goto()

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

Set the channel to next execute the specified dialplan location.

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

Definition at line 7011 of file pbx.c.

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, and LOG_WARNING.

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

7012 {
7013  struct ast_channel *newchan;
7014 
7015  ast_channel_lock(chan);
7016  /* Channels in a bridge or running a PBX can be sent directly to the specified destination */
7017  if (ast_channel_is_bridged(chan) || ast_channel_pbx(chan)) {
7019  priority += 1;
7020  }
7023  ast_channel_unlock(chan);
7024  return 0;
7025  }
7026  ast_channel_unlock(chan);
7027 
7028  /* Otherwise, we need to gain control of the channel first */
7029  newchan = ast_channel_yank(chan);
7030  if (!newchan) {
7031  ast_log(LOG_WARNING, "Unable to gain control of channel %s\n", ast_channel_name(chan));
7032  return -1;
7033  }
7035  if (ast_pbx_start(newchan)) {
7036  ast_hangup(newchan);
7037  ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(newchan));
7038  return -1;
7039  }
7040 
7041  return 0;
7042 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
#define ast_test_flag(p, flag)
Definition: utils.h:63
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:6987
#define LOG_WARNING
Definition: logger.h:274
struct ast_channel * ast_channel_yank(struct ast_channel *yankee)
Gain control of a channel in the system.
Definition: channel.c:10794
static int priority
#define ast_log
Definition: astobj2.c:42
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4712
int ast_softhangup_nolock(struct ast_channel *chan, int reason)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2463
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10746
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
const char * ast_channel_name(const struct ast_channel *chan)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_flags * ast_channel_flags(struct ast_channel *chan)

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

References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.

7045 {
7046  struct ast_channel *chan;
7047  int res = -1;
7048 
7049  if ((chan = ast_channel_get_by_name(channame))) {
7050  res = ast_async_goto(chan, context, exten, priority);
7051  chan = ast_channel_unref(chan);
7052  }
7053 
7054  return res;
7055 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
static int priority
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:7011
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454

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

References __ast_goto_if_exists().

8799 {
8800  return __ast_goto_if_exists(chan, context, exten, priority, 1);
8801 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static int __ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
Definition: pbx.c:8772
static int priority
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

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

References pbx_parseable_goto().

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

8865 {
8866  return pbx_parseable_goto(chan, goto_string, 1);
8867 }
static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string, int async)
Definition: pbx.c:8803

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

References E_CANMATCH, NULL, and pbx_extension_helper().

Referenced by __analog_ss_thread(), analog_ss_thread(), background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), leave_voicemail(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), test_exten(), and valid_exit().

4195 {
4196  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
4197 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define NULL
Definition: resample.c:96
static int priority
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
The return value depends on the action:
Definition: pbx.c:2875

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

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

4097 {
4098  struct ast_hint *hint;
4099 
4100  if (!oe || !ne) {
4101  return -1;
4102  }
4103 
4104  ao2_lock(hints);/* Locked to hold off others while we move the hint around. */
4105 
4106  /*
4107  * Unlink the hint from the hints container as the extension
4108  * name (which is the hash value) could change.
4109  */
4110  hint = ao2_find(hints, oe, OBJ_UNLINK);
4111  if (!hint) {
4112  ao2_unlock(hints);
4114  return -1;
4115  }
4116 
4117  remove_hintdevice(hint);
4118 
4119  /* Update the hint and put it back in the hints container. */
4120  ao2_lock(hint);
4121  hint->exten = ne;
4122 
4123  ao2_unlock(hint);
4124 
4125  ao2_link(hints, hint);
4126  if (add_hintdevice(hint, ast_get_extension_app(ne))) {
4127  ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
4130  }
4131  ao2_unlock(hints);
4132 
4133  publish_hint_change(hint, ne);
4134 
4135  ao2_ref(hint, -1);
4136 
4137  return 0;
4138 }
struct ast_context * ast_get_extension_context(struct ast_exten *exten)
Definition: pbx.c:8543
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
#define LOG_WARNING
Definition: logger.h:274
static int add_hintdevice(struct ast_hint *hint, const char *devicelist)
add hintdevice structure and link it into the container.
Definition: pbx.c:552
static ast_mutex_t context_merge_lock
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
Definition: pbx.c:790
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_exten * exten
Hint extension.
Definition: pbx.c:331
Structure for dial plan hints.
Definition: pbx.c:324
static int remove_hintdevice(struct ast_hint *hint)
Definition: pbx.c:517
static int publish_hint_change(struct ast_hint *hint, struct ast_exten *ne)
Publish a hint changed event.
Definition: pbx.c:4074
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8596
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ao2_link(container, obj)
Definition: astobj2.h:1549

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

References ast_context_add_ignorepat2(), ast_unlock_contexts(), c, and find_context_locked().

Referenced by handle_cli_dialplan_add_ignorepat().

6878 {
6879  int ret = -1;
6880  struct ast_context *c;
6881 
6883  if (c) {
6886  }
6887  return ret;
6888 }
static struct test_val c
int value
Definition: syslog.c:37
int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
Definition: pbx.c:6890
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
static char * registrar
Definition: pbx_ael.c:78
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4818
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

◆ ast_context_add_ignorepat2()

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

Definition at line 6890 of file pbx.c.

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(), and ast_context::ignorepats.

Referenced by ast_context_add_ignorepat(), and context_merge_incls_swits_igps_other_registrars().

6891 {
6892  struct ast_ignorepat *ignorepat = ignorepat_alloc(value, registrar);
6893  int idx;
6894 
6895  if (!ignorepat) {
6896  return -1;
6897  }
6898 
6899  ast_wrlock_context(con);
6900  for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6901  const struct ast_ignorepat *i = ast_context_ignorepats_get(con, idx);
6902 
6903  if (!strcasecmp(ast_get_ignorepat_name(i), value)) {
6904  /* Already there */
6905  ast_unlock_context(con);
6906  ignorepat_free(ignorepat);
6907  errno = EEXIST;
6908  return -1;
6909  }
6910  }
6911  if (AST_VECTOR_APPEND(&con->ignorepats, ignorepat)) {
6912  ignorepat_free(ignorepat);
6913  ast_unlock_context(con);
6914  return -1;
6915  }
6916  ast_unlock_context(con);
6917 
6918  return 0;
6919 }
struct ast_ignorepats ignorepats
Definition: pbx.c:291
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8530
const struct ast_ignorepat * ast_context_ignorepats_get(const struct ast_context *con, int idx)
Definition: pbx.c:8745
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
int value
Definition: syslog.c:37
void ignorepat_free(struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:77
const char * ast_get_ignorepat_name(const struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:42
int ast_context_ignorepats_count(const struct ast_context *con)
Definition: pbx.c:8740
struct ast_ignorepat * ignorepat_alloc(const char *value, const char *registrar)
Definition: pbx_ignorepat.c:52
ast_ignorepat: Ignore patterns in dial plan
Definition: pbx_ignorepat.c:37
int errno
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition: pbx.c:8520
static char * registrar
Definition: pbx_ael.c:78

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

References ast_context_add_include2(), ast_unlock_contexts(), c, and find_context_locked().

Referenced by AST_TEST_DEFINE(), and handle_cli_dialplan_add_include().

6707 {
6708  int ret = -1;
6709  struct ast_context *c;
6710 
6712  if (c) {
6713  ret = ast_context_add_include2(c, include, registrar);
6715  }
6716  return ret;
6717 }
int ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
Add a context include.
Definition: pbx.c:6726
static struct test_val c
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
static char * registrar
Definition: pbx_ael.c:78
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4818
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

◆ ast_context_add_include2()

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

Add a context include.

Parameters
concontext to add the include to
valueinclude value to add
registrarwho registered the context

Adds an include taking a struct ast_context as the first parameter

Return values
0on success
-1on failure

Definition at line 6726 of file pbx.c.

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(), and ast_context::includes.

Referenced by ast_context_add_include(), and context_merge_incls_swits_igps_other_registrars().

6728 {
6729  struct ast_include *new_include;
6730  int idx;
6731 
6732  /* allocate new include structure ... */
6733  new_include = include_alloc(value, registrar);
6734  if (!new_include) {
6735  return -1;
6736  }
6737 
6738  ast_wrlock_context(con);
6739 
6740  /* ... go to last include and check if context is already included too... */
6741  for (idx = 0; idx < ast_context_includes_count(con); idx++) {
6742  const struct ast_include *i = ast_context_includes_get(con, idx);
6743 
6744  if (!strcasecmp(ast_get_include_name(i), ast_get_include_name(new_include))) {
6745  include_free(new_include);
6746  ast_unlock_context(con);
6747  errno = EEXIST;
6748  return -1;
6749  }
6750  }
6751 
6752  /* ... include new context into context list, unlock, return */
6753  if (AST_VECTOR_APPEND(&con->includes, new_include)) {
6754  include_free(new_include);
6755  ast_unlock_context(con);
6756  return -1;
6757  }
6758  ast_debug(1, "Including context '%s' in context '%s'\n",
6759  ast_get_include_name(new_include), ast_get_context_name(con));
6760 
6761  ast_unlock_context(con);
6762 
6763  return 0;
6764 }
ast_include: include= support in extensions.conf
Definition: pbx_include.c:37
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8530
struct ast_include * include_alloc(const char *value, const char *registrar)
Definition: pbx_include.c:74
void include_free(struct ast_include *inc)
Definition: pbx_include.c:106
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
int value
Definition: syslog.c:37
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct ast_includes includes
Definition: pbx.c:290
int errno
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition: pbx.c:8520
static char * registrar
Definition: pbx_ael.c:78
const char * ast_get_include_name(const struct ast_include *include)
Definition: pbx_include.c:50
const struct ast_include * ast_context_includes_get(const struct ast_context *con, int idx)
Definition: pbx.c:8702
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
int ast_context_includes_count(const struct ast_context *con)
Definition: pbx.c:8697

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

References ast_context_add_switch2(), ast_unlock_contexts(), c, and find_context_locked().

6772 {
6773  int ret = -1;
6774  struct ast_context *c;
6775 
6777  if (c) { /* found, add switch to this context */
6778  ret = ast_context_add_switch2(c, sw, data, eval, registrar);
6780  }
6781  return ret;
6782 }
static struct test_val c
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
static char * registrar
Definition: pbx_ael.c:78
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4818
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:6791
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

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

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(), errno, sw_alloc(), and sw_free().

Referenced by ast_context_add_switch(), and context_merge_incls_swits_igps_other_registrars().

6793 {
6794  int idx;
6795  struct ast_sw *new_sw;
6796 
6797  /* allocate new sw structure ... */
6798  if (!(new_sw = sw_alloc(value, data, eval, registrar))) {
6799  return -1;
6800  }
6801 
6802  /* ... try to lock this context ... */
6803  ast_wrlock_context(con);
6804 
6805  /* ... go to last sw and check if context is already swd too... */
6806  for (idx = 0; idx < ast_context_switches_count(con); idx++) {
6807  const struct ast_sw *i = ast_context_switches_get(con, idx);
6808 
6809  if (!strcasecmp(ast_get_switch_name(i), ast_get_switch_name(new_sw)) &&
6810  !strcasecmp(ast_get_switch_data(i), ast_get_switch_data(new_sw))) {
6811  sw_free(new_sw);
6812  ast_unlock_context(con);
6813  errno = EEXIST;
6814  return -1;
6815  }
6816  }
6817 
6818  /* ... sw new context into context list, unlock, return */
6819  if (AST_VECTOR_APPEND(&con->alts, new_sw)) {
6820  sw_free(new_sw);
6821  ast_unlock_context(con);
6822  return -1;
6823  }
6824 
6825  ast_verb(3, "Including switch '%s/%s' in context '%s'\n",
6827 
6828  ast_unlock_context(con);
6829 
6830  return 0;
6831 }
const char * ast_get_switch_name(const struct ast_sw *sw)
Definition: pbx_sw.c:48
int ast_context_switches_count(const struct ast_context *con)
Definition: pbx.c:8652
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8530
const struct ast_sw * ast_context_switches_get(const struct ast_context *con, int idx)
Definition: pbx.c:8657
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
int value
Definition: syslog.c:37
#define ast_verb(level,...)
Definition: logger.h:463
ast_sw: Switch statement in extensions.conf
Definition: pbx_sw.c:37
const char * data
Definition: pbx_sw.c:42
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
int errno
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition: pbx.c:8520
static char * registrar
Definition: pbx_ael.c:78
const char * ast_get_switch_data(const struct ast_sw *sw)
Definition: pbx_sw.c:53
void sw_free(struct ast_sw *sw)
Definition: pbx_sw.c:101
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
struct ast_sws alts
Definition: pbx.c:292

◆ 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.

Returns
nothing

Definition at line 8260 of file pbx.c.

References __ast_context_destroy(), ast_unlock_contexts(), and ast_wrlock_contexts().

Referenced by ast_context_destroy_by_name().

8261 {
8265 }
void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
Definition: pbx.c:8095
static struct ast_hashtab * contexts_table
Definition: pbx.c:777
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8502
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
static char * registrar
Definition: pbx_ael.c:78
static struct ast_context * contexts
Definition: pbx.c:776

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

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

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

8245 {
8246  struct ast_context *con;
8247  int ret = -1;
8248 
8250  con = ast_context_find(context);
8251  if (con) {
8253  ret = 0;
8254  }
8256 
8257  return ret;
8258 }
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: pbx.c:2443
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
Definition: pbx.c:8260
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8502
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
static char * registrar
Definition: pbx_ael.c:78
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

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

References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), ast_context::name, fake_context::name, NULL, and tmp().

Referenced by _macro_exec(), app_create(), ast_context_destroy_by_name(), ast_context_verify_includes(), ast_ignore_pattern(), handle_cli_dialplan_add_extension(), handle_cli_dialplan_add_include(), isexten_function_read(), register_exten(), register_peer_exten(), and unregister_exten().

2444 {
2445  struct ast_context *tmp;
2446  struct fake_context item;
2447 
2448  if (!name) {
2449  return NULL;
2450  }
2452  if (contexts_table) {
2453  ast_copy_string(item.name, name, sizeof(item.name));
2455  } else {
2456  tmp = NULL;
2457  while ((tmp = ast_walk_contexts(tmp))) {
2458  if (!strcasecmp(name, tmp->name)) {
2459  break;
2460  }
2461  }
2462  }
2464  return tmp;
2465 }
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition: hashtab.c:486
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: pbx.c:8609
static struct ast_hashtab * contexts_table
Definition: pbx.c:777
static int tmp()
Definition: bt_open.c:389
static struct aco_type item
Definition: test_config.c:1463
#define NULL
Definition: resample.c:96
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8507
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
char name[0]
Definition: pbx.c:297
static const char name[]
Definition: cdr_mysql.c:74
const char * name
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

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

References ast_context::alts, ast_calloc, ast_copy_string(), 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_mutex_init, ast_rdlock_contexts(), ast_rwlock_init, ast_strdup, ast_unlock_contexts(), AST_VECTOR_INIT, ast_wrlock_contexts(), contexts, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, ast_context::macrolock, ast_context::name, fake_context::name, ast_context::next, NULL, ast_context::refcount, ast_context::registrar, ast_context::root, ast_context::root_table, and tmp().

Referenced by context_merge().

6199 {
6200  struct ast_context *tmp, **local_contexts;
6201  struct fake_context search;
6202  int length = sizeof(struct ast_context) + strlen(name) + 1;
6203 
6204  if (!contexts_table) {
6205  /* Protect creation of contexts_table from reentrancy. */
6207  if (!contexts_table) {
6213  0);
6214  }
6216  }
6217 
6218  ast_copy_string(search.name, name, sizeof(search.name));
6219  if (!extcontexts) {
6221  local_contexts = &contexts;
6222  tmp = ast_hashtab_lookup(contexts_table, &search);
6223  if (tmp) {
6224  tmp->refcount++;
6226  return tmp;
6227  }
6228  } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
6229  local_contexts = extcontexts;
6230  tmp = ast_hashtab_lookup(exttable, &search);
6231  if (tmp) {
6232  tmp->refcount++;
6233  return tmp;
6234  }
6235  }
6236 
6237  if ((tmp = ast_calloc(1, length))) {
6238  ast_rwlock_init(&tmp->lock);
6239  ast_mutex_init(&tmp->macrolock);
6240  strcpy(tmp->name, name);
6241  tmp->root = NULL;
6242  tmp->root_table = NULL;
6243  tmp->registrar = ast_strdup(registrar);
6244  AST_VECTOR_INIT(&tmp->includes, 0);
6245  AST_VECTOR_INIT(&tmp->ignorepats, 0);
6246  AST_VECTOR_INIT(&tmp->alts, 0);
6247  tmp->refcount = 1;
6248  } else {
6249  ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
6250  if (!extcontexts) {
6252  }
6253  return NULL;
6254  }
6255 
6256  if (!extcontexts) {
6257  tmp->next = *local_contexts;
6258  *local_contexts = tmp;
6259  ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
6261  } else {
6262  tmp->next = *local_contexts;
6263  if (exttable)
6264  ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
6265 
6266  *local_contexts = tmp;
6267  }
6268  ast_debug(1, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
6269  return tmp;
6270 }
struct ast_ignorepats ignorepats
Definition: pbx.c:291
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition: hashtab.c:486
int ast_hashtab_newsize_java(struct ast_hashtab *tab)
Create a prime number roughly 2x the current table size.
Definition: hashtab.c:127
struct ast_exten * root
Definition: pbx.c:286
static struct ast_hashtab * contexts_table
Definition: pbx.c:777
static int tmp()
Definition: bt_open.c:389
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
struct ast_context * local_contexts
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8507
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 ast_hashtab_insert_safe(tab, obj)
Definition: hashtab.h:315
struct ast_context * next
Definition: pbx.c:289
ast_mutex_t macrolock
Definition: pbx.c:296
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8502
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_hashtab_insert_immediate(tab, obj)
Definition: hashtab.h:291
#define ast_log
Definition: astobj2.c:42
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
char * registrar
Definition: pbx.c:293
struct ast_includes includes
Definition: pbx.c:290
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
ast_rwlock_t lock
Definition: pbx.c:285
#define LOG_ERROR
Definition: logger.h:285
char name[0]
Definition: pbx.c:297
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
Definition: lock.h:222
static char * registrar
Definition: pbx_ael.c:78
static const char name[]
Definition: cdr_mysql.c:74
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
unsigned int ast_hashtab_hash_contexts(const void *obj)
Definition: pbx.c:735
int refcount
Definition: pbx.c:294
struct ast_hashtab * root_table
Definition: pbx.c:287
static struct ast_context * contexts
Definition: pbx.c:776
#define ast_hashtab_create(initial_buckets, compare, resize, newsize, hash, do_locking)
Definition: hashtab.h:261
#define ast_mutex_init(pmutex)
Definition: lock.h:184
struct ast_sws alts
Definition: pbx.c:292
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
hashtable functions for contexts
Definition: pbx.c:683

◆ 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_lockmacro()

int ast_context_lockmacro ( const char *  context)

locks the macrolock in the given context

Note
This function locks contexts list by &conlist, searches for the right context structure, and locks the macrolock mutex in that context. macrolock is used to limit a macro to be executed by one call at a time.
Parameters
contextThe context

Definition at line 5162 of file pbx.c.

References ast_mutex_lock, ast_unlock_contexts(), c, find_context_locked(), and ast_context::macrolock.

Referenced by _macro_exec().

5163 {
5164  struct ast_context *c;
5165  int ret = -1;
5166 
5168  if (c) {
5170 
5171  /* if we found context, lock macrolock */
5172  ret = ast_mutex_lock(&c->macrolock);
5173  }
5174 
5175  return ret;
5176 }
#define ast_mutex_lock(a)
Definition: lock.h:187
static struct test_val c
ast_mutex_t macrolock
Definition: pbx.c:296
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4818
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

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

References ast_context_remove_extension_callerid(), AST_EXT_MATCHCID_ANY, and NULL.

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

4953 {
4955 }
#define NULL
Definition: resample.c:96
static int priority
structure to hold extensions
static char * registrar
Definition: pbx_ael.c:78
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
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:4957

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

References ast_context_remove_extension_callerid2(), AST_EXT_MATCHCID_ANY, and NULL.

Referenced by add_extension(), and add_hints().

4983 {
4985 }
#define NULL
Definition: resample.c:96
static int priority
structure to hold extensions
static char * registrar
Definition: pbx_ael.c:78
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:4987

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

References ast_context_remove_extension_callerid2(), ast_unlock_contexts(), c, and find_context_locked().

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

4958 {
4959  int ret = -1; /* default error return */
4960  struct ast_context *c;
4961 
4963  if (c) { /* ... remove extension ... */
4965  matchcallerid, registrar, 0);
4967  }
4968 
4969  return ret;
4970 }
static struct test_val c
static int priority
structure to hold extensions
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
static char * registrar
Definition: pbx_ael.c:78
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4818
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:4987
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

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

References add_exten_to_pattern_tree(), 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, match_char::deleted, 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, ast_exten::priority, ast_exten::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().

4988 {
4989  struct ast_exten *exten, *prev_exten = NULL;
4990  struct ast_exten *peer;
4991  struct ast_exten ex, *exten2, *exten3;
4992  char dummy_name[1024];
4993  char dummy_cid[1024];
4994  struct ast_exten *previous_peer = NULL;
4995  struct ast_exten *next_peer = NULL;
4996  int found = 0;
4997 
4998  if (!already_locked)
4999  ast_wrlock_context(con);
5000 
5001 #ifdef NEED_DEBUG
5002  ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
5003 #endif
5004 #ifdef CONTEXT_DEBUG
5005  check_contexts(__FILE__, __LINE__);
5006 #endif
5007  /* find this particular extension */
5008  ex.exten = dummy_name;
5009  ext_strncpy(dummy_name, extension, sizeof(dummy_name), 1);
5010  ex.matchcid = matchcallerid;
5011  if (callerid) {
5012  ex.cidmatch = dummy_cid;
5013  ext_strncpy(dummy_cid, callerid, sizeof(dummy_cid), 1);
5014  } else {
5015  ex.cidmatch = NULL;
5016  }
5017  exten = ast_hashtab_lookup(con->root_table, &ex);
5018  if (exten) {
5019  if (priority == 0) {
5020  exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
5021  if (!exten2)
5022  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);
5023  if (con->pattern_tree) {
5024  struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
5025 
5026  if (x->exten) { /* this test for safety purposes */
5027  x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
5028  x->exten = 0; /* get rid of what will become a bad pointer */
5029  } else {
5030  ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
5031  }
5032  }
5033  } else {
5034  ex.priority = priority;
5035  exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
5036  if (exten2) {
5037  if (exten2->label) { /* if this exten has a label, remove that, too */
5038  exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
5039  if (!exten3) {
5040  ast_log(LOG_ERROR, "Did not remove this priority label (%d/%s) "
5041  "from the peer_label_table of context %s, extension %s!\n",
5042  priority, exten2->label, con->name, exten2->name);
5043  }
5044  }
5045 
5046  exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
5047  if (!exten3) {
5048  ast_log(LOG_ERROR, "Did not remove this priority (%d) from the "
5049  "peer_table of context %s, extension %s!\n",
5050  priority, con->name, exten2->name);
5051  }
5052  if (exten2 == exten && exten2->peer) {
5053  exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
5055  }
5056  if (ast_hashtab_size(exten->peer_table) == 0) {
5057  /* well, if the last priority of an exten is to be removed,
5058  then, the extension is removed, too! */
5059  exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
5060  if (!exten3) {
5061  ast_log(LOG_ERROR, "Did not remove this exten (%s) from the "
5062  "context root_table (%s) (priority %d)\n",
5063  exten->name, con->name, priority);
5064  }
5065  if (con->pattern_tree) {
5066  struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
5067  if (x->exten) { /* this test for safety purposes */
5068  x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
5069  x->exten = 0; /* get rid of what will become a bad pointer */
5070  }
5071  }
5072  }
5073  } else {
5074  ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
5075  priority, exten->name, con->name);
5076  }
5077  }
5078  } else {
5079  /* hmmm? this exten is not in this pattern tree? */
5080  ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
5081  extension, con->name);
5082  }
5083 #ifdef NEED_DEBUG
5084  if (con->pattern_tree) {
5085  ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
5086  log_match_char_tree(con->pattern_tree, " ");
5087  }
5088 #endif
5089 
5090  /* scan the extension list to find first matching extension-registrar */
5091  for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
5092  if (!strcmp(exten->exten, ex.exten) &&
5093  (!matchcallerid ||
5094  (!ast_strlen_zero(ex.cidmatch) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, ex.cidmatch)) ||
5095  (ast_strlen_zero(ex.cidmatch) && ast_strlen_zero(exten->cidmatch)))) {
5096  break;
5097  }
5098  }
5099  if (!exten) {
5100  /* we can't find right extension */
5101  if (!already_locked)
5102  ast_unlock_context(con);
5103  return -1;
5104  }
5105 
5106  /* scan the priority list to remove extension with exten->priority == priority */
5107  for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
5108  peer && !strcmp(peer->exten, ex.exten) &&
5109  (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, ex.cidmatch))) ;
5110  peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
5111 
5112  if ((priority == 0 || peer->priority == priority) &&
5113  (!registrar || !strcmp(peer->registrar, registrar) )) {
5114  found = 1;
5115 
5116  /* we are first priority extension? */
5117  if (!previous_peer) {
5118  /*
5119  * We are first in the priority chain, so must update the extension chain.
5120  * The next node is either the next priority or the next extension
5121  */
5122  struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
5123  if (peer->peer) {
5124  /* move the peer_table and peer_label_table down to the next peer, if
5125  it is there */
5126  peer->peer->peer_table = peer->peer_table;
5127  peer->peer->peer_label_table = peer->peer_label_table;
5128  peer->peer_table = NULL;
5129  peer->peer_label_table = NULL;
5130  }
5131  if (!prev_exten) { /* change the root... */
5132  con->root = next_node;
5133  } else {
5134  prev_exten->next = next_node; /* unlink */
5135  }
5136  if (peer->peer) { /* update the new head of the pri list */
5137  peer->peer->next = peer->next;
5138  }
5139  } else { /* easy, we are not first priority in extension */
5140  previous_peer->peer = peer->peer;
5141  }
5142 
5143 
5144  /* now, free whole priority extension */
5145  destroy_exten(peer);
5146  } else {
5147  previous_peer = peer;
5148  }
5149  }
5150  if (!already_locked)
5151  ast_unlock_context(con);
5152  return found ? 0 : -1;
5153 }
const char * label
Definition: pbx.c:244
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition: hashtab.c:486
static unsigned int ext_strncpy(char *dst, const char *src, size_t dst_size, int nofluff)
Definition: pbx.c:7068
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8530
struct ast_exten * exten
Definition: pbx.c:268
struct ast_exten * root
Definition: pbx.c:286
char * name
Definition: pbx.c:239
static struct match_char * add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
Definition: pbx.c:1657
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
struct ast_hashtab * peer_table
Definition: pbx.c:251
static int priority
char x[1]
Definition: pbx.c:269
#define ast_verb(level,...)
Definition: logger.h:463
const char * registrar
Definition: pbx.c:253
#define ast_strlen_zero(foo)
Definition: strings.h:52
int matchcid
Definition: pbx.c:240
struct ast_exten * next
Definition: pbx.c:256
#define ast_hashtab_insert_immediate(tab, obj)
Definition: hashtab.h:291
int priority
Definition: pbx.c:243
#define ast_log
Definition: astobj2.c:42
struct ast_exten * peer
Definition: pbx.c:250
structure to hold extensions
struct ast_hashtab * peer_label_table
Definition: pbx.c:252
char * exten
Definition: pbx.c:238
#define LOG_ERROR
Definition: logger.h:285
char name[0]
Definition: pbx.c:297
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition: pbx.c:8520
#define LOG_NOTICE
Definition: logger.h:263
static char * registrar
Definition: pbx_ael.c:78
const char * cidmatch
Definition: pbx.c:241
struct ast_hashtab * root_table
Definition: pbx.c:287
int ast_hashtab_size(struct ast_hashtab *tab)
Returns the number of elements stored in the hashtab.
Definition: hashtab.c:577
struct match_char * pattern_tree
Definition: pbx.c:288
static void destroy_exten(struct ast_exten *e)
Definition: pbx.c:4678
int deleted
Definition: pbx.c:264
match_char: forms a syntax tree for quick matching of extension patterns
Definition: pbx.c:261
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

◆ ast_context_remove_ignorepat()

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

Definition at line 6837 of file pbx.c.

References ast_context_remove_ignorepat2(), ast_unlock_contexts(), c, and find_context_locked().

Referenced by handle_cli_dialplan_remove_ignorepat().

6838 {
6839  int ret = -1;
6840  struct ast_context *c;
6841 
6843  if (c) {
6844  ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
6846  }
6847  return ret;
6848 }
int ast_context_remove_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
Definition: pbx.c:6850
static struct test_val c
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
static char * registrar
Definition: pbx_ael.c:78
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4818
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

◆ ast_context_remove_ignorepat2()

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

Definition at line 6850 of file pbx.c.

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(), and ast_context::ignorepats.

Referenced by ast_context_remove_ignorepat().

6851 {
6852  int idx;
6853 
6854  ast_wrlock_context(con);
6855 
6856  for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6857  struct ast_ignorepat *ip = AST_VECTOR_GET(&con->ignorepats, idx);
6858 
6859  if (!strcmp(ast_get_ignorepat_name(ip), ignorepat) &&
6862  ignorepat_free(ip);
6863  ast_unlock_context(con);
6864  return 0;
6865  }
6866  }
6867 
6868  ast_unlock_context(con);
6869  errno = EINVAL;
6870  return -1;
6871 }
struct ast_ignorepats ignorepats
Definition: pbx.c:291
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8530
const char * ast_get_ignorepat_registrar(const struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:47
void ignorepat_free(struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:77
#define AST_VECTOR_REMOVE_ORDERED(vec, idx)
Remove an element from a vector by index while maintaining order.
Definition: vector.h:448
const char * ast_get_ignorepat_name(const struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:42
int ast_context_ignorepats_count(const struct ast_context *con)
Definition: pbx.c:8740
ast_ignorepat: Ignore patterns in dial plan
Definition: pbx_ignorepat.c:37
int errno
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition: pbx.c:8520
static char * registrar
Definition: pbx_ael.c:78
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682

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

References ast_context_remove_include2(), ast_unlock_contexts(), c, and find_context_locked().

Referenced by handle_cli_dialplan_remove_include().

4841 {
4842  int ret = -1;
4843  struct ast_context *c;
4844 
4846  if (c) {
4847  /* found, remove include from this context ... */
4848  ret = ast_context_remove_include2(c, include, registrar);
4850  }
4851  return ret;
4852 }
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.
Definition: pbx.c:4863
static struct test_val c
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
static char * registrar
Definition: pbx_ael.c:78
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4818
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

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

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(), and ast_context::includes.

Referenced by ast_context_remove_include().

4864 {
4865  int ret = -1;
4866  int idx;
4867 
4868  ast_wrlock_context(con);
4869 
4870  /* find our include */
4871  for (idx = 0; idx < ast_context_includes_count(con); idx++) {
4872  struct ast_include *i = AST_VECTOR_GET(&con->includes, idx);
4873 
4874  if (!strcmp(ast_get_include_name(i), include) &&
4875  (!registrar || !strcmp(ast_get_include_registrar(i), registrar))) {
4876 
4877  /* remove from list */
4878  ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
4879  AST_VECTOR_REMOVE_ORDERED(&con->includes, idx);
4880 
4881  /* free include and return */
4882  include_free(i);
4883  ret = 0;
4884  break;
4885  }
4886  }
4887 
4888  ast_unlock_context(con);
4889 
4890  return ret;
4891 }
ast_include: include= support in extensions.conf
Definition: pbx_include.c:37
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8530
void include_free(struct ast_include *inc)
Definition: pbx_include.c:106
const char * ast_get_include_registrar(const struct ast_include *i)
Definition: pbx_include.c:60
#define ast_verb(level,...)
Definition: logger.h:463
#define AST_VECTOR_REMOVE_ORDERED(vec, idx)
Remove an element from a vector by index while maintaining order.
Definition: vector.h:448
struct ast_includes includes
Definition: pbx.c:290
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition: pbx.c:8520
static char * registrar
Definition: pbx_ael.c:78
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
const char * ast_get_include_name(const struct ast_include *include)
Definition: pbx_include.c:50
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
int ast_context_includes_count(const struct ast_context *con)
Definition: pbx.c:8697

◆ 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 rigt context structure, leave context list locked and call ast_context_remove_switch2 which removes switch, unlock contexts list and return ...

Definition at line 4898 of file pbx.c.

References ast_context_remove_switch2(), ast_unlock_contexts(), c, and find_context_locked().

4899 {
4900  int ret = -1; /* default error return */
4901  struct ast_context *c;
4902 
4904  if (c) {
4905  /* remove switch from this context ... */
4906  ret = ast_context_remove_switch2(c, sw, data, registrar);
4908  }
4909  return ret;
4910 }
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:4920
static struct test_val c
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
static char * registrar
Definition: pbx_ael.c:78
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4818
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

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

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

Referenced by ast_context_remove_switch().

4921 {
4922  int idx;
4923  int ret = -1;
4924 
4925  ast_wrlock_context(con);
4926 
4927  /* walk switches */
4928  for (idx = 0; idx < ast_context_switches_count(con); idx++) {
4929  struct ast_sw *i = AST_VECTOR_GET(&con->alts, idx);
4930 
4931  if (!strcmp(ast_get_switch_name(i), sw) &&
4932  !strcmp(ast_get_switch_data(i), data) &&
4933  (!registrar || !strcmp(ast_get_switch_registrar(i), registrar))) {
4934 
4935  /* found, remove from list */
4936  ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
4937  AST_VECTOR_REMOVE_ORDERED(&con->alts, idx);
4938 
4939  /* free switch and return */
4940  sw_free(i);
4941  ret = 0;
4942  break;
4943  }
4944  }
4945 
4946  ast_unlock_context(con);
4947 
4948  return ret;
4949 }
const char * ast_get_switch_name(const struct ast_sw *sw)
Definition: pbx_sw.c:48
const char * ast_get_switch_registrar(const struct ast_sw *sw)
Definition: pbx_sw.c:63
int ast_context_switches_count(const struct ast_context *con)
Definition: pbx.c:8652
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8530
#define ast_verb(level,...)
Definition: logger.h:463
ast_sw: Switch statement in extensions.conf
Definition: pbx_sw.c:37
const char * data
Definition: pbx_sw.c:42
#define AST_VECTOR_REMOVE_ORDERED(vec, idx)
Remove an element from a vector by index while maintaining order.
Definition: vector.h:448
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition: pbx.c:8520
static char * registrar
Definition: pbx_ael.c:78
const char * ast_get_switch_data(const struct ast_sw *sw)
Definition: pbx_sw.c:53
void sw_free(struct ast_sw *sw)
Definition: pbx_sw.c:101
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
struct ast_sws alts
Definition: pbx.c:292

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

References __ast_context_destroy(), ast_context::autohints, enabled, and ast_exten::registrar.

Referenced by pbx_load_config().

6273 {
6274  con->autohints = enabled;
6275 }
int autohints
Definition: pbx.c:295
static int enabled
Definition: dnsmgr.c:91

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

Definition at line 8657 of file pbx.c.

References ast_context::alts, and AST_VECTOR_GET.

Referenced by ast_context_add_switch2(), ast_walk_context_switches(), context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), and show_dialplan_helper().

8658 {
8659  return AST_VECTOR_GET(&con->alts, idx);
8660 }
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
struct ast_sws alts
Definition: pbx.c:292

◆ ast_context_unlockmacro()

int ast_context_unlockmacro ( const char *  context)

Unlocks the macrolock in the given context.

Note
This function locks contexts list by &conlist, searches for the right context structure, and unlocks the macrolock mutex in that context. macrolock is used to limit a macro to be executed by one call at a time.
Parameters
contextThe context

Definition at line 5184 of file pbx.c.

References ast_mutex_unlock, ast_unlock_contexts(), c, find_context_locked(), and ast_context::macrolock.

Referenced by _macro_exec().

5185 {
5186  struct ast_context *c;
5187  int ret = -1;
5188 
5190  if (c) {
5192 
5193  /* if we found context, unlock macrolock */
5194  ret = ast_mutex_unlock(&c->macrolock);
5195  }
5196 
5197  return ret;
5198 }
static struct test_val c
ast_mutex_t macrolock
Definition: pbx.c:296
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4818
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
#define ast_mutex_unlock(a)
Definition: lock.h:188

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

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

8751 {
8752  int idx;
8753  int res = 0;
8754 
8755  for (idx = 0; idx < ast_context_includes_count(con); idx++) {
8756  const struct ast_include *inc = ast_context_includes_get(con, idx);
8757 
8758  if (ast_context_find(include_rname(inc))) {
8759  continue;
8760  }
8761 
8762  res = -1;
8763  ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
8764  ast_get_context_name(con), include_rname(inc));
8765  break;
8766  }
8767 
8768  return res;
8769 }
ast_include: include= support in extensions.conf
Definition: pbx_include.c:37
const char * include_rname(const struct ast_include *inc)
Definition: pbx_include.c:55
#define LOG_WARNING
Definition: logger.h:274
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: pbx.c:2443
#define ast_log
Definition: astobj2.c:42
const struct ast_include * ast_context_includes_get(const struct ast_context *con, int idx)
Definition: pbx.c:8702
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
int ast_context_includes_count(const struct ast_context *con)
Definition: pbx.c:8697

◆ ast_devstate_to_extenstate()

enum ast_extension_states ast_devstate_to_extenstate ( enum ast_device_state  devstate)

Map devstate to an extension state.

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

Definition at line 3006 of file pbx.c.

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

3007 {
3008  switch (devstate) {
3009  case AST_DEVICE_ONHOLD:
3010  return AST_EXTENSION_ONHOLD;
3011  case AST_DEVICE_BUSY:
3012  return AST_EXTENSION_BUSY;
3013  case AST_DEVICE_UNKNOWN:
3014  return AST_EXTENSION_NOT_INUSE;
3016  case AST_DEVICE_INVALID:
3018  case AST_DEVICE_RINGINUSE:
3020  case AST_DEVICE_RINGING:
3021  return AST_EXTENSION_RINGING;
3022  case AST_DEVICE_INUSE:
3023  return AST_EXTENSION_INUSE;
3024  case AST_DEVICE_NOT_INUSE:
3025  return AST_EXTENSION_NOT_INUSE;
3026  case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
3027  break;
3028  }
3029 
3030  return AST_EXTENSION_NOT_INUSE;
3031 }

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

References E_MATCH, NULL, and pbx_extension_helper().

Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), action_originate(), add_to_regcontext(), analog_ss_thread(), ast_app_dtget(), ast_bridge_setup_after_goto(), ast_pbx_outgoing_exten_predial(), ast_sip_persistent_endpoint_update_state(), cb_events(), chan_pjsip_cng_tone_detected(), cli_console_dial(), comeback_goto(), conf_run(), console_dial(), dahdi_handle_dtmf(), dial_exec_full(), dialplan_has_destination_cb(), disa_exec(), dp_lookup(), dundi_lookup_local(), fax_detect_framehook(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_clear_alarms(), handle_gosub(), isexten_function_read(), jingle_new(), join_conference_bridge(), key_dial_page(), leave_voicemail(), local_call(), local_devicestate(), loopback_exists(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmf(), new_subscribe(), onModeChanged(), ooh323_rtp_read(), options_on_rx_request(), pbx_builtin_waitexten(), phone_check_exception(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), refer_incoming_attended_request(), refer_incoming_blind_request(), register_peer_exten(), setsubstate(), show_debug_helper(), sip_new(), sip_read(), skinny_dialer(), socket_process_helper(), try_calling(), vm_authenticate(), and waitstream_core().

4180 {
4181  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
4182 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define NULL
Definition: resample.c:96
static int priority
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
The return value depends on the action:
Definition: pbx.c:2875

◆ ast_explicit_goto()

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

Definition at line 6987 of file pbx.c.

References ast_channel_context_set(), ast_channel_exten_set(), ast_channel_flags(), ast_channel_lock, ast_channel_priority_set(), ast_channel_unlock, AST_FLAG_IN_AUTOLOOP, ast_strlen_zero, ast_test_flag, and ast_exten::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().

6988 {
6989  if (!chan)
6990  return -1;
6991 
6992  ast_channel_lock(chan);
6993 
6994  if (!ast_strlen_zero(context))
6996  if (!ast_strlen_zero(exten))
6998  if (priority > -1) {
6999  /* see flag description in channel.h for explanation */
7001  --priority;
7002  }
7004  }
7005 
7006  ast_channel_unlock(chan);
7007 
7008  return 0;
7009 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int priority
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
void ast_channel_priority_set(struct ast_channel *chan, int value)

◆ ast_extension_close()

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

Definition at line 2418 of file pbx.c.

References ast_log, E_CANMATCH, E_MATCHMORE, extension_match_core(), and LOG_WARNING.

Referenced by lua_find_extension(), and realtime_switch_common().

2419 {
2420  if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
2421  ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
2422  return extension_match_core(pattern, data, needmore);
2423 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
Definition: pbx.c:2400

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

References ext_cmp().

Referenced by lua_extension_cmp().

2184 {
2185  int cmp;
2186 
2187  cmp = ext_cmp(a, b);
2188  if (cmp < 0) {
2189  return -1;
2190  }
2191  if (cmp > 0) {
2192  return 1;
2193  }
2194  return 0;
2195 }
static int ext_cmp(const char *left, const char *right)
Definition: pbx.c:2126
static struct test_val b
static struct test_val a

◆ ast_extension_match()

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

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

References E_MATCH, and extension_match_core().

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

2414 {
2415  return extension_match_core(pattern, data, E_MATCH);
2416 }
static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
Definition: pbx.c:2400

◆ ast_extension_state()

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

Check extension state for an extension by using hint.

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

Definition at line 3170 of file pbx.c.

References internal_extension_state_extended(), and NULL.

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

3171 {
3173 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static int internal_extension_state_extended(struct ast_channel *c, const char *context, const char *exten, struct ao2_container *device_state_info)
Definition: pbx.c:3141
#define NULL
Definition: resample.c:96
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ ast_extension_state2()

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

Check state of extension by using hints.

Definition at line 3113 of file pbx.c.

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

Referenced by ast_add_hint(), and internal_extension_state_extended().

3114 {
3115  struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
3116 
3117  if (!e || !hint_app) {
3118  return -1;
3119  }
3120 
3121  ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e));
3122  return ast_extension_state3(hint_app, device_state_info);
3123 }
static struct ast_threadstorage extensionstate_buf
Definition: pbx.c:229
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:1065
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static int ast_extension_state3(struct ast_str *hint_app, struct ao2_container *device_state_info)
Definition: pbx.c:3081
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8596
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:861

◆ ast_extension_state2str()

const char* ast_extension_state2str ( int  extension_state)

Return extension_state as string.

Return string representation of the state of an extension.

Definition at line 3126 of file pbx.c.

References ARRAY_LEN, extension_states, and cfextension_states::text.

Referenced by action_extensionstate(), action_extensionstatelist(), AST_TEST_DEFINE(), exten_state_publisher_state_cb(), extensionstate_update(), handle_request_subscribe(), handle_show_device2extenstate(), handle_show_hint(), handle_show_hints(), manager_state_cb(), show_channels_cb(), skinny_extensionstate_cb(), and to_ami().

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

◆ ast_extension_state3()

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

Definition at line 3081 of file pbx.c.

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

Referenced by ast_extension_state2(), and device_state_notify_callbacks().

3082 {
3083  char *cur;
3084  char *rest;
3085  struct ast_devstate_aggregate agg;
3086 
3087  /* One or more devices separated with a & character */
3088  rest = parse_hint_device(hint_app);
3089 
3091  while ((cur = strsep(&rest, "&"))) {
3093 
3094  ast_devstate_aggregate_add(&agg, state);
3095  if (device_state_info) {
3096  struct ast_device_state_info *obj;
3097 
3098  obj = ao2_alloc_options(sizeof(*obj) + strlen(cur), device_state_info_dt, AO2_ALLOC_OPT_LOCK_NOLOCK);
3099  /* if failed we cannot add this device */
3100  if (obj) {
3101  obj->device_state = state;
3102  strcpy(obj->device_name, cur);
3103  ao2_link(device_state_info, obj);
3104  ao2_ref(obj, -1);
3105  }
3106  }
3107  }
3108 
3110 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
ast_device_state
Device States.
Definition: devicestate.h:52
char device_name[1]
Definition: pbx.h:99
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
enum ast_device_state ast_devstate_aggregate_result(struct ast_devstate_aggregate *agg)
Get the aggregate device state result.
Definition: devicestate.c:663
static void device_state_info_dt(void *obj)
Definition: pbx.c:3069
#define ao2_ref(o, delta)
Definition: astobj2.h:464
enum ast_device_state device_state
Definition: pbx.h:97
void ast_devstate_aggregate_add(struct ast_devstate_aggregate *agg, enum ast_device_state state)
Add a device state to the aggregate device state.
Definition: devicestate.c:636
void ast_devstate_aggregate_init(struct ast_devstate_aggregate *agg)
Initialize aggregate device state.
Definition: devicestate.c:630
enum ast_extension_states ast_devstate_to_extenstate(enum ast_device_state devstate)
Map devstate to an extension state.
Definition: pbx.c:3006
char * strsep(char **str, const char *delims)
static char * parse_hint_device(struct ast_str *hint_args)
Definition: pbx.c:3056
You shouldn&#39;t care about the contents of this struct.
Definition: devicestate.h:230
#define ao2_link(container, obj)
Definition: astobj2.h:1549

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

References extension_state_add_destroy(), and NULL.

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

3827 {
3828  return extension_state_add_destroy(context, exten, change_cb, NULL, data, 0);
3829 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define NULL
Definition: resample.c:96
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:3729
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

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

References extension_state_add_destroy().

3821 {
3822  return extension_state_add_destroy(context, exten, change_cb, destroy_cb, data, 0);
3823 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
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:3729
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

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

References extension_state_add_destroy().

Referenced by handle_request_subscribe(), and subscription_established().

3833 {
3834  return extension_state_add_destroy(context, exten, change_cb, destroy_cb, data, 1);
3835 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
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:3729
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

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

References extension_state_add_destroy(), and NULL.

3839 {
3840  return extension_state_add_destroy(context, exten, change_cb, NULL, data, 1);
3841 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define NULL
Definition: resample.c:96
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:3729
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

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

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

Referenced by destroy_queue_member_cb(), dialog_unlink_all(), handle_request_subscribe(), skinny_session_cleanup(), subscription_shutdown(), and unload_module().

3859 {
3860  struct ast_state_cb *p_cur;
3861  int ret = -1;
3862 
3863  if (!id) { /* id == 0 is a callback without extension */
3864  if (!change_cb) {
3865  return ret;
3866  }
3868  if (p_cur) {
3869  ret = 0;
3870  ao2_ref(p_cur, -1);
3871  }
3872  } else { /* callback with extension, find the callback based on ID */
3873  struct ast_hint *hint;
3874 
3875  ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
3876  hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
3877  if (hint) {
3878  p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
3879  if (p_cur) {
3880  ret = 0;
3881  ao2_ref(p_cur, -1);
3882  }
3883  ao2_ref(hint, -1);
3884  }
3885  ao2_unlock(hints);
3886  }
3887 
3888  return ret;
3889 }
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
ast_state_cb: An extension state notify register item
Definition: pbx.c:301
#define ao2_unlock(a)
Definition: astobj2.h:730
ast_state_cb_type change_cb
Definition: pbx.c:309
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
Structure for dial plan hints.
Definition: pbx.c:324
struct ao2_container * callbacks
Definition: pbx.c:332
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static int find_hint_by_cb_id(void *obj, void *arg, int flags)
Find Hint by callback id.
Definition: pbx.c:3844
static struct ao2_container * statecbs
Definition: pbx.c:803

◆ ast_extension_state_extended()

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

Check extended extension state for an extension by using hint.

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

Definition at line 3176 of file pbx.c.

References alloc_device_state_info(), ao2_ref, container, get_device_state_causing_channels(), internal_extension_state_extended(), and NULL.

Referenced by exten_state_data_alloc(), and handle_request_subscribe().

3178 {
3179  struct ao2_container *container = NULL;
3180  int ret;
3181 
3182  if (device_state_info) {
3183  container = alloc_device_state_info();
3184  }
3185 
3186  ret = internal_extension_state_extended(c, context, exten, container);
3187  if (ret < 0 && container) {
3188  ao2_ref(container, -1);
3189  container = NULL;
3190  }
3191 
3192  if (device_state_info) {
3194  *device_state_info = container;
3195  }
3196 
3197  return ret;
3198 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static struct ao2_container * alloc_device_state_info(void)
Definition: pbx.c:3076
static int internal_extension_state_extended(struct ast_channel *c, const char *context, const char *exten, struct ao2_container *device_state_info)
Definition: pbx.c:3141
#define NULL
Definition: resample.c:96
static void get_device_state_causing_channels(struct ao2_container *c)
Definition: pbx.c:3296
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ao2_container * container
Definition: res_fax.c:502
Generic container type.
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

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

References E_FINDLABEL, NULL, and pbx_extension_helper().

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

4185 {
4186  return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
4187 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define NULL
Definition: resample.c:96
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
The return value depends on the action:
Definition: pbx.c:2875

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

References E_FINDLABEL, NULL, and pbx_extension_helper().

Referenced by pbx_load_config().

4190 {
4191  return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
4192 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define NULL
Definition: resample.c:96
static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
The return value depends on the action:
Definition: pbx.c:2875

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

References NULL, and ast_context::registrar.

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

8567 {
8568  return c ? c->registrar : NULL;
8569 }
#define NULL
Definition: resample.c:96
char * registrar
Definition: pbx.c:293

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

Definition at line 8601 of file pbx.c.

References ast_exten::data, and NULL.

Referenced by _macro_exec(), add_extension(), ast_get_hint(), ast_str_get_hint(), get_extension_data(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), parking_blind_transfer_park(), and print_ext().

8602 {
8603  return e ? e->data : NULL;
8604 }
#define NULL
Definition: resample.c:96
void * data
Definition: pbx.c:248

◆ ast_get_extension_cidmatch()

const char* ast_get_extension_cidmatch ( struct ast_exten e)

Definition at line 8591 of file pbx.c.

References ast_exten::cidmatch_display, and NULL.

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

8592 {
8593  return e ? e->cidmatch_display : NULL;
8594 }
#define NULL
Definition: resample.c:96
const char * cidmatch_display
Definition: pbx.c:242

◆ ast_get_extension_context()

struct ast_context* ast_get_extension_context ( struct ast_exten exten)

Definition at line 8543 of file pbx.c.

References NULL, and ast_exten::parent.

Referenced by ast_add_hint(), ast_change_hint(), ast_remove_hint(), device_state_notify_callbacks(), extension_is_compatible(), handle_show_hint(), handle_show_hints(), presence_state_notify_callbacks(), print_hintdevices_key(), and print_hints_key().

8544 {
8545  return exten ? exten->parent : NULL;
8546 }
#define NULL
Definition: resample.c:96
struct ast_context * parent
Definition: pbx.c:245

◆ ast_get_extension_label()

const char* ast_get_extension_label ( struct ast_exten exten)

Definition at line 8553 of file pbx.c.

References ast_exten::label, and NULL.

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

8554 {
8555  return exten ? exten->label : NULL;
8556 }
const char * label
Definition: pbx.c:244
#define NULL
Definition: resample.c:96

◆ ast_get_extension_matchcid()

int ast_get_extension_matchcid ( struct ast_exten e)

Definition at line 8586 of file pbx.c.

References ast_exten::matchcid.

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

8587 {
8588  return e ? e->matchcid : 0;
8589 }
int matchcid
Definition: pbx.c:240

◆ ast_get_extension_name()

const char* ast_get_extension_name ( struct ast_exten exten)

◆ ast_get_extension_priority()

int ast_get_extension_priority ( struct ast_exten exten)

Definition at line 8558 of file pbx.c.

References ast_exten::priority.

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

8559 {
8560  return exten ? exten->priority : -1;
8561 }
int priority
Definition: pbx.c:243

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

References NULL, and ast_exten::registrar_file.

Referenced by show_dialplan_helper_extension_output().

8577 {
8578  return e ? e->registrar_file : NULL;
8579 }
#define NULL
Definition: resample.c:96
const char * registrar_file
Definition: pbx.c:254

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

References ast_exten::registrar_line.

Referenced by show_dialplan_helper_extension_output().

8582 {
8583  return e ? e->registrar_line : 0;
8584 }
int registrar_line
Definition: pbx.c:255

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

References ast_copy_string(), ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), and tmp().

Referenced by action_extensionstate(), device_state_cb(), get_cid_name(), get_destination(), hint_read(), manager_state_cb(), skinny_extensionstate_cb(), and state_notify_build_xml().

4142 {
4143  struct ast_exten *e = ast_hint_extension(c, context, exten);
4144 
4145  if (e) {
4146  if (hint)
4147  ast_copy_string(hint, ast_get_extension_app(e), hintsize);
4148  if (name) {
4149  const char *tmp = ast_get_extension_app_data(e);
4150  if (tmp)
4151  ast_copy_string(name, tmp, namesize);
4152  }
4153  return -1;
4154  }
4155  return 0;
4156 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
static int tmp()
Definition: bt_open.c:389
void * ast_get_extension_app_data(struct ast_exten *e)
Definition: pbx.c:8601
static struct ast_exten * ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
Definition: pbx.c:2997
static const char name[]
Definition: cdr_mysql.c:74
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8596
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

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

References __ast_goto_if_exists().

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

8794 {
8795  return __ast_goto_if_exists(chan, context, exten, priority, 0);
8796 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static int __ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
Definition: pbx.c:8772
static int priority
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ ast_hashtab_compare_contexts()

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

hashtable functions for contexts

Definition at line 683 of file pbx.c.

References bc, and ast_context::name.

Referenced by ast_context_find_or_create().

684 {
685  const struct ast_context *ac = ah_a;
686  const struct ast_context *bc = ah_b;
687  if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
688  return 1;
689  /* assume context names are registered in a string table! */
690  return strcmp(ac->name, bc->name);
691 }
#define bc
char name[0]
Definition: pbx.c:297
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

◆ ast_hashtab_hash_contexts()

unsigned int ast_hashtab_hash_contexts ( const void *  obj)

Definition at line 735 of file pbx.c.

References ast_hashtab_hash_string(), and ast_context::name.

Referenced by ast_context_find_or_create().

736 {
737  const struct ast_context *ac = obj;
738  return ast_hashtab_hash_string(ac->name);
739 }
char name[0]
Definition: pbx.c:297
unsigned int ast_hashtab_hash_string(const void *obj)
Hashes a string to a number.
Definition: hashtab.c:153
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

◆ ast_hint_extension()

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

Definition at line 2997 of file pbx.c.

References ast_hint_extension_nolock(), ast_rdlock_contexts(), and ast_unlock_contexts().

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

2998 {
2999  struct ast_exten *e;
3003  return e;
3004 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8507
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
static struct ast_exten * ast_hint_extension_nolock(struct ast_channel *c, const char *context, const char *exten)
Find hint for given extension in context.
Definition: pbx.c:2991
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ ast_hint_extension_nolock()

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

Find hint for given extension in context.

Definition at line 2991 of file pbx.c.

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

Referenced by ast_hint_extension(), and ast_merge_contexts_and_delete().

2992 {
2993  struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
2994  return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
2995 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define NULL
Definition: resample.c:96
#define PRIORITY_HINT
Definition: pbx.h:54
int stacklen
Definition: extconf.h:238
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:2485
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ ast_hint_presence_state()

int ast_hint_presence_state ( struct ast_channel c,
const char *  context,
const char *  exten,
char **  subtype,
char **  message 
)

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

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

Definition at line 3226 of file pbx.c.

References ao2_lock, ao2_unlock, ast_exten::app, ast_add_extension(), ast_free_ptr(), ast_hint_extension(), ast_strdup, 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(), and handle_request_subscribe().

3227 {
3228  struct ast_exten *e;
3229 
3230  if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */
3231  return -1; /* No hint, return -1 */
3232  }
3233 
3234  if (e->exten[0] == '_') {
3235  /* Create this hint on-the-fly */
3236  ao2_lock(hints);
3237  ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
3238  e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
3239  e->registrar);
3240  ao2_unlock(hints);
3241  if (!(e = ast_hint_extension(c, context, exten))) {
3242  /* Improbable, but not impossible */
3243  return -1;
3244  }
3245  }
3246 
3247  return extension_presence_state_helper(e, subtype, message);
3248 }
const char * label
Definition: pbx.c:244
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
static int extension_presence_state_helper(struct ast_exten *e, char **subtype, char **message)
Definition: pbx.c:3200
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1771
const char * registrar
Definition: pbx.c:253
int matchcid
Definition: pbx.c:240
int priority
Definition: pbx.c:243
static struct ast_exten * ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
Definition: pbx.c:2997
#define ao2_lock(a)
Definition: astobj2.h:718
char * exten
Definition: pbx.c:238
char name[0]
Definition: pbx.c:297
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:6970
const char * cidmatch
Definition: pbx.c:241
const char * app
Definition: pbx.c:246
struct ast_context * parent
Definition: pbx.c:245
void * data
Definition: pbx.c:248
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

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

References ast_context_find(), ast_context_ignorepats_count(), ast_context_ignorepats_get(), ast_extension_match(), ast_get_ignorepat_name(), ast_rdlock_contexts(), and ast_unlock_contexts().

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

6922 {
6923  int ret = 0;
6924  struct ast_context *con;
6925 
6927  con = ast_context_find(context);
6928  if (con) {
6929  int idx;
6930 
6931  for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6932  const struct ast_ignorepat *pat = ast_context_ignorepats_get(con, idx);
6933 
6935  ret = 1;
6936  break;
6937  }
6938  }
6939  }
6941 
6942  return ret;
6943 }
const char pattern[0]
Definition: pbx_ignorepat.c:39
const struct ast_ignorepat * ast_context_ignorepats_get(const struct ast_context *con, int idx)
Definition: pbx.c:8745
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: pbx.c:2443
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8507
const char * ast_get_ignorepat_name(const struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:42
int ast_context_ignorepats_count(const struct ast_context *con)
Definition: pbx.c:8740
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
ast_ignorepat: Ignore patterns in dial plan
Definition: pbx_ignorepat.c:37
int ast_extension_match(const char *pattern, const char *data)
Determine if a given extension matches a given pattern (in NXX format)
Definition: pbx.c:2413
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

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

References E_MATCHMORE, NULL, and pbx_extension_helper().

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

4200 {
4201  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
4202 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define NULL
Definition: resample.c:96
static int priority
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
The return value depends on the action:
Definition: pbx.c:2875

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

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

6469 {
6470  double ft;
6471  struct ast_context *tmp;
6472  struct ast_context *oldcontextslist;
6473  struct ast_hashtab *oldtable;
6474  struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
6475  struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
6476  struct store_hint *saved_hint;
6477  struct ast_hint *hint;
6478  struct ast_exten *exten;
6479  int length;
6480  struct ast_state_cb *thiscb;
6481  struct ast_hashtab_iter *iter;
6482  struct ao2_iterator i;
6483  int ctx_count = 0;
6484  struct timeval begintime;
6485  struct timeval writelocktime;
6486  struct timeval endlocktime;
6487  struct timeval enddeltime;
6488 
6489  /*
6490  * It is very important that this function hold the hints
6491  * container lock _and_ the conlock during its operation; not
6492  * only do we need to ensure that the list of contexts and
6493  * extensions does not change, but also that no hint callbacks
6494  * (watchers) are added or removed during the merge/delete
6495  * process
6496  *
6497  * In addition, the locks _must_ be taken in this order, because
6498  * there are already other code paths that use this order
6499  */
6500 
6501  begintime = ast_tvnow();
6502  ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
6504 
6505  if (!contexts_table) {
6506  /* Create any autohint contexts */
6508 
6509  /* Well, that's odd. There are no contexts. */
6510  contexts_table = exttable;
6511  contexts = *extcontexts;
6514  return;
6515  }
6516 
6518  while ((tmp = ast_hashtab_next(iter))) {
6519  ++ctx_count;
6520  context_merge(extcontexts, exttable, tmp, registrar);
6521  }
6523 
6524  ao2_lock(hints);
6525  writelocktime = ast_tvnow();
6526 
6527  /* preserve all watchers for hints */
6529  for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
6530  if (ao2_container_count(hint->callbacks)) {
6531  size_t exten_len;
6532 
6533  ao2_lock(hint);
6534  if (!hint->exten) {
6535  /* The extension has already been destroyed. (Should never happen here) */
6536  ao2_unlock(hint);
6537  continue;
6538  }
6539 
6540  exten_len = strlen(hint->exten->exten) + 1;
6541  length = exten_len + strlen(hint->exten->parent->name) + 1
6542  + sizeof(*saved_hint);
6543  if (!(saved_hint = ast_calloc(1, length))) {
6544  ao2_unlock(hint);
6545  continue;
6546  }
6547 
6548  /* This removes all the callbacks from the hint into saved_hint. */
6549  while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
6550  AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
6551  /*
6552  * We intentionally do not unref thiscb to account for the
6553  * non-ao2 reference in saved_hint->callbacks
6554  */
6555  }
6556 
6557  saved_hint->laststate = hint->laststate;
6558  saved_hint->context = saved_hint->data;
6559  strcpy(saved_hint->data, hint->exten->parent->name);
6560  saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
6561  ast_copy_string(saved_hint->exten, hint->exten->exten, exten_len);
6562  if (hint->last_presence_subtype) {
6563  saved_hint->last_presence_subtype = ast_strdup(hint->last_presence_subtype);
6564  }
6565  if (hint->last_presence_message) {
6566  saved_hint->last_presence_message = ast_strdup(hint->last_presence_message);
6567  }
6568  saved_hint->last_presence_state = hint->last_presence_state;
6569  ao2_unlock(hint);
6570  AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
6571  }
6572  }
6574 
6575  /* save the old table and list */
6576  oldtable = contexts_table;
6577  oldcontextslist = contexts;
6578 
6579  /* move in the new table and list */
6580  contexts_table = exttable;
6581  contexts = *extcontexts;
6582 
6583  /*
6584  * Restore the watchers for hints that can be found; notify
6585  * those that cannot be restored.
6586  */
6587  while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
6588  struct pbx_find_info q = { .stacklen = 0 };
6589 
6590  exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
6591  PRIORITY_HINT, NULL, "", E_MATCH);
6592  /*
6593  * If this is a pattern, dynamically create a new extension for this
6594  * particular match. Note that this will only happen once for each
6595  * individual extension, because the pattern will no longer match first.
6596  */
6597  if (exten && exten->exten[0] == '_') {
6598  ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
6599  PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
6600  exten->registrar);
6601  /* rwlocks are not recursive locks */
6602  exten = ast_hint_extension_nolock(NULL, saved_hint->context,
6603  saved_hint->exten);
6604  }
6605 
6606  /* Find the hint in the hints container */
6607  hint = exten ? ao2_find(hints, exten, 0) : NULL;
6608  if (!hint) {
6609  /*
6610  * Notify watchers of this removed hint later when we aren't
6611  * encumberd by so many locks.
6612  */
6613  AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
6614  } else {
6615  ao2_lock(hint);
6616  while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
6617  ao2_link(hint->callbacks, thiscb);
6618  /* Ref that we added when putting into saved_hint->callbacks */
6619  ao2_ref(thiscb, -1);
6620  }
6621  hint->laststate = saved_hint->laststate;
6622  hint->last_presence_state = saved_hint->last_presence_state;
6623  hint->last_presence_subtype = saved_hint->last_presence_subtype;
6624  hint->last_presence_message = saved_hint->last_presence_message;
6625  ao2_unlock(hint);
6626  ao2_ref(hint, -1);
6627  /*
6628  * The free of saved_hint->last_presence_subtype and
6629  * saved_hint->last_presence_message is not necessary here.
6630  */
6631  ast_free(saved_hint);
6632  }
6633  }
6634 
6635  /* Create all applicable autohint contexts */
6637 
6638  ao2_unlock(hints);
6640 
6641  /*
6642  * Notify watchers of all removed hints with the same lock
6643  * environment as device_state_cb().
6644  */
6645  while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
6646  /* this hint has been removed, notify the watchers */
6647  while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
6649  saved_hint->context,
6650  saved_hint->exten,
6651  thiscb->data,
6653  NULL,
6654  NULL);
6655  /* Ref that we added when putting into saved_hint->callbacks */
6656  ao2_ref(thiscb, -1);
6657  }
6658  ast_free(saved_hint->last_presence_subtype);
6659  ast_free(saved_hint->last_presence_message);
6660  ast_free(saved_hint);
6661  }
6662 
6664  endlocktime = ast_tvnow();
6665 
6666  /*
6667  * The old list and hashtab no longer are relevant, delete them
6668  * while the rest of asterisk is now freely using the new stuff
6669  * instead.
6670  */
6671 
6672  ast_hashtab_destroy(oldtable, NULL);
6673 
6674  for (tmp = oldcontextslist; tmp; ) {
6675  struct ast_context *next; /* next starting point */
6676 
6677  next = tmp->next;
6679  tmp = next;
6680  }
6681  enddeltime = ast_tvnow();
6682 
6683  ft = ast_tvdiff_us(writelocktime, begintime);
6684  ft /= 1000000.0;
6685  ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
6686 
6687  ft = ast_tvdiff_us(endlocktime, writelocktime);
6688  ft /= 1000000.0;
6689  ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
6690 
6691  ft = ast_tvdiff_us(enddeltime, endlocktime);
6692  ft /= 1000000.0;
6693  ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
6694 
6695  ft = ast_tvdiff_us(enddeltime, begintime);
6696  ft /= 1000000.0;
6697  ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
6698  ast_verb(3, "%s successfully loaded %d contexts (enable debug for details).\n", registrar, ctx_count);
6699 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
static void __ast_internal_context_destroy(struct ast_context *con)
Definition: pbx.c:8050
void * data
Definition: pbx.c:305
static struct ast_hashtab * contexts_table
Definition: pbx.c:777
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
ast_state_cb: An extension state notify register item
Definition: pbx.c:301
static int tmp()
Definition: bt_open.c:389
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
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_mutex_lock(a)
Definition: lock.h:187
static ast_mutex_t context_merge_lock
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
Definition: pbx.c:790
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1771
#define ast_verb(level,...)
Definition: logger.h:463
const char * registrar
Definition: pbx.c:253
ast_state_cb_type change_cb
Definition: pbx.c:309
int last_presence_state
Definition: pbx.c:338
struct ast_context * next
Definition: pbx.c:289
#define ast_hashtab_start_traversal(tab)
Definition: hashtab.h:355
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8502
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
#define PRIORITY_HINT
Definition: pbx.h:54
void ast_hashtab_end_traversal(struct ast_hashtab_iter *it)
end the traversal, free the iterator, unlock if necc.
Definition: hashtab.c:674
struct ast_exten * exten
Hint extension.
Definition: pbx.c:331
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
Definition: pbx.c:6369
char * exten
Definition: pbx.c:238
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
int laststate
Definition: pbx.c:335
char name[0]
Definition: pbx.c:297
Structure for dial plan hints.
Definition: pbx.c:324
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
struct ao2_container * callbacks
Definition: pbx.c:332
an iterator for traversing the buckets
Definition: hashtab.h:105
static char * registrar
Definition: pbx_ael.c:78
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
int stacklen
Definition: extconf.h:238
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
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:6950
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
Definition: linkedlists.h:251
static void context_table_create_autohints(struct ast_hashtab *table)
Definition: pbx.c:6332
Assume that the ao2_container is already locked.
Definition: astobj2.h:1872
static struct ast_exten * ast_hint_extension_nolock(struct ast_channel *c, const char *context, const char *exten)
Find hint for given extension in context.
Definition: pbx.c:2991
const char * app
Definition: pbx.c:246
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
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:2485
static struct ast_context * contexts
Definition: pbx.c:776
Definition: search.h:40
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:78
struct ast_context * parent
Definition: pbx.c:245
char * last_presence_message
Definition: pbx.c:340
void * data
Definition: pbx.c:248
static int execute_state_callback(ast_state_cb_type cb, const char *context, const char *exten, void *data, enum ast_state_cb_update_reason reason, struct ast_hint *hint, struct ao2_container *device_state_info)
Definition: pbx.c:3250
char * last_presence_subtype
Definition: pbx.c:339
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ast_mutex_unlock(a)
Definition: lock.h:188
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 ao2_link(container, obj)
Definition: astobj2.h:1549

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

References pbx_parseable_goto().

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

8860 {
8861  return pbx_parseable_goto(chan, goto_string, 0);
8862 }
static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string, int async)
Definition: pbx.c:8803

◆ 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.
Returns
Nothing

Definition at line 4209 of file pbx.c.

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

4210 {
4211  int autoloopflag;
4212  int found;
4213  int spawn_error;
4214 
4215  ast_channel_lock(chan);
4216 
4217  /*
4218  * Make sure that the channel is marked as hungup since we are
4219  * going to run the h exten on it.
4220  */
4222 
4223  /* Set h exten location */
4224  if (context != ast_channel_context(chan)) {
4226  }
4227  ast_channel_exten_set(chan, "h");
4228  ast_channel_priority_set(chan, 1);
4229 
4230  /* Save autoloop flag */
4231  autoloopflag = ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
4233  ast_channel_unlock(chan);
4234 
4235  for (;;) {
4236  spawn_error = ast_spawn_extension(chan, ast_channel_context(chan),
4238  S_COR(ast_channel_caller(chan)->id.number.valid,
4239  ast_channel_caller(chan)->id.number.str, NULL), &found, 1);
4240 
4241  ast_channel_lock(chan);
4242  if (spawn_error) {
4243  /* The code after the loop needs the channel locked. */
4244  break;
4245  }
4247  ast_channel_unlock(chan);
4248  }
4249  if (found && spawn_error) {
4250  /* Something bad happened, or a hangup has been requested. */
4251  ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n",
4253  ast_channel_priority(chan), ast_channel_name(chan));
4254  ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n",
4256  ast_channel_priority(chan), ast_channel_name(chan));
4257  }
4258 
4259  /* An "h" exten has been run, so indicate that one has been run. */
4261 
4262  /* Restore autoloop flag */
4264  ast_channel_unlock(chan);
4265 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
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:4204
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define NULL
Definition: resample.c:96
int ast_channel_priority(const struct ast_channel *chan)
#define ast_verb(level,...)
Definition: logger.h:463
Number structure.
Definition: app_followme.c:154
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#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:85
const char * ast_channel_exten(const struct ast_channel *chan)
int ast_softhangup_nolock(struct ast_channel *chan, int reason)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2463
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
const char * ast_channel_name(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
void ast_channel_priority_set(struct ast_channel *chan, int value)

◆ ast_pbx_init()

int ast_pbx_init ( void  )

Provided by pbx.c

Definition at line 8982 of file pbx.c.

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(), HASH_EXTENHINT_SIZE, hint_cmp(), hint_hash(), hintdevice_cmp_multiple(), hintdevice_hash_cb(), NULL, pbx_shutdown(), print_autohint_key(), print_hintdevices_key(), print_hints_key(), print_statecbs_key(), STASIS_MESSAGE_TYPE_INIT, and statecbs_cmp().

Referenced by asterisk_daemon().

8983 {
8986  if (hints) {
8988  }
8991  if (hintdevices) {
8993  }
8994  /* This is protected by the context_and_merge lock */
8997  if (autohints) {
8999  }
9001  if (statecbs) {
9003  }
9004 
9006 
9007  if (STASIS_MESSAGE_TYPE_INIT(hint_change_message_type) != 0) {
9008  return -1;
9009  }
9010  if (STASIS_MESSAGE_TYPE_INIT(hint_remove_message_type) != 0) {
9011  return -1;
9012  }
9013 
9014  return (hints && hintdevices && autohints && statecbs) ? 0 : -1;
9015 }
static void print_autohint_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: pbx.c:8962
static int hint_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:8889
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1501
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1335
static struct ao2_container * hintdevices
Container for hint devices.
Definition: pbx.c:363
static int hint_hash(const void *obj, const int flags)
Definition: pbx.c:8869
static void print_statecbs_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: pbx.c:8972
#define NULL
Definition: resample.c:96
static int hintdevice_cmp_multiple(void *obj, void *arg, int flags)
Definition: pbx.c:421
static int statecbs_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:8897
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.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define HASH_EXTENHINT_SIZE
Definition: pbx.c:358
static void pbx_shutdown(void)
Definition: pbx.c:8909
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
static int autohint_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:474
static int autohint_hash_cb(const void *obj, const int flags)
Definition: pbx.c:453
static void print_hintdevices_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: pbx.c:8950
static struct ao2_container * statecbs
Definition: pbx.c:803
static int hintdevice_hash_cb(const void *obj, const int flags)
Definition: pbx.c:395
static void print_hints_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: pbx.c:8939
static struct ao2_container * autohints
Container for autohint contexts.
Definition: pbx.c:380

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

References ast_pbx_outgoing_app_predial(), and NULL.

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

8020 {
8021  return ast_pbx_outgoing_app_predial(type, cap, addr, timeout, app, appdata, reason, synchronous,
8022  cid_num, cid_name, vars, account, locked_channel, assignedids, NULL);
8023 }
static const char type[]
Definition: chan_ooh323.c:109
static int timeout
Definition: cdr_mysql.c:86
#define NULL
Definition: resample.c:96
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:164
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:165
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:8025
static const char app[]
Definition: app_mysql.c:62

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

References ast_strlen_zero, NULL, and pbx_outgoing_attempt().

Referenced by ast_pbx_outgoing_app(), and originate_exec().

8030 {
8031  if (reason) {
8032  *reason = 0;
8033  }
8034  if (locked_channel) {
8035  *locked_channel = NULL;
8036  }
8037  if (ast_strlen_zero(app)) {
8038  return -1;
8039  }
8040 
8041  return pbx_outgoing_attempt(type, cap, addr, timeout, NULL, NULL, 0, app, appdata,
8042  reason, synchronous, cid_num, cid_name, vars, account, locked_channel, 0,
8043  assignedids, predial_callee);
8044 }
static const char type[]
Definition: chan_ooh323.c:109
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:7755
static int timeout
Definition: cdr_mysql.c:86
#define NULL
Definition: resample.c:96
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:164
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:165
static const char app[]
Definition: app_mysql.c:62

◆ 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 exists then run a channel named OutgoingSpoolFailed at failed .
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 7951 of file pbx.c.

References ast_pbx_outgoing_exten_predial(), and NULL.

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

7956 {
7957  return ast_pbx_outgoing_exten_predial(type, cap, addr, timeout, context, exten, priority, reason,
7958  synchronous, cid_num, cid_name, vars, account, locked_channel, early_media, assignedids, NULL);
7959 }
static const char type[]
Definition: chan_ooh323.c:109
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static int timeout
Definition: cdr_mysql.c:86
#define NULL
Definition: resample.c:96
static int priority
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:164
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:165
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:7961
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

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

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, LOG_ERROR, NULL, pbx_builtin_setvar_helper(), and pbx_outgoing_attempt().

Referenced by ast_pbx_outgoing_exten(), and originate_exec().

7966 {
7967  int res;
7968  int my_reason;
7969 
7970  if (!reason) {
7971  reason = &my_reason;
7972  }
7973  *reason = 0;
7974  if (locked_channel) {
7975  *locked_channel = NULL;
7976  }
7977 
7978  res = pbx_outgoing_attempt(type, cap, addr, timeout, context, exten, priority,
7979  NULL, NULL, reason, synchronous, cid_num, cid_name, vars, account, locked_channel,
7980  early_media, assignedids, predial_callee);
7981 
7982  if (res < 0 /* Call failed to get connected for some reason. */
7983  && 0 < synchronous
7984  && ast_exists_extension(NULL, context, "failed", 1, NULL)) {
7985  struct ast_channel *failed;
7986 
7987  /* We do not have to worry about a locked_channel if dialing failed. */
7988  ast_assert(!locked_channel || !*locked_channel);
7989 
7990  /*!
7991  * \todo XXX Not good. The channel name is not unique if more than
7992  * one originate fails at a time.
7993  */
7994  failed = ast_channel_alloc(0, AST_STATE_DOWN, cid_num, cid_name, account,
7995  "failed", context, NULL, NULL, 0, "OutgoingSpoolFailed");
7996  if (failed) {
7997  char failed_reason[12];
7998 
7999  ast_set_variables(failed, vars);
8000  snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
8001  pbx_builtin_setvar_helper(failed, "REASON", failed_reason);
8002  ast_channel_unlock(failed);
8003 
8004  if (ast_pbx_run(failed)) {
8005  ast_log(LOG_ERROR, "Unable to run PBX on '%s'\n",
8006  ast_channel_name(failed));
8007  ast_hangup(failed);
8008  }
8009  }
8010  }
8011 
8012  return res;
8013 }
static const char type[]
Definition: chan_ooh323.c:109
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
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:7755
static int timeout
Definition: cdr_mysql.c:86
void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars)
adds a list of channel variables to a channel
Definition: channel.c:8217
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
static int priority
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:164
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4759
#define ast_log
Definition: astobj2.c:42
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:4179
#define LOG_ERROR
Definition: logger.h:285
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:165
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...
const char * ast_channel_name(const struct ast_channel *chan)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1259

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

References ast_pbx_run_args(), 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(), mgcp_ss(), pbx_outgoing_exec(), skinny_newcall(), and unistim_ss().

4760 {
4761  return ast_pbx_run_args(c, NULL);
4762 }
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:4739
#define NULL
Definition: resample.c:96

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

References __ast_pbx_run(), ast_log, AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_test_flag, 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().

4740 {
4741  enum ast_pbx_result res = AST_PBX_SUCCESS;
4742 
4744  ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
4745  return AST_PBX_FAILED;
4746  }
4747 
4748  if (increase_call_count(c)) {
4749  return AST_PBX_CALL_LIMIT;
4750  }
4751 
4752  res = __ast_pbx_run(c, args);
4753 
4755 
4756  return res;
4757 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
static void decrease_call_count(void)
Definition: pbx.c:4670
#define LOG_WARNING
Definition: logger.h:274
static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c, struct ast_pbx_args *args)
Definition: pbx.c:4310
#define ast_log
Definition: astobj2.c:42
static int increase_call_count(const struct ast_channel *c)
Increase call count for channel.
Definition: pbx.c:4621
ast_pbx_result
The result codes when starting the PBX on a channel with ast_pbx_start.
Definition: pbx.h:354
struct ast_flags ast_options
Definition: options.c:61

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

References ast_log, AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, ast_test_flag, decrease_call_count(), increase_call_count(), LOG_WARNING, NULL, and pbx_thread().

Referenced by alsa_new(), ast_async_goto(), ast_iax2_new(), bridge_failed_peer_goto(), console_new(), dahdi_new(), dial_exec_full(), do_monitor_headset(), generic_recall(), handle_request_invite(), handle_response_clip(), handle_response_cmgr(), jingle_action_session_initiate(), local_call(), mgcp_new(), nbs_new(), ooh323_new(), oss_new(), pbx_start_chan(), pbx_start_incoming_request(), phone_new(), skinny_new(), unistim_new(), and wait_for_digits().

4713 {
4714  pthread_t t;
4715 
4716  if (!c) {
4717  ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
4718  return AST_PBX_FAILED;
4719  }
4720 
4722  ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
4723  return AST_PBX_FAILED;
4724  }
4725 
4726  if (increase_call_count(c))
4727  return AST_PBX_CALL_LIMIT;
4728 
4729  /* Start a new thread, and get something handling this channel. */
4731  ast_log(LOG_WARNING, "Failed to create new channel thread\n");
4733  return AST_PBX_FAILED;
4734  }
4735 
4736  return AST_PBX_SUCCESS;
4737 }
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:563
#define ast_test_flag(p, flag)
Definition: utils.h:63
static void decrease_call_count(void)
Definition: pbx.c:4670
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
static int increase_call_count(const struct ast_channel *c)
Increase call count for channel.
Definition: pbx.c:4621
static void * pbx_thread(void *data)
Definition: pbx.c:4692
struct ast_flags ast_options
Definition: options.c:61

◆ ast_processed_calls()

int ast_processed_calls ( void  )

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

Definition at line 4769 of file pbx.c.

References totalcalls.

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

4770 {
4771  return totalcalls;
4772 }
static int totalcalls
Definition: pbx.c:774

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

References ast_rwlock_rdlock, and ast_context::lock.

Referenced by _macro_exec(), 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().

8526 {
8527  return ast_rwlock_rdlock(&con->lock);
8528 }
#define ast_rwlock_rdlock(a)
Definition: lock.h:233
ast_rwlock_t lock
Definition: pbx.c:285

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

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

3946 {
3947  /* Cleanup the Notifys if hint is removed */
3948  struct ast_hint *hint;
3949 
3950  if (!e) {
3951  return -1;
3952  }
3953 
3954  hint = ao2_find(hints, e, OBJ_UNLINK);
3955  if (!hint) {
3956  return -1;
3957  }
3958 
3959  remove_hintdevice(hint);
3960 
3961  /*
3962  * The extension is being destroyed so we must save some
3963  * information to notify that the extension is deactivated.
3964  */
3965  ao2_lock(hint);
3968  sizeof(hint->context_name));
3970  sizeof(hint->exten_name));
3971  hint->exten = NULL;
3972  ao2_unlock(hint);
3973 
3974  publish_hint_remove(hint);
3975 
3976  ao2_ref(hint, -1);
3977 
3978  return 0;
3979 }
struct ast_context * ast_get_extension_context(struct ast_exten *exten)
Definition: pbx.c:8543
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
static int publish_hint_remove(struct ast_hint *hint)
Publish a hint removed event.
Definition: pbx.c:3924
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_exten * exten
Hint extension.
Definition: pbx.c:331
char context_name[AST_MAX_CONTEXT]
Definition: pbx.c:342
Structure for dial plan hints.
Definition: pbx.c:324
static int remove_hintdevice(struct ast_hint *hint)
Definition: pbx.c:517
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
char exten_name[AST_MAX_EXTENSION]
Definition: pbx.c:343

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

References E_SPAWN, NULL, and pbx_extension_helper().

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

4205 {
4206  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
4207 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define NULL
Definition: resample.c:96
static int priority
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
The return value depends on the action:
Definition: pbx.c:2875

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

References ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), ast_str_set(), and tmp().

Referenced by ast_str_retrieve_variable().

4160 {
4161  struct ast_exten *e = ast_hint_extension(c, context, exten);
4162 
4163  if (!e) {
4164  return 0;
4165  }
4166 
4167  if (hint) {
4168  ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
4169  }
4170  if (name) {
4171  const char *tmp = ast_get_extension_app_data(e);
4172  if (tmp) {
4173  ast_str_set(name, namesize, "%s", tmp);
4174  }
4175  }
4176  return -1;
4177 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
static int tmp()
Definition: bt_open.c:389
void * ast_get_extension_app_data(struct ast_exten *e)
Definition: pbx.c:8601
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:1065
static struct ast_exten * ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
Definition: pbx.c:2997
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8596
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ ast_unlock_context()

int ast_unlock_context ( struct ast_context con)

◆ ast_unlock_contexts()

int ast_unlock_contexts ( void  )

Unlocks contexts.

Return values
0on success
-1on failure

Definition at line 8512 of file pbx.c.

References ast_mutex_unlock, and conlock.

Referenced by _macro_exec(), add_hints(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_destroy(), ast_context_destroy_by_name(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_ignore_pattern(), ast_merge_contexts_and_delete(), ast_unregister_application(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_context(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endif(), find_matching_endwhile(), get_extension_data(), handle_cli_dialplan_save(), manager_dialplan_extension_add(), manager_show_dialplan_helper(), parking_duration_callback(), parking_lot_cfg_create_extensions(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().

8513 {
8514  return ast_mutex_unlock(&conlock);
8515 }
static ast_mutex_t conlock
Lock for the ast_context list.
Definition: pbx.c:785
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ ast_walk_context_extensions()

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

Definition at line 8614 of file pbx.c.

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

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

8616 {
8617  if (!exten)
8618  return con ? con->root : NULL;
8619  else
8620  return exten->next;
8621 }
struct ast_exten * root
Definition: pbx.c:286
#define NULL
Definition: resample.c:96
struct ast_exten * next
Definition: pbx.c:256

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

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

8709 {
8710  if (!con) {
8711  return NULL;
8712  }
8713 
8714  if (ip) {
8715  int idx;
8716  int next = 0;
8717 
8718  for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
8719  const struct ast_ignorepat *i = ast_context_ignorepats_get(con, idx);
8720 
8721  if (next) {
8722  return i;
8723  }
8724 
8725  if (ip == i) {
8726  next = 1;
8727  }
8728  }
8729 
8730  return NULL;
8731  }
8732 
8733  if (!ast_context_ignorepats_count(con)) {
8734  return NULL;
8735  }
8736 
8737  return ast_context_ignorepats_get(con, 0);
8738 }
const struct ast_ignorepat * ast_context_ignorepats_get(const struct ast_context *con, int idx)
Definition: pbx.c:8745
#define NULL
Definition: resample.c:96
struct ast_exten * next
Definition: pbx.c:256
int ast_context_ignorepats_count(const struct ast_context *con)
Definition: pbx.c:8740
ast_ignorepat: Ignore patterns in dial plan
Definition: pbx_ignorepat.c:37

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

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

8670 {
8671  if (inc) {
8672  int idx;
8673  int next = 0;
8674 
8675  for (idx = 0; idx < ast_context_includes_count(con); idx++) {
8676  const struct ast_include *include = AST_VECTOR_GET(&con->includes, idx);
8677 
8678  if (next) {
8679  return include;
8680  }
8681 
8682  if (inc == include) {
8683  next = 1;
8684  }
8685  }
8686 
8687  return NULL;
8688  }
8689 
8690  if (!ast_context_includes_count(con)) {
8691  return NULL;
8692  }
8693 
8694  return ast_context_includes_get(con, 0);
8695 }
ast_include: include= support in extensions.conf
Definition: pbx_include.c:37
struct ast_ignorepat * next
Definition: conf2ael.c:169
#define NULL
Definition: resample.c:96
struct ast_includes includes
Definition: pbx.c:290
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
const struct ast_include * ast_context_includes_get(const struct ast_context *con, int idx)
Definition: pbx.c:8702
int ast_context_includes_count(const struct ast_context *con)
Definition: pbx.c:8697

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

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

8625 {
8626  if (sw) {
8627  int idx;
8628  int next = 0;
8629 
8630  for (idx = 0; idx < ast_context_switches_count(con); idx++) {
8631  const struct ast_sw *s = ast_context_switches_get(con, idx);
8632 
8633  if (next) {
8634  return s;
8635  }
8636 
8637  if (sw == s) {
8638  next = 1;
8639  }
8640  }
8641 
8642  return NULL;
8643  }
8644 
8645  if (!ast_context_switches_count(con)) {
8646  return NULL;
8647  }
8648 
8649  return ast_context_switches_get(con, 0);
8650 }
int ast_context_switches_count(const struct ast_context *con)
Definition: pbx.c:8652
const struct ast_sw * ast_context_switches_get(const struct ast_context *con, int idx)
Definition: pbx.c:8657
struct ast_include * next
Definition: conf2ael.c:151
#define NULL
Definition: resample.c:96
ast_sw: Switch statement in extensions.conf
Definition: pbx_sw.c:37

◆ ast_walk_contexts()

struct ast_context* ast_walk_contexts ( struct ast_context con)

Definition at line 8609 of file pbx.c.

References contexts, and ast_context::next.

Referenced by ast_context_find(), complete_show_dialplan_context(), manager_show_dialplan_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().

8610 {
8611  return con ? con->next : contexts;
8612 }
struct ast_context * next
Definition: pbx.c:289
static struct ast_context * contexts
Definition: pbx.c:776

◆ ast_walk_extension_priorities()

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

Definition at line 8662 of file pbx.c.

References ast_exten::exten, and ast_exten::peer.

Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), show_dialplan_helper(), and unreference_cached_app().

8664 {
8665  return priority ? priority->peer : exten;
8666 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
struct ast_exten * peer
Definition: pbx.c:250

◆ ast_wrlock_context()

int ast_wrlock_context ( struct ast_context con)

Write locks a given context.

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

Definition at line 8520 of file pbx.c.

References ast_rwlock_wrlock, and ast_context::lock.

Referenced by __ast_context_destroy(), add_hints(), ast_add_extension2_lockopt(), ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_extension_callerid2(), ast_context_remove_ignorepat2(), ast_context_remove_include2(), ast_context_remove_switch2(), parking_duration_callback(), and parking_lot_cfg_create_extensions().

8521 {
8522  return ast_rwlock_wrlock(&con->lock);
8523 }
ast_rwlock_t lock
Definition: pbx.c:285
#define ast_rwlock_wrlock(a)
Definition: lock.h:234

◆ ast_wrlock_contexts()

int ast_wrlock_contexts ( void  )

Write locks the context list.

Return values
0on success
-1on error

Definition at line 8502 of file pbx.c.

References ast_mutex_lock, and conlock.

Referenced by add_hints(), ast_context_destroy(), ast_context_destroy_by_name(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), complete_dialplan_remove_include(), manager_dialplan_extension_add(), parking_duration_callback(), and parking_lot_cfg_create_extensions().

8503 {
8504  return ast_mutex_lock(&conlock);
8505 }
#define ast_mutex_lock(a)
Definition: lock.h:187
static ast_mutex_t conlock
Lock for the ast_context list.
Definition: pbx.c:785

◆ autohint_cmp()

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

Definition at line 474 of file pbx.c.

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

475 {
476  struct ast_autohint *left = obj;
477  struct ast_autohint *right = arg;
478  const char *right_key = arg;
479  int cmp;
480 
481  switch (flags & OBJ_SEARCH_MASK) {
482  case OBJ_SEARCH_OBJECT:
483  right_key = right->context;
484  /* Fall through */
485  case OBJ_SEARCH_KEY:
486  cmp = strcasecmp(left->context, right_key);
487  break;
489  /*
490  * We could also use a partial key struct containing a length
491  * so strlen() does not get called for every comparison instead.
492  */
493  cmp = strncmp(left->context, right_key, strlen(right_key));
494  break;
495  default:
496  ast_assert(0);
497  cmp = 0;
498  break;
499  }
500  return cmp ? 0 : CMP_MATCH | CMP_STOP;
501 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
char context[1]
Name of the context.
Definition: pbx.c:389
#define ast_assert(a)
Definition: utils.h:695
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
Structure for dial plan autohints.
Definition: pbx.c:385
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076

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

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

454 {
455  const struct ast_autohint *autohint;
456  const char *key;
457 
458  switch (flags & OBJ_SEARCH_MASK) {
459  case OBJ_SEARCH_KEY:
460  key = obj;
461  break;
462  case OBJ_SEARCH_OBJECT:
463  autohint = obj;
464  key = autohint->context;
465  break;
466  default:
467  ast_assert(0);
468  return 0;
469  }
470 
471  return ast_str_case_hash(key);
472 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
char context[1]
Name of the context.
Definition: pbx.c:389
#define ast_assert(a)
Definition: utils.h:695
Structure for dial plan autohints.
Definition: pbx.c:385
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076
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:1250

◆ candidate_exten_advance()

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

Definition at line 1219 of file pbx.c.

References str.

1220 {
1221  str++;
1222  while (*str == '-') {
1223  str++;
1224  }
1225  return str;
1226 }
const char * str
Definition: app_jack.c:147

◆ cli_match_char_tree()

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

Definition at line 1111 of file pbx.c.

References match_char::alt_char, ast_cli(), ast_str_alloca, ast_str_buffer(), ast_str_set(), match_char::deleted, match_char::exten, match_char::is_pattern, ast_exten::name, match_char::next_char, match_char::specificity, and match_char::x.

Referenced by show_debug_helper().

1112 {
1113  char extenstr[40];
1114  struct ast_str *my_prefix = ast_str_alloca(1024);
1115 
1116  extenstr[0] = '\0';
1117 
1118  if (node->exten) {
1119  snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
1120  }
1121 
1122  if (strlen(node->x) > 1) {
1123  ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
1124  node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
1125  node->exten ? node->exten->name : "", extenstr);
1126  } else {
1127  ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
1128  node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
1129  node->exten ? node->exten->name : "", extenstr);
1130  }
1131 
1132  ast_str_set(&my_prefix, 0, "%s+ ", prefix);
1133 
1134  if (node->next_char)
1135  cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd);
1136 
1137  if (node->alt_char)
1138  cli_match_char_tree(node->alt_char, prefix, fd);
1139 }
struct ast_exten * exten
Definition: pbx.c:268
char * name
Definition: pbx.c:239
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
int specificity
Definition: pbx.c:265
struct match_char * alt_char
Definition: pbx.c:266
#define ast_str_alloca(init_len)
Definition: strings.h:800
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
char x[1]
Definition: pbx.c:269
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:1065
static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
Definition: pbx.c:1111
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
int is_pattern
Definition: pbx.c:263
struct match_char * next_char
Definition: pbx.c:267
static char prefix[MAX_PREFIX]
Definition: http.c:141
int deleted
Definition: pbx.c:264

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

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(), digit, ast_pbx::dtimeoutms, NULL, and S_COR.

Referenced by __ast_pbx_run().

4284 {
4285  int digit;
4286 
4287  buf[pos] = '\0'; /* make sure it is properly terminated */
4289  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4290  /* As long as we're willing to wait, and as long as it's not defined,
4291  keep reading digits until we can't possibly get a right answer anymore. */
4292  digit = ast_waitfordigit(c, waittime);
4294  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
4295  } else {
4296  if (!digit) /* No entry */
4297  break;
4298  if (digit < 0) /* Error, maybe a hangup */
4299  return -1;
4300  if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
4301  buf[pos++] = digit;
4302  buf[pos] = '\0';
4303  }
4304  waittime = ast_channel_pbx(c)->dtimeoutms;
4305  }
4306  }
4307  return 0;
4308 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
char digit
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define NULL
Definition: resample.c:96
Number structure.
Definition: app_followme.c:154
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition: channel.c:2437
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
#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:85
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:4199
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3184
int ast_channel_softhangup_internal_flag(struct ast_channel *chan)
int dtimeoutms
Definition: pbx.h:212
const char * ast_channel_context(const struct ast_channel *chan)

◆ compare_char()

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

Definition at line 674 of file pbx.c.

References a, b, and bc.

Referenced by get_pattern_node().

675 {
676  const unsigned char *ac = a;
677  const unsigned char *bc = b;
678 
679  return *ac - *bc;
680 }
#define bc
static struct test_val b
static struct test_val a

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

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

5269 {
5270  struct ast_hint *hint;
5271  char *ret = NULL;
5272  int which = 0;
5273  int wordlen;
5274  struct ao2_iterator i;
5275 
5276  if (pos != 3)
5277  return NULL;
5278 
5279  wordlen = strlen(word);
5280 
5281  /* walk through all hints */
5282  i = ao2_iterator_init(hints, 0);
5283  for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
5284  ao2_lock(hint);
5285  if (!hint->exten) {
5286  /* The extension has already been destroyed */
5287  ao2_unlock(hint);
5288  continue;
5289  }
5290  if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
5291  ret = ast_strdup(ast_get_extension_name(hint->exten));
5292  ao2_unlock(hint);
5293  ao2_ref(hint, -1);
5294  break;
5295  }
5296  ao2_unlock(hint);
5297  }
5299 
5300  return ret;
5301 }
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_exten * exten
Hint extension.
Definition: pbx.c:331
Structure for dial plan hints.
Definition: pbx.c:324
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
short word

◆ complete_show_dialplan_context()

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

Definition at line 5447 of file pbx.c.

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

5449 {
5450  struct ast_context *c = NULL;
5451  char *ret = NULL;
5452  int which = 0;
5453  int wordlen;
5454 
5455  /* we are do completion of [exten@]context on second position only */
5456  if (pos != 2)
5457  return NULL;
5458 
5460 
5461  wordlen = strlen(word);
5462 
5463  /* walk through all contexts and return the n-th match */
5464  while ( (c = ast_walk_contexts(c)) ) {
5465  if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
5466  ret = ast_strdup(ast_get_context_name(c));
5467  break;
5468  }
5469  }
5470 
5472 
5473  return ret;
5474 }
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: pbx.c:8609
static struct test_val c
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8507
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
short word

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

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_context::autohints, 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, ast_context::name, NULL, ast_exten::peer_table, ast_exten::priority, ast_context::refcount, ast_exten::registrar, ast_context::registrar, ast_exten::registrar_file, ast_exten::registrar_line, and ast_context::root_table.

Referenced by ast_merge_contexts_and_delete().

6370 {
6371  struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
6372  struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
6373  struct ast_hashtab_iter *exten_iter;
6374  struct ast_hashtab_iter *prio_iter;
6375  int insert_count = 0;
6376  int first = 1;
6377 
6378  /* We'll traverse all the extensions/prios, and see which are not registrar'd with
6379  the current registrar, and copy them to the new context. If the new context does not
6380  exist, we'll create it "on demand". If no items are in this context to copy, then we'll
6381  only create the empty matching context if the old one meets the criteria */
6382 
6383  if (context->root_table) {
6384  exten_iter = ast_hashtab_start_traversal(context->root_table);
6385  while ((exten_item=ast_hashtab_next(exten_iter))) {
6386  if (new) {
6387  new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
6388  } else {
6389  new_exten_item = NULL;
6390  }
6391  prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
6392  while ((prio_item=ast_hashtab_next(prio_iter))) {
6393  int res1;
6394  char *dupdstr;
6395 
6396  if (new_exten_item) {
6397  new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
6398  } else {
6399  new_prio_item = NULL;
6400  }
6401  if (strcmp(prio_item->registrar,registrar) == 0) {
6402  continue;
6403  }
6404  /* make sure the new context exists, so we have somewhere to stick this exten/prio */
6405  if (!new) {
6406  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 */
6407  if (new) {
6408  new->autohints = context->autohints;
6409  }
6410  }
6411 
6412  /* copy in the includes, switches, and ignorepats */
6413  if (first) { /* but, only need to do this once */
6415  first = 0;
6416  }
6417 
6418  if (!new) {
6419  ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
6420  ast_hashtab_end_traversal(prio_iter);
6421  ast_hashtab_end_traversal(exten_iter);
6422  return; /* no sense continuing. */
6423  }
6424  /* we will not replace existing entries in the new context with stuff from the old context.
6425  but, if this is because of some sort of registrar conflict, we ought to say something... */
6426 
6427  dupdstr = ast_strdup(prio_item->data);
6428 
6429  res1 = ast_add_extension2(new, 0, prio_item->name, prio_item->priority, prio_item->label,
6430  prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, ast_free_ptr, prio_item->registrar,
6431  prio_item->registrar_file, prio_item->registrar_line);
6432  if (!res1 && new_exten_item && new_prio_item){
6433  ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
6434  context->name, prio_item->name, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
6435  } else {
6436  /* 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,
6437  and no double frees take place, either! */
6438  insert_count++;
6439  }
6440  }
6441  ast_hashtab_end_traversal(prio_iter);
6442  }
6443  ast_hashtab_end_traversal(exten_iter);
6444  } else if (new) {
6445  /* If the context existed but had no extensions, we still want to merge
6446  * the includes, switches and ignore patterns.
6447  */
6449  }
6450 
6451  if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
6452  (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
6453  /* we could have given it the registrar of the other module who incremented the refcount,
6454  but that's not available, so we give it the registrar we know about */
6455  new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
6456 
6457  if (new) {
6458  new->autohints = context->autohints;
6459  }
6460 
6461  /* copy in the includes, switches, and ignorepats */
6463  }
6464 }
const char * label
Definition: pbx.c:244
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition: hashtab.c:486
char * name
Definition: pbx.c:239
int registrar_line
Definition: pbx.c:255
static void context_merge_incls_swits_igps_other_registrars(struct ast_context *new, struct ast_context *old, const char *registrar)
Definition: pbx.c:6294
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
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:7299
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
struct ast_hashtab * peer_table
Definition: pbx.c:251
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1771
#define ast_verb(level,...)
Definition: logger.h:463
const char * registrar
Definition: pbx.c:253
int autohints
Definition: pbx.c:295
#define ast_hashtab_start_traversal(tab)
Definition: hashtab.h:355
int matchcid
Definition: pbx.c:240
const char * registrar_file
Definition: pbx.c:254
int priority
Definition: pbx.c:243
#define ast_log
Definition: astobj2.c:42
char * registrar
Definition: pbx.c:293
void ast_hashtab_end_traversal(struct ast_hashtab_iter *it)
end the traversal, free the iterator, unlock if necc.
Definition: hashtab.c:674
#define LOG_ERROR
Definition: logger.h:285
char name[0]
Definition: pbx.c:297
struct sla_ringing_trunk * first
Definition: app_meetme.c:1092
an iterator for traversing the buckets
Definition: hashtab.h:105
static char * registrar
Definition: pbx_ael.c:78
const char * cidmatch
Definition: pbx.c:241
const char * app
Definition: pbx.c:246
int refcount
Definition: pbx.c:294
struct ast_hashtab * root_table
Definition: pbx.c:287
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:6198
void * data
Definition: pbx.c:248
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

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

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

Referenced by context_merge().

6295 {
6296  int idx;
6297 
6298  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);
6299  /* copy in the includes, switches, and ignorepats */
6300  /* walk through includes */
6301  for (idx = 0; idx < ast_context_includes_count(old); idx++) {
6302  const struct ast_include *i = ast_context_includes_get(old, idx);
6303 
6304  if (!strcmp(ast_get_include_registrar(i), registrar)) {
6305  continue; /* not mine */
6306  }
6308  }
6309 
6310  /* walk through switches */
6311  for (idx = 0; idx < ast_context_switches_count(old); idx++) {
6312  const struct ast_sw *sw = ast_context_switches_get(old, idx);
6313 
6314  if (!strcmp(ast_get_switch_registrar(sw), registrar)) {
6315  continue; /* not mine */
6316  }
6318  }
6319 
6320  /* walk thru ignorepats ... */
6321  for (idx = 0; idx < ast_context_ignorepats_count(old); idx++) {
6322  const struct ast_ignorepat *ip = ast_context_ignorepats_get(old, idx);
6323 
6324  if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) {
6325  continue; /* not mine */
6326  }
6328  }
6329 }
ast_include: include= support in extensions.conf
Definition: pbx_include.c:37
const char * ast_get_switch_name(const struct ast_sw *sw)
Definition: pbx_sw.c:48
const char * ast_get_switch_registrar(const struct ast_sw *sw)
Definition: pbx_sw.c:63
int ast_context_switches_count(const struct ast_context *con)
Definition: pbx.c:8652
int ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
Add a context include.
Definition: pbx.c:6726
const char * ast_get_ignorepat_registrar(const struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:47
const struct ast_ignorepat * ast_context_ignorepats_get(const struct ast_context *con, int idx)
Definition: pbx.c:8745
const struct ast_sw * ast_context_switches_get(const struct ast_context *con, int idx)
Definition: pbx.c:8657
const char * ast_get_include_registrar(const struct ast_include *i)
Definition: pbx_include.c:60
int ast_get_switch_eval(const struct ast_sw *sw)
Definition: pbx_sw.c:58
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
ast_sw: Switch statement in extensions.conf
Definition: pbx_sw.c:37
int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
Definition: pbx.c:6890
const char * ast_get_ignorepat_name(const struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:42
int ast_context_ignorepats_count(const struct ast_context *con)
Definition: pbx.c:8740
ast_ignorepat: Ignore patterns in dial plan
Definition: pbx_ignorepat.c:37
static char * registrar
Definition: pbx_ael.c:78
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:6791
const char * ast_get_switch_data(const struct ast_sw *sw)
Definition: pbx_sw.c:53
const char * ast_get_include_name(const struct ast_include *include)
Definition: pbx_include.c:50
const struct ast_include * ast_context_includes_get(const struct ast_context *con, int idx)
Definition: pbx.c:8702
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
int ast_context_includes_count(const struct ast_context *con)
Definition: pbx.c:8697

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

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

6333 {
6334  struct ast_context *con;
6335  struct ast_hashtab_iter *iter;
6336 
6337  /* Remove all autohints as the below iteration will recreate them */
6339 
6340  iter = ast_hashtab_start_traversal(table);
6341  while ((con = ast_hashtab_next(iter))) {
6342  size_t name_len = strlen(con->name) + 1;
6343  size_t registrar_len = strlen(con->registrar) + 1;
6344  struct ast_autohint *autohint;
6345 
6346  if (!con->autohints) {
6347  continue;
6348  }
6349 
6350  autohint = ao2_alloc_options(sizeof(*autohint) + name_len + registrar_len, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
6351  if (!autohint) {
6352  continue;
6353  }
6354 
6355  ast_copy_string(autohint->context, con->name, name_len);
6356  autohint->registrar = autohint->context + name_len;
6357  ast_copy_string(autohint->registrar, con->registrar, registrar_len);
6358 
6359  ao2_link(autohints, autohint);
6360  ao2_ref(autohint, -1);
6361 
6362  ast_verb(3, "Enabled autohints support on context '%s'\n", con->name);
6363  }
6365 }
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
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
char context[1]
Name of the context.
Definition: pbx.c:389
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
int autohints
Definition: pbx.c:295
#define ast_hashtab_start_traversal(tab)
Definition: hashtab.h:355
char * registrar
Definition: pbx.c:293
#define ao2_ref(o, delta)
Definition: astobj2.h:464
char * registrar
Name of the registrar.
Definition: pbx.c:387
void ast_hashtab_end_traversal(struct ast_hashtab_iter *it)
end the traversal, free the iterator, unlock if necc.
Definition: hashtab.c:674
char name[0]
Definition: pbx.c:297
Structure for dial plan autohints.
Definition: pbx.c:385
an iterator for traversing the buckets
Definition: hashtab.h:105
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
static struct ao2_container * autohints
Container for autohint contexts.
Definition: pbx.c:380
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ create_match_char_tree()

static void create_match_char_tree ( struct ast_context con)
static

Definition at line 1756 of file pbx.c.

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, ast_context::root_table, and t1.

Referenced by pbx_find_extension().

1757 {
1758  struct ast_hashtab_iter *t1;
1759  struct ast_exten *e1;
1760 #ifdef NEED_DEBUG
1761  int biggest_bucket, resizes, numobjs, numbucks;
1762 
1763  ast_debug(1, "Creating Extension Trie for context %s(%p)\n", con->name, con);
1764  ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
1765  ast_debug(1, "This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
1766  numobjs, numbucks, biggest_bucket, resizes);
1767 #endif
1769  while ((e1 = ast_hashtab_next(t1))) {
1770  if (e1->exten) {
1771  add_exten_to_pattern_tree(con, e1, 0);
1772  } else {
1773  ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n");
1774  }
1775  }
1777 }
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
static struct match_char * add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
Definition: pbx.c:1657
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_hashtab_start_traversal(tab)
Definition: hashtab.h:355
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
void ast_hashtab_end_traversal(struct ast_hashtab_iter *it)
end the traversal, free the iterator, unlock if necc.
Definition: hashtab.c:674
char * exten
Definition: pbx.c:238
#define LOG_ERROR
Definition: logger.h:285
char name[0]
Definition: pbx.c:297
an iterator for traversing the buckets
Definition: hashtab.h:105
struct ast_hashtab * root_table
Definition: pbx.c:287
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
static uint16_t t1
Definition: res_pktccops.c:157

◆ decrease_call_count()

static void decrease_call_count ( void  )
static

Definition at line 4670 of file pbx.c.

References ast_mutex_lock, ast_mutex_unlock, and maxcalllock.

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

4671 {
4673  if (countcalls > 0)
4674  countcalls--;
4676 }
#define ast_mutex_lock(a)
Definition: lock.h:187
static ast_mutex_t maxcalllock
Definition: pbx.c:772
static int countcalls
Definition: pbx.c:773
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ destroy_exten()

static void destroy_exten ( struct ast_exten e)
static

Definition at line 4678 of file pbx.c.

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

4679 {
4680  if (e->priority == PRIORITY_HINT)
4681  ast_remove_hint(e);
4682 
4683  if (e->peer_table)
4685  if (e->peer_label_table)
4687  if (e->datad)
4688  e->datad(e->data);
4689  ast_free(e);
4690 }
struct ast_hashtab * peer_table
Definition: pbx.c:251
int priority
Definition: pbx.c:243
void(* datad)(void *)
Definition: pbx.c:249
#define PRIORITY_HINT
Definition: pbx.h:54
struct ast_hashtab * peer_label_table
Definition: pbx.c:252
#define ast_free(a)
Definition: astmm.h:182
static int ast_remove_hint(struct ast_exten *e)
Remove hint from extension.
Definition: pbx.c:3945
void * data
Definition: pbx.c:248
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

◆ destroy_hint()

static void destroy_hint ( void *  obj)
static

Definition at line 3907 of file pbx.c.

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

Referenced by ast_add_hint().

3908 {
3909  struct ast_hint *hint = obj;
3910  int i;
3911 
3912  ao2_cleanup(hint->callbacks);
3913 
3914  for (i = 0; i < AST_VECTOR_SIZE(&hint->devices); i++) {
3915  char *device = AST_VECTOR_GET(&hint->devices, i);
3916  ast_free(device);
3917  }
3918  AST_VECTOR_FREE(&hint->devices);
3921 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
Structure for dial plan hints.
Definition: pbx.c:324
struct ao2_container * callbacks
Definition: pbx.c:332
#define ast_free(a)
Definition: astmm.h:182
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
char * last_presence_message
Definition: pbx.c:340
char * last_presence_subtype
Definition: pbx.c:339
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ destroy_pattern_tree()

static void destroy_pattern_tree ( struct match_char pattern_tree)
static

Definition at line 1779 of file pbx.c.

References match_char::alt_char, ast_free, match_char::exten, and match_char::next_char.

Referenced by __ast_internal_context_destroy().

1780 {
1781  /* destroy all the alternates */
1782  if (pattern_tree->alt_char) {
1783  destroy_pattern_tree(pattern_tree->alt_char);
1784  pattern_tree->alt_char = 0;
1785  }
1786  /* destroy all the nexts */
1787  if (pattern_tree->next_char) {
1788  destroy_pattern_tree(pattern_tree->next_char);
1789  pattern_tree->next_char = 0;
1790  }
1791  pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
1792  ast_free(pattern_tree);
1793 }
struct ast_exten * exten
Definition: pbx.c:268
struct match_char * alt_char
Definition: pbx.c:266
#define ast_free(a)
Definition: astmm.h:182
static void destroy_pattern_tree(struct match_char *pattern_tree)
Definition: pbx.c:1779
struct match_char * next_char
Definition: pbx.c:267

◆ destroy_state_cb()

static void destroy_state_cb ( void *  doomed)
static

Definition at line 3716 of file pbx.c.

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

Referenced by extension_state_add_destroy().

3717 {
3718  struct ast_state_cb *state_cb = doomed;
3719 
3720  if (state_cb->destroy_cb) {
3721  state_cb->destroy_cb(state_cb->id, state_cb->data);
3722  }
3723 }
void * data
Definition: pbx.c:305
ast_state_cb: An extension state notify register item
Definition: pbx.c:301
int id
Definition: pbx.c:303
ast_state_cb_destroy_type destroy_cb
Definition: pbx.c:311

◆ device_state_cb()

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

Definition at line 3584 of file pbx.c.

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, 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(), ast_hint::laststate, NULL, OBJ_MULTIPLE, OBJ_SEARCH_OBJECT, PRIORITY_HINT, ast_autohint::registrar, stasis_message_data(), stasis_message_type(), and type.

Referenced by load_pbx().

3585 {
3586  struct ast_device_state_message *dev_state;
3587  struct ast_str *hint_app;
3588  struct ast_hintdevice *device;
3589  struct ast_hintdevice *cmpdevice;
3590  struct ao2_iterator *dev_iter;
3591  struct ao2_iterator auto_iter;
3592  struct ast_autohint *autohint;
3593  char *virtual_device;
3594  char *type;
3595  char *device_name;
3596 
3598  return;
3599  }
3600 
3601  if (hint_remove_message_type() == stasis_message_type(msg)) {
3602  /* The extension has already been destroyed */
3603  struct ast_state_cb *state_cb;
3604  struct ao2_iterator cb_iter;
3605  struct ast_hint *hint = stasis_message_data(msg);
3606 
3607  ao2_lock(hint);
3609  ao2_unlock(hint);
3610 
3611  cb_iter = ao2_iterator_init(hint->callbacks, 0);
3612  for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3614  hint->context_name,
3615  hint->exten_name,
3616  state_cb->data,
3618  hint,
3619  NULL);
3620  }
3621  ao2_iterator_destroy(&cb_iter);
3622  return;
3623  }
3624 
3626  return;
3627  }
3628 
3629  dev_state = stasis_message_data(msg);
3630  if (dev_state->eid) {
3631  /* ignore non-aggregate states */
3632  return;
3633  }
3634 
3636  /* There are no hints monitoring devices. */
3637  return;
3638  }
3639 
3640  hint_app = ast_str_create(1024);
3641  if (!hint_app) {
3642  return;
3643  }
3644 
3645  cmpdevice = ast_alloca(sizeof(*cmpdevice) + strlen(dev_state->device));
3646  strcpy(cmpdevice->hintdevice, dev_state->device);
3647 
3648  ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
3649 
3650  /* Initially we find all hints for the device and notify them */
3651  dev_iter = ao2_t_callback(hintdevices,
3654  cmpdevice,
3655  "find devices in container");
3656  if (dev_iter) {
3657  for (; (device = ao2_iterator_next(dev_iter)); ao2_t_ref(device, -1, "Next device")) {
3658  if (device->hint) {
3659  device_state_notify_callbacks(device->hint, &hint_app);
3660  }
3661  }
3662  ao2_iterator_destroy(dev_iter);
3663  }
3664 
3665  /* Second stage we look for any autohint contexts and if the device is not already in the hints
3666  * we create it.
3667  */
3668  type = ast_strdupa(dev_state->device);
3669  if (ast_strlen_zero(type)) {
3670  goto end;
3671  }
3672 
3673  /* Determine if this is a virtual/custom device or a real device */
3674  virtual_device = strchr(type, ':');
3675  device_name = strchr(type, '/');
3676  if (virtual_device && (!device_name || (virtual_device < device_name))) {
3677  device_name = virtual_device;
3678  }
3679 
3680  /* Invalid device state name - not a virtual/custom device and not a real device */
3681  if (ast_strlen_zero(device_name)) {
3682  goto end;
3683  }
3684 
3685  *device_name++ = '\0';
3686 
3687  auto_iter = ao2_iterator_init(autohints, 0);
3688  for (; (autohint = ao2_iterator_next(&auto_iter)); ao2_t_ref(autohint, -1, "Next autohint")) {
3689  if (ast_get_hint(NULL, 0, NULL, 0, NULL, autohint->context, device_name)) {
3690  continue;
3691  }
3692 
3693  /* The device has no hint in the context referenced by this autohint so create one */
3694  ast_add_extension(autohint->context, 0, device_name,
3695  PRIORITY_HINT, NULL, NULL, dev_state->device,
3696  ast_strdup(dev_state->device), ast_free_ptr, autohint->registrar);
3697 
3698  /* Since this hint was just created there are no watchers, so we don't need to notify anyone */
3699  }
3700  ao2_iterator_destroy(&auto_iter);
3701 
3702 end:
3704  ast_free(hint_app);
3705  return;
3706 }
#define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:463
static const char type[]
Definition: chan_ooh323.c:109
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
void * data
Definition: pbx.c:305
ast_state_cb: An extension state notify register item
Definition: pbx.c:301
static struct ao2_container * hintdevices
Container for hint devices.
Definition: pbx.c:363
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
char context[1]
Name of the context.
Definition: pbx.c:389
static void device_state_notify_callbacks(struct ast_hint *hint, struct ast_str **hint_app)
Definition: pbx.c:3370
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct ast_hint * hint
Hint this hintdevice belongs to.
Definition: pbx.c:374
#define ast_mutex_lock(a)
Definition: lock.h:187
static ast_mutex_t context_merge_lock
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
Definition: pbx.c:790
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
char * end
Definition: eagi_proxy.c:73
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1771
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:4141
static int handle_hint_change_message_type(struct stasis_message *msg, enum ast_state_cb_update_reason reason)
Definition: pbx.c:3537
ast_state_cb_type change_cb
Definition: pbx.c:309
#define ast_strlen_zero(foo)
Definition: strings.h:52
char hintdevice[1]
Definition: pbx.c:376
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
static int hintdevice_cmp_multiple(void *obj, void *arg, int flags)
Definition: pbx.c:421
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:248
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define PRIORITY_HINT
Definition: pbx.h:54
char * registrar
Name of the registrar.
Definition: pbx.c:387
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
char context_name[AST_MAX_CONTEXT]
Definition: pbx.c:342
int laststate
Definition: pbx.c:335
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
Structure for dial plan autohints.
Definition: pbx.c:385
Structure for dial plan hints.
Definition: pbx.c:324
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:1714
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:6970
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
struct ao2_container * callbacks
Definition: pbx.c:332
#define ast_free(a)
Definition: astmm.h:182
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Structure for dial plan hint devices.
Definition: pbx.c:369
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
The structure that contains device state.
Definition: devicestate.h:240
static int execute_state_callback(ast_state_cb_type cb, const char *context, const char *exten, void *data, enum ast_state_cb_update_reason reason, struct ast_hint *hint, struct ao2_container *device_state_info)
Definition: pbx.c:3250
char exten_name[AST_MAX_EXTENSION]
Definition: pbx.c:343
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
static struct ao2_container * autohints
Container for autohint contexts.
Definition: pbx.c:380
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ device_state_info_dt()

static void device_state_info_dt ( void *  obj)
static

Definition at line 3069 of file pbx.c.

References ao2_cleanup, ast_device_state_info::causing_channel, and sip_to_pjsip::info().

Referenced by ast_extension_state3().

3070 {
3071  struct ast_device_state_info *info = obj;
3072 
3074 }
struct ast_channel * causing_channel
Definition: pbx.h:98
def info(msg)
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ device_state_notify_callbacks()

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

Definition at line 3370 of file pbx.c.

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 state.

Referenced by device_state_cb(), and handle_hint_change_message_type().

3371 {
3372  struct ao2_iterator cb_iter;
3373  struct ast_state_cb *state_cb;
3374  int state;
3375  int same_state;
3376  struct ao2_container *device_state_info;
3377  int first_extended_cb_call = 1;
3380 
3381  ao2_lock(hint);
3382  if (!hint->exten) {
3383  /* The extension has already been destroyed */
3384  ao2_unlock(hint);
3385  return;
3386  }
3387 
3388  /*
3389  * Save off strings in case the hint extension gets destroyed
3390  * while we are notifying the watchers.
3391  */
3392  ast_copy_string(context_name,
3394  sizeof(context_name));
3395  ast_copy_string(exten_name, ast_get_extension_name(hint->exten),
3396  sizeof(exten_name));
3397  ast_str_set(hint_app, 0, "%s", ast_get_extension_app(hint->exten));
3398  ao2_unlock(hint);
3399 
3400  /*
3401  * Get device state for this hint.
3402  *
3403  * NOTE: We cannot hold any locks while determining the hint
3404  * device state or notifying the watchers without causing a
3405  * deadlock. (conlock, hints, and hint)
3406  */
3407 
3408  /* Make a container so state3 can fill it if we wish.
3409  * If that failed we simply do not provide the extended state info.
3410  */
3411  device_state_info = alloc_device_state_info();
3412 
3413  state = ast_extension_state3(*hint_app, device_state_info);
3414  same_state = state == hint->laststate;
3415  if (same_state && (~state & AST_EXTENSION_RINGING)) {
3416  ao2_cleanup(device_state_info);
3417  return;
3418  }
3419 
3420  /* Device state changed since last check - notify the watchers. */
3421  hint->laststate = state; /* record we saw the change */
3422 
3423  /* For general callbacks */
3424  if (!same_state) {
3425  cb_iter = ao2_iterator_init(statecbs, 0);
3426  for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3428  context_name,
3429  exten_name,
3430  state_cb->data,
3432  hint,
3433  NULL);
3434  }
3435  ao2_iterator_destroy(&cb_iter);
3436  }
3437 
3438  /* For extension callbacks */
3439  /* extended callbacks are called when the state changed or when AST_STATE_RINGING is
3440  * included. Normal callbacks are only called when the state changed.
3441  */
3442  cb_iter = ao2_iterator_init(hint->callbacks, 0);
3443  for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3444  if (state_cb->extended && first_extended_cb_call) {
3445  /* Fill detailed device_state_info now that we know it is used by extd. callback */
3446  first_extended_cb_call = 0;
3447  get_device_state_causing_channels(device_state_info);
3448  }
3449  if (state_cb->extended || !same_state) {
3451  context_name,
3452  exten_name,
3453  state_cb->data,
3455  hint,
3456  state_cb->extended ? device_state_info : NULL);
3457  }
3458  }
3459  ao2_iterator_destroy(&cb_iter);
3460 
3461  ao2_cleanup(device_state_info);
3462 }
struct ast_context * ast_get_extension_context(struct ast_exten *exten)
Definition: pbx.c:8543
enum sip_cc_notify_state state
Definition: chan_sip.c:959
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
static struct ao2_container * alloc_device_state_info(void)
Definition: pbx.c:3076
void * data
Definition: pbx.c:305
int extended
Definition: pbx.c:307
ast_state_cb: An extension state notify register item
Definition: pbx.c:301
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
ast_state_cb_type change_cb
Definition: pbx.c:309
static void get_device_state_causing_channels(struct ao2_container *c)
Definition: pbx.c:3296
static const char context_name[]
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:1065
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_exten * exten
Hint extension.
Definition: pbx.c:331
int laststate
Definition: pbx.c:335
static int ast_extension_state3(struct ast_str *hint_app, struct ao2_container *device_state_info)
Definition: pbx.c:3081
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
struct ao2_container * callbacks
Definition: pbx.c:332
#define AST_MAX_CONTEXT
Definition: channel.h:136
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8596
static struct ao2_container * statecbs
Definition: pbx.c:803
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
Generic container type.
static int execute_state_callback(ast_state_cb_type cb, const char *context, const char *exten, void *data, enum ast_state_cb_update_reason reason, struct ast_hint *hint, struct ao2_container *device_state_info)
Definition: pbx.c:3250
static const char exten_name[]
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ exception_store_free()

static void exception_store_free ( void *  data)
static

Definition at line 2783 of file pbx.c.

References ast_free, ast_string_field_free_memory, and ast_exten::data.

2784 {
2785  struct pbx_exception *exception = data;
2786  ast_string_field_free_memory(exception);
2787  ast_free(exception);
2788 }
#define ast_free(a)
Definition: astmm.h:182
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ execute_state_callback()

static int execute_state_callback ( ast_state_cb_type  cb,
const char *  context,
const char *  exten,
void *  data,
enum ast_state_cb_update_reason  reason,
struct ast_hint hint,
struct ao2_container device_state_info 
)
static

Definition at line 3250 of file pbx.c.

References ao2_lock, ao2_unlock, AST_EXTENSION_REMOVED, ast_strdupa, ast_strlen_zero, ast_state_cb_info::device_state_info, ast_state_cb_info::exten_state, ast_hint::last_presence_message, ast_hint::last_presence_state, ast_hint::last_presence_subtype, ast_hint::laststate, ast_state_cb_info::presence_message, ast_state_cb_info::presence_state, ast_state_cb_info::presence_subtype, 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().

3257 {
3258  int res = 0;
3259  struct ast_state_cb_info info = { 0, };
3260 
3261  info.reason = reason;
3262 
3263  /* Copy over current hint data */
3264  if (hint) {
3265  ao2_lock(hint);
3266  info.exten_state = hint->laststate;
3268  info.presence_state = hint->last_presence_state;
3269  if (!(ast_strlen_zero(hint->last_presence_subtype))) {
3271  } else {
3272  info.presence_subtype = "";
3273  }
3274  if (!(ast_strlen_zero(hint->last_presence_message))) {
3276  } else {
3277  info.presence_message = "";
3278  }
3279  ao2_unlock(hint);
3280  } else {
3282  }
3283 
3284  res = cb(context, exten, &info, data);
3285 
3286  return res;
3287 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
const char * presence_message
Definition: pbx.h:108
enum ast_state_cb_update_reason reason
Definition: pbx.h:103
#define ao2_unlock(a)
Definition: astobj2.h:730
int last_presence_state
Definition: pbx.c:338
#define ast_strlen_zero(foo)
Definition: strings.h:52
enum ast_extension_states exten_state
Definition: pbx.h:104
enum ast_presence_state presence_state
Definition: pbx.h:106
const char * presence_subtype
Definition: pbx.h:107
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
struct ao2_container * device_state_info
Definition: pbx.h:105
int laststate
Definition: pbx.c:335
def info(msg)
char * last_presence_message
Definition: pbx.c:340
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
char * last_presence_subtype
Definition: pbx.c:339

◆ ext_cmp()

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

Definition at line 2126 of file pbx.c.

References ext_cmp_exten(), and ext_cmp_pattern().

Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().

2127 {
2128  /* Make sure non-pattern extens come first. */
2129  if (left[0] != '_') {
2130  if (right[0] == '_') {
2131  return -1;
2132  }
2133  /* Compare two non-pattern extens. */
2134  return ext_cmp_exten(left, right);
2135  }
2136  if (right[0] != '_') {
2137  return 1;
2138  }
2139 
2140  /*
2141  * OK, we need full pattern sorting routine.
2142  *
2143  * Skip past the underscores
2144  */
2145  return ext_cmp_pattern(left + 1, right + 1);
2146 }
static int ext_cmp_pattern(const char *left, const char *right)
Definition: pbx.c:2078
static int ext_cmp_exten(const char *left, const char *right)
Definition: pbx.c:1876

◆ ext_cmp_exten()

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

Definition at line 1876 of file pbx.c.

Referenced by _extension_match_core(), and ext_cmp().

1877 {
1878  int cmp;
1879 
1880  for (;;) {
1881  /* Ignore '-' chars as eye candy fluff. */
1882  while (*left == '-') {
1883  ++left;
1884  }
1885  while (*right == '-') {
1886  ++right;
1887  }
1888 
1889  cmp = *left - *right;
1890  if (cmp) {
1891  break;
1892  }
1893  if (!*left) {
1894  /*
1895  * Get here only if both strings ended at the same time. cmp
1896  * would be non-zero if only one string ended.
1897  */
1898  break;
1899  }
1900  ++left;
1901  ++right;
1902  }
1903  return cmp;
1904 }

◆ ext_cmp_exten_partial()

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

Definition at line 1833 of file pbx.c.

Referenced by _extension_match_core().

1834 {
1835  int cmp;
1836 
1837  for (;;) {
1838  /* Ignore '-' chars as eye candy fluff. */
1839  while (*left == '-') {
1840  ++left;
1841  }
1842  while (*right == '-') {
1843  ++right;
1844  }
1845 
1846  if (!*right) {
1847  /*
1848  * Right ended first for partial match or both ended at the same
1849  * time for a match.
1850  */
1851  cmp = 0;
1852  break;
1853  }
1854 
1855  cmp = *left - *right;
1856  if (cmp) {
1857  break;
1858  }
1859  ++left;
1860  ++right;
1861  }
1862  return cmp;
1863 }

◆ ext_cmp_exten_strlen()

static int ext_cmp_exten_strlen ( const char *  str)
static

Definition at line 1803 of file pbx.c.

References len(), and str.

Referenced by _extension_match_core().

1804 {
1805  int len;
1806 
1807  len = 0;
1808  for (;;) {
1809  /* Ignore '-' chars as eye candy fluff. */
1810  while (*str == '-') {
1811  ++str;
1812  }
1813  if (!*str) {
1814  break;
1815  }
1816  ++str;
1817  ++len;
1818  }
1819  return len;
1820 }
const char * str
Definition: app_jack.c:147
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

◆ ext_cmp_pattern()

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

Definition at line 2078 of file pbx.c.

References ARRAY_LEN, and ext_cmp_pattern_pos().

Referenced by _extension_match_core(), and ext_cmp().

2079 {
2080  int cmp;
2081  int left_pos;
2082  int right_pos;
2083 
2084  for (;;) {
2085  unsigned char left_bitwise[32] = { 0, };
2086  unsigned char right_bitwise[32] = { 0, };
2087 
2088  left_pos = ext_cmp_pattern_pos(&left, left_bitwise);
2089  right_pos = ext_cmp_pattern_pos(&right, right_bitwise);
2090  cmp = left_pos - right_pos;
2091  if (!cmp) {
2092  /*
2093  * Are the character sets different, even though they score the same?
2094  *
2095  * Note: Must swap left and right to get the sense of the
2096  * comparison correct. Otherwise, we would need to multiply by
2097  * -1 instead.
2098  */
2099  cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise));
2100  }
2101  if (cmp) {
2102  break;
2103  }
2104  if (!left) {
2105  /*
2106  * Get here only if both patterns ended at the same time. cmp
2107  * would be non-zero if only one pattern ended.
2108  */
2109  break;
2110  }
2111  }
2112  return cmp;
2113 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
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:1963

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

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

Referenced by ext_cmp_pattern().

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

◆ ext_fluff_count()

static int ext_fluff_count ( const char *  exten)
static

Definition at line 2148 of file pbx.c.

Referenced by ast_add_extension2_lockopt().

2149 {
2150  int fluff = 0;
2151 
2152  if (*exten != '_') {
2153  /* not a pattern, simple check. */
2154  while (*exten) {
2155  if (*exten == '-') {
2156  fluff++;
2157  }
2158  exten++;
2159  }
2160 
2161  return fluff;
2162  }
2163 
2164  /* do pattern check */
2165  while (*exten) {
2166  if (*exten == '-') {
2167  fluff++;
2168  } else if (*exten == '[') {
2169  /* skip set, dashes here matter. */
2170  exten = strchr(exten, ']');
2171 
2172  if (!exten) {
2173  /* we'll end up warning about this later, don't spam logs */
2174  return fluff;
2175  }
2176  }
2177  exten++;
2178  }
2179 
2180  return fluff;
2181 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118

◆ ext_strncpy()

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

Definition at line 7068 of file pbx.c.

Referenced by ast_add_extension2_lockopt(), and ast_context_remove_extension_callerid2().

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

◆ extension_match_core()

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

Definition at line 2400 of file pbx.c.

References _extension_match_core(), ast_add_profile(), ast_mark(), and ast_strlen_zero.

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

2401 {
2402  int i;
2403  static int prof_id = -2; /* marker for 'unallocated' id */
2404  if (prof_id == -2) {
2405  prof_id = ast_add_profile("ext_match", 0);
2406  }
2407  ast_mark(prof_id, 1);
2408  i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode);
2409  ast_mark(prof_id, 0);
2410  return i;
2411 }
int64_t ast_mark(int, int start1_stop0)
Definition: astman.c:103
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_add_profile(const char *, uint64_t scale)
support for event profiling
Definition: astman.c:92
static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
Definition: pbx.c:2209

◆ extension_presence_state_helper()

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

Definition at line 3200 of file pbx.c.

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

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

3201 {
3202  struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
3203  char *presence_provider;
3204  const char *app;
3205 
3206  if (!e || !hint_app) {
3207  return -1;
3208  }
3209 
3210  app = ast_get_extension_app(e);
3211  if (ast_strlen_zero(app)) {
3212  return -1;
3213  }
3214 
3215  ast_str_set(&hint_app, 0, "%s", app);
3216  presence_provider = parse_hint_presence(hint_app);
3217 
3218  if (ast_strlen_zero(presence_provider)) {
3219  /* No presence string in the hint */
3220  return 0;
3221  }
3222 
3223  return ast_presence_state(presence_provider, subtype, message);
3224 }
static struct ast_threadstorage extensionstate_buf
Definition: pbx.c:229
static char * parse_hint_presence(struct ast_str *hint_args)
Definition: pbx.c:3037
#define ast_strlen_zero(foo)
Definition: strings.h:52
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:1065
ast_presence_state
Definition: presencestate.h:26
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8596
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:861
static const char app[]
Definition: app_mysql.c:62

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

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, ast_state_cb::id, id, ast_exten::label, ast_exten::matchcid, ast_context::name, NULL, OBJ_NODATA, OBJ_UNLINK, ast_exten::parent, ast_exten::priority, and ast_exten::registrar.

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

3731 {
3732  struct ast_hint *hint;
3733  struct ast_state_cb *state_cb;
3734  struct ast_exten *e;
3735  int id;
3736 
3737  /* If there's no context and extension: add callback to statecbs list */
3738  if (!context && !exten) {
3739  /* Prevent multiple adds from adding the same change_cb at the same time. */
3740  ao2_lock(statecbs);
3741 
3742  /* Remove any existing change_cb. */
3743  ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
3744 
3745  /* Now insert the change_cb */
3746  if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
3748  return -1;
3749  }
3750  state_cb->id = 0;
3751  state_cb->change_cb = change_cb;
3752  state_cb->destroy_cb = destroy_cb;
3753  state_cb->data = data;
3754  state_cb->extended = extended;
3755  ao2_link(statecbs, state_cb);
3756 
3757  ao2_ref(state_cb, -1);
3759  return 0;
3760  }
3761 
3762  if (!context || !exten)
3763  return -1;
3764 
3765  /* This callback type is for only one hint, so get the hint */
3767  if (!e) {
3768  return -1;
3769  }
3770 
3771  /* If this is a pattern, dynamically create a new extension for this
3772  * particular match. Note that this will only happen once for each
3773  * individual extension, because the pattern will no longer match first.
3774  */
3775  if (e->exten[0] == '_') {
3776  ao2_lock(hints);
3777  ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
3778  e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
3779  e->registrar);
3780  ao2_unlock(hints);
3782  if (!e || e->exten[0] == '_') {
3783  return -1;
3784  }
3785  }
3786 
3787  /* Find the hint in the hints container */
3788  ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
3789  hint = ao2_find(hints, e, 0);
3790  if (!hint) {
3791  ao2_unlock(hints);
3792  return -1;
3793  }
3794 
3795  /* Now insert the callback in the callback list */
3796  if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
3797  ao2_ref(hint, -1);
3798  ao2_unlock(hints);
3799  return -1;
3800  }
3801  do {
3802  id = stateid++; /* Unique ID for this callback */
3803  /* Do not allow id to ever be -1 or 0. */
3804  } while (id == -1 || id == 0);
3805  state_cb->id = id;
3806  state_cb->change_cb = change_cb; /* Pointer to callback routine */
3807  state_cb->destroy_cb = destroy_cb;
3808  state_cb->data = data; /* Data for the callback */
3809  state_cb->extended = extended;
3810  ao2_link(hint->callbacks, state_cb);
3811 
3812  ao2_ref(state_cb, -1);
3813  ao2_ref(hint, -1);
3814  ao2_unlock(hints);
3815 
3816  return id;
3817 }
const char * label
Definition: pbx.c:244
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
void * data
Definition: pbx.c:305
int extended
Definition: pbx.c:307
ast_state_cb: An extension state notify register item
Definition: pbx.c:301
static int stateid
Definition: pbx.c:792
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1771
const char * registrar
Definition: pbx.c:253
ast_state_cb_type change_cb
Definition: pbx.c:309
int matchcid
Definition: pbx.c:240
int priority
Definition: pbx.c:243
int id
Definition: pbx.c:303
static struct ast_exten * ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
Definition: pbx.c:2997
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
char * exten
Definition: pbx.c:238
char name[0]
Definition: pbx.c:297
ast_state_cb_destroy_type destroy_cb
Definition: pbx.c:311
Structure for dial plan hints.
Definition: pbx.c:324
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:6970
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct ao2_container * callbacks
Definition: pbx.c:332
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static void destroy_state_cb(void *doomed)
Definition: pbx.c:3716
const char * cidmatch
Definition: pbx.c:241
const char * app
Definition: pbx.c:246
static struct ao2_container * statecbs
Definition: pbx.c:803
struct ast_context * parent
Definition: pbx.c:245
enum queue_result id
Definition: app_queue.c:1507
void * data
Definition: pbx.c:248
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define ao2_link(container, obj)
Definition: astobj2.h:1549

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

References ast_copy_string(), ast_hashtab_lookup(), and fake_context::name.

Referenced by ast_add_extension_nolock(), and pbx_find_extension().

4805 {
4806  struct fake_context item;
4807 
4809 
4811 }
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition: hashtab.c:486
static struct ast_hashtab * contexts_table
Definition: pbx.c:777
static struct aco_type item
Definition: test_config.c:1463
const char * name
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

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

References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), c, and fake_context::name.

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

4819 {
4820  struct ast_context *c;
4821  struct fake_context item;
4822 
4824 
4827  if (!c) {
4829  }
4830 
4831  return c;
4832 }
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition: hashtab.c:486
static struct ast_hashtab * contexts_table
Definition: pbx.c:777
static struct aco_type item
Definition: test_config.c:1463
static struct test_val c
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8507
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
const char * name
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

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

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

Referenced by ast_extension_state_del().

3845 {
3846  struct ast_state_cb *state_cb;
3847  const struct ast_hint *hint = obj;
3848  int *id = arg;
3849 
3850  if ((state_cb = ao2_find(hint->callbacks, id, 0))) {
3851  ao2_ref(state_cb, -1);
3852  return CMP_MATCH | CMP_STOP;
3853  }
3854 
3855  return 0;
3856 }
ast_state_cb: An extension state notify register item
Definition: pbx.c:301
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Structure for dial plan hints.
Definition: pbx.c:324
struct ao2_container * callbacks
Definition: pbx.c:332
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756

◆ get_canmatch_exten()

static struct ast_exten * get_canmatch_exten ( struct match_char node)
static

Definition at line 1141 of file pbx.c.

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

1142 {
1143  /* find the exten at the end of the rope */
1144  struct match_char *node2 = node;
1145 
1146  for (node2 = node; node2; node2 = node2->next_char) {
1147  if (node2->exten) {
1148 #ifdef NEED_DEBUG_HERE
1149  ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten);
1150 #endif
1151  return node2->exten;
1152  }
1153  }
1154 #ifdef NEED_DEBUG_HERE
1155  ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x);
1156 #endif
1157  return 0;
1158 }
struct ast_exten * exten
Definition: pbx.c:268
char x[1]
Definition: pbx.c:269
#define ast_log
Definition: astobj2.c:42
char * exten
Definition: pbx.c:238
#define LOG_NOTICE
Definition: logger.h:263
struct match_char * next_char
Definition: pbx.c:267
match_char: forms a syntax tree for quick matching of extension patterns
Definition: pbx.c:261

◆ get_device_state_causing_channels()

static void get_device_state_causing_channels ( struct ao2_container c)
static

/internal /brief Identify a channel for every device which is supposedly responsible for the device state.

Especially when the device is ringing, the oldest ringing channel is chosen. For all other cases the first encountered channel in the specific state is chosen.

Definition at line 3296 of file pbx.c.

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(), ast_device_state_info::causing_channel, ast_device_state_info::device_name, ast_device_state_info::device_state, sip_to_pjsip::info(), and match().

Referenced by ast_extension_state_extended(), and device_state_notify_callbacks().

3297 {
3298  struct ao2_iterator iter;
3299  struct ast_device_state_info *info;
3300  struct ast_channel *chan;
3301 
3302  if (!c || !ao2_container_count(c)) {
3303  return;
3304  }
3305  iter = ao2_iterator_init(c, 0);
3306  for (; (info = ao2_iterator_next(&iter)); ao2_ref(info, -1)) {
3307  enum ast_channel_state search_state = 0; /* prevent false uninit warning */
3308  char match[AST_CHANNEL_NAME];
3309  struct ast_channel_iterator *chan_iter;
3310  struct timeval chantime = {0, }; /* prevent false uninit warning */
3311 
3312  switch (info->device_state) {
3313  case AST_DEVICE_RINGING:
3314  case AST_DEVICE_RINGINUSE:
3315  /* find ringing channel */
3316  search_state = AST_STATE_RINGING;
3317  break;
3318  case AST_DEVICE_BUSY:
3319  /* find busy channel */
3320  search_state = AST_STATE_BUSY;
3321  break;
3322  case AST_DEVICE_ONHOLD:
3323  case AST_DEVICE_INUSE:
3324  /* find up channel */
3325  search_state = AST_STATE_UP;
3326  break;
3327  case AST_DEVICE_UNKNOWN:
3328  case AST_DEVICE_NOT_INUSE:
3329  case AST_DEVICE_INVALID:
3331  case AST_DEVICE_TOTAL /* not a state */:
3332  /* no channels are of interest */
3333  continue;
3334  }
3335 
3336  /* iterate over all channels of the device */
3337  snprintf(match, sizeof(match), "%s-", info->device_name);
3338  chan_iter = ast_channel_iterator_by_name_new(match, strlen(match));
3339  for (; (chan = ast_channel_iterator_next(chan_iter)); ast_channel_unref(chan)) {
3340  ast_channel_lock(chan);
3341  /* this channel's state doesn't match */
3342  if (search_state != ast_channel_state(chan)) {
3343  ast_channel_unlock(chan);
3344  continue;
3345  }
3346  /* any non-ringing channel will fit */
3347  if (search_state != AST_STATE_RINGING) {
3348  ast_channel_unlock(chan);
3349  info->causing_channel = chan; /* is kept ref'd! */
3350  break;
3351  }
3352  /* but we need the oldest ringing channel of the device to match with undirected pickup */
3353  if (!info->causing_channel) {
3354  chantime = ast_channel_creationtime(chan);
3355  ast_channel_ref(chan); /* must ref it! */
3356  info->causing_channel = chan;
3357  } else if (ast_tvcmp(ast_channel_creationtime(chan), chantime) < 0) {
3358  chantime = ast_channel_creationtime(chan);
3360  ast_channel_ref(chan); /* must ref it! */
3361  info->causing_channel = chan;
3362  }
3363  ast_channel_unlock(chan);
3364  }
3365  ast_channel_iterator_destroy(chan_iter);
3366  }
3367  ao2_iterator_destroy(&iter);
3368 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Definition: channel.c:1422
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
char device_name[1]
Definition: pbx.h:99
ast_channel_state
ast_channel states
Definition: channelstate.h:35
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
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:2315
struct ast_channel * causing_channel
Definition: pbx.h:98
#define ao2_ref(o, delta)
Definition: astobj2.h:464
enum ast_device_state device_state
Definition: pbx.h:97
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compres two struct timeval instances returning -1, 0, 1 if the first arg is smaller, equal or greater to the second.
Definition: time.h:128
def info(msg)
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
struct timeval ast_channel_creationtime(struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define AST_CHANNEL_NAME
Definition: channel.h:172
struct ast_channel_iterator * ast_channel_iterator_by_name_new(const char *name, size_t name_len)
Create a new channel iterator based on name.
Definition: channel.c:1388
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
Definition: channel.c:1360
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

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

References ast_log, pattern_node::buf, compare_char(), first, INC_DST_OVERFLOW_CHECK, last, LOG_ERROR, LOG_WARNING, and pattern_node::specif.

Referenced by add_exten_to_pattern_tree().

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

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

References ast_cli_args::argc, ast_cli_args::argv, 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, ast_exten::exten, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NULL, ast_cli_args::pos, show_debug_helper(), strsep(), dialplan_counters::total_context, ast_cli_entry::usage, and ast_cli_args::word.

5800 {
5801  char *exten = NULL, *context = NULL;
5802  /* Variables used for different counters */
5803  struct dialplan_counters counters;
5804  const char *incstack[AST_PBX_MAX_STACK];
5805 
5806  switch (cmd) {
5807  case CLI_INIT:
5808  e->command = "dialplan debug";
5809  e->usage =
5810  "Usage: dialplan debug [context]\n"
5811  " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
5812  return NULL;
5813  case CLI_GENERATE:
5814  return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
5815  }
5816 
5817  memset(&counters, 0, sizeof(counters));
5818 
5819  if (a->argc != 2 && a->argc != 3)
5820  return CLI_SHOWUSAGE;
5821 
5822  /* we obtain [exten@]context? if yes, split them ... */
5823  /* note: we ignore the exten totally here .... */
5824  if (a->argc == 3) {
5825  if (strchr(a->argv[2], '@')) { /* split into exten & context */
5826  context = ast_strdupa(a->argv[2]);
5827  exten = strsep(&context, "@");
5828  /* change empty strings to NULL */
5829  if (ast_strlen_zero(exten))
5830  exten = NULL;
5831  } else { /* no '@' char, only context given */
5832  context = ast_strdupa(a->argv[2]);
5833  }
5834  if (ast_strlen_zero(context))
5835  context = NULL;
5836  }
5837  /* else Show complete dial plan, context and exten are NULL */
5838  show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
5839 
5840  /* check for input failure and throw some error messages */
5841  if (context && !counters.context_existence) {
5842  ast_cli(a->fd, "There is no existence of '%s' context\n", context);
5843  return CLI_FAILURE;
5844  }
5845 
5846 
5847  ast_cli(a->fd,"-= %d %s. =-\n",
5848  counters.total_context, counters.total_context == 1 ? "context" : "contexts");
5849 
5850  /* everything ok */
5851  return CLI_SUCCESS;
5852 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const char * line
Definition: cli.h:162
#define ast_strlen_zero(foo)
Definition: strings.h:52
const int fd
Definition: cli.h:159
const int n
Definition: cli.h:165
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
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:5677
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define AST_PBX_MAX_STACK
Definition: extconf.h:226
#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:5447
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
char * strsep(char **str, const char *delims)
const int pos
Definition: cli.h:164
Counters for the show dialplan manager command.
Definition: pbx.c:5477
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ handle_hint_change_message_type()

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

Definition at line 3537 of file pbx.c.

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

Referenced by device_state_cb().

3538 {
3539  struct ast_hint *hint;
3540  struct ast_str *hint_app;
3541 
3542  if (hint_change_message_type() != stasis_message_type(msg)) {
3543  return 0;
3544  }
3545 
3546  if (!(hint_app = ast_str_create(1024))) {
3547  return -1;
3548  }
3549 
3550  hint = stasis_message_data(msg);
3551 
3552  switch (reason) {
3554  device_state_notify_callbacks(hint, &hint_app);
3555  break;
3557  {
3558  char *presence_subtype = NULL;
3559  char *presence_message = NULL;
3560  int state;
3561 
3563  hint->exten, &presence_subtype, &presence_message);
3564  {
3565  struct ast_presence_state_message presence_state = {
3566  .state = state > 0 ? state : AST_PRESENCE_INVALID,
3567  .subtype = presence_subtype,
3568  .message = presence_message
3569  };
3570 
3571  presence_state_notify_callbacks(hint, &hint_app, &presence_state);
3572  }
3573 
3574  ast_free(presence_subtype);
3575  ast_free(presence_message);
3576  }
3577  break;
3578  }
3579 
3580  ast_free(hint_app);
3581  return 1;
3582 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
static int extension_presence_state_helper(struct ast_exten *e, char **subtype, char **message)
Definition: pbx.c:3200
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
static void device_state_notify_callbacks(struct ast_hint *hint, struct ast_str **hint_app)
Definition: pbx.c:3370
Stasis message payload representing a presence state update.
#define NULL
Definition: resample.c:96
static void presence_state_notify_callbacks(struct ast_hint *hint, struct ast_str **hint_app, struct ast_presence_state_message *presence_state)
Definition: pbx.c:3464
struct ast_exten * exten
Hint extension.
Definition: pbx.c:331
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
Structure for dial plan hints.
Definition: pbx.c:324
#define ast_free(a)
Definition: astmm.h:182
enum ast_presence_state state
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ handle_set_extenpatternmatchnew()

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

Definition at line 6105 of file pbx.c.

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

6106 {
6107  int oldval = 0;
6108 
6109  switch (cmd) {
6110  case CLI_INIT:
6111  e->command = "dialplan set extenpatternmatchnew true";
6112  e->usage =
6113  "Usage: dialplan set extenpatternmatchnew true|false\n"
6114  " Use the NEW extension pattern matching algorithm, true or false.\n";
6115  return NULL;
6116  case CLI_GENERATE:
6117  return NULL;
6118  }
6119 
6120  if (a->argc != 4)
6121  return CLI_SHOWUSAGE;
6122 
6123  oldval = pbx_set_extenpatternmatchnew(1);
6124 
6125  if (oldval)
6126  ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
6127  else
6128  ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
6129 
6130  return CLI_SUCCESS;
6131 }
int pbx_set_extenpatternmatchnew(int newval)
Definition: pbx.c:4781
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const int fd
Definition: cli.h:159
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44

◆ handle_show_device2extenstate()

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

Definition at line 6076 of file pbx.c.

References ast_cli(), AST_DEVICE_TOTAL, ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_devstate_str(), ast_devstate_to_extenstate(), ast_extension_state2str(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_exten::exten, ast_cli_args::fd, NULL, and ast_cli_entry::usage.

6077 {
6078  struct ast_devstate_aggregate agg;
6079  int i, j, exten, combined;
6080 
6081  switch (cmd) {
6082  case CLI_INIT:
6083  e->command = "core show device2extenstate";
6084  e->usage =
6085  "Usage: core show device2extenstate\n"
6086  " Lists device state to extension state combinations.\n";
6087  case CLI_GENERATE:
6088  return NULL;
6089  }
6090  for (i = 0; i < AST_DEVICE_TOTAL; i++) {
6091  for (j = 0; j < AST_DEVICE_TOTAL; j++) {
6093  ast_devstate_aggregate_add(&agg, i);
6094  ast_devstate_aggregate_add(&agg, j);
6095  combined = ast_devstate_aggregate_result(&agg);
6096  exten = ast_devstate_to_extenstate(combined);
6097  ast_cli(a->fd, "\n Exten:%14s CombinedDevice:%12s Dev1:%12s Dev2:%12s", ast_extension_state2str(exten), ast_devstate_str(combined), ast_devstate_str(j), ast_devstate_str(i));
6098  }
6099  }
6100  ast_cli(a->fd, "\n");
6101  return CLI_SUCCESS;
6102 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
enum ast_device_state ast_devstate_aggregate_result(struct ast_devstate_aggregate *agg)
Get the aggregate device state result.
Definition: devicestate.c:663
const int fd
Definition: cli.h:159
void ast_devstate_aggregate_add(struct ast_devstate_aggregate *agg, enum ast_device_state state)
Add a device state to the aggregate device state.
Definition: devicestate.c:636
const char * ast_devstate_str(enum ast_device_state devstate) attribute_pure
Convert device state to text string that is easier to parse.
Definition: devicestate.c:255
char * command
Definition: cli.h:186
void ast_devstate_aggregate_init(struct ast_devstate_aggregate *agg)
Initialize aggregate device state.
Definition: devicestate.c:630
enum ast_extension_states ast_devstate_to_extenstate(enum ast_device_state devstate)
Map devstate to an extension state.
Definition: pbx.c:3006
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
You shouldn&#39;t care about the contents of this struct.
Definition: devicestate.h:230
const char * ast_extension_state2str(int extension_state)
Return extension_state as string.
Definition: pbx.c:3126

◆ handle_show_dialplan()

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

Definition at line 5732 of file pbx.c.

References ast_cli_args::argc, ast_cli_args::argv, 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, ast_exten::exten, dialplan_counters::extension_existence, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NULL, ast_cli_args::pos, show_dialplan_helper(), strsep(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_prio, ast_cli_entry::usage, and ast_cli_args::word.

5733 {
5734  char *exten = NULL, *context = NULL;
5735  /* Variables used for different counters */
5736  struct dialplan_counters counters;
5737  const char *incstack[AST_PBX_MAX_STACK];
5738 
5739  switch (cmd) {
5740  case CLI_INIT:
5741  e->command = "dialplan show";
5742  e->usage =
5743  "Usage: dialplan show [[exten@]context]\n"
5744  " Show dialplan\n";
5745  return NULL;
5746  case CLI_GENERATE:
5747  return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
5748  }
5749 
5750  memset(&counters, 0, sizeof(counters));
5751 
5752  if (a->argc != 2 && a->argc != 3)
5753  return CLI_SHOWUSAGE;
5754 
5755  /* we obtain [exten@]context? if yes, split them ... */
5756  if (a->argc == 3) {
5757  if (strchr(a->argv[2], '@')) { /* split into exten & context */
5758  context = ast_strdupa(a->argv[2]);
5759  exten = strsep(&context, "@");
5760  /* change empty strings to NULL */
5761  if (ast_strlen_zero(exten))
5762  exten = NULL;
5763  } else { /* no '@' char, only context given */
5764  context = ast_strdupa(a->argv[2]);
5765  }
5766  if (ast_strlen_zero(context))
5767  context = NULL;
5768  }
5769  /* else Show complete dial plan, context and exten are NULL */
5770  show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
5771 
5772  /* check for input failure and throw some error messages */
5773  if (context && !counters.context_existence) {
5774  ast_cli(a->fd, "There is no existence of '%s' context\n", context);
5775  return CLI_FAILURE;
5776  }
5777 
5778  if (exten && !counters.extension_existence) {
5779  if (context)
5780  ast_cli(a->fd, "There is no existence of %s@%s extension\n",
5781  exten, context);
5782  else
5783  ast_cli(a->fd,
5784  "There is no existence of '%s' extension in all contexts\n",
5785  exten);
5786  return CLI_FAILURE;
5787  }
5788 
5789  ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
5790  counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
5791  counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
5792  counters.total_context, counters.total_context == 1 ? "context" : "contexts");
5793 
5794  /* everything ok */
5795  return CLI_SUCCESS;
5796 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const char * line
Definition: cli.h:162
#define ast_strlen_zero(foo)
Definition: strings.h:52
const int fd
Definition: cli.h:159
const int n
Definition: cli.h:165
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define AST_PBX_MAX_STACK
Definition: extconf.h:226
#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:5447
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
char * strsep(char **str, const char *delims)
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:5516
const int pos
Definition: cli.h:164
Counters for the show dialplan manager command.
Definition: pbx.c:5477
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

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

References a, ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_log, ast_malloc, 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_cli_args::fd, ast_hint::last_presence_state, ast_hint::laststate, ast_cli_args::line, LOG_ERROR, LOG_WARNING, ast_cli_args::n, NULL, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

5305 {
5306  struct ast_hint *hint;
5307  int watchers;
5308  int num = 0, extenlen;
5309  struct ao2_iterator i;
5311 
5312  switch (cmd) {
5313  case CLI_INIT:
5314  e->command = "core show hint";
5315  e->usage =
5316  "Usage: core show hint <exten>\n"
5317  " List registered hint.\n"
5318  " Hint details are shown in five columns. In order from left to right, they are:\n"
5319  " 1. Hint extension URI.\n"
5320  " 2. List of mapped device or presence state identifiers.\n"
5321  " 3. Current extension state. The aggregate of mapped device states.\n"
5322  " 4. Current presence state for the mapped presence state provider.\n"
5323  " 5. Watchers - number of subscriptions and other entities watching this hint.\n";
5324  return NULL;
5325  case CLI_GENERATE:
5326  return complete_core_show_hint(a->line, a->word, a->pos, a->n);
5327  }
5328 
5329  if (a->argc < 4)
5330  return CLI_SHOWUSAGE;
5331 
5332  if (ao2_container_count(hints) == 0) {
5333  ast_cli(a->fd, "There are no registered dialplan hints\n");
5334  return CLI_SUCCESS;
5335  }
5336 
5337  extenlen = strlen(a->argv[3]);
5338  i = ao2_iterator_init(hints, 0);
5339  for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
5340  ao2_lock(hint);
5341  if (!hint->exten) {
5342  /* The extension has already been destroyed */
5343  ao2_unlock(hint);
5344  continue;
5345  }
5346  if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
5347  watchers = ao2_container_count(hint->callbacks);
5348  sprintf(buf, "%s@%s",
5351  ast_cli(a->fd, "%-20.20s: %-20.20s State:%-15.15s Presence:%-15.15s Watchers %2d\n",
5352  buf,
5356  watchers);
5357  num++;
5358  }
5359  ao2_unlock(hint);
5360  }
5362  if (!num)
5363  ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
5364  else
5365  ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
5366  return CLI_SUCCESS;
5367 }
struct ast_context * ast_get_extension_context(struct ast_exten *exten)
Definition: pbx.c:8543
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
const int argc
Definition: cli.h:160
Definition: cli.h:152
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int last_presence_state
Definition: pbx.c:338
const char * line
Definition: cli.h:162
const int fd
Definition: cli.h:159
const int n
Definition: cli.h:165
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
const char *const * argv
Definition: cli.h:161
struct ast_exten * exten
Hint extension.
Definition: pbx.c:331
int laststate
Definition: pbx.c:335
#define CLI_SHOWUSAGE
Definition: cli.h:45
Structure for dial plan hints.
Definition: pbx.c:324
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
struct ao2_container * callbacks
Definition: pbx.c:332
#define AST_MAX_CONTEXT
Definition: channel.h:136
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
static char * complete_core_show_hint(const char *line, const char *word, int pos, int state)
autocomplete for CLI command &#39;core show hint&#39;
Definition: pbx.c:5268
const int pos
Definition: cli.h:164
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8596
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
const char * ast_extension_state2str(int extension_state)
Return extension_state as string.
Definition: pbx.c:3126
const char * ast_presence_state2str(enum ast_presence_state state)
Convert presence state to text string for output.

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

References 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_cli_args::fd, ast_hint::last_presence_state, ast_hint::laststate, NULL, and ast_cli_entry::usage.

5206 {
5207  struct ast_hint *hint;
5208  int num = 0;
5209  int watchers;
5210  struct ao2_iterator i;
5212 
5213  switch (cmd) {
5214  case CLI_INIT:
5215  e->command = "core show hints";
5216  e->usage =
5217  "Usage: core show hints\n"
5218  " List registered hints.\n"
5219  " Hint details are shown in five columns. In order from left to right, they are:\n"
5220  " 1. Hint extension URI.\n"
5221  " 2. List of mapped device or presence state identifiers.\n"
5222  " 3. Current extension state. The aggregate of mapped device states.\n"
5223  " 4. Current presence state for the mapped presence state provider.\n"
5224  " 5. Watchers - number of subscriptions and other entities watching this hint.\n";
5225  return NULL;
5226  case CLI_GENERATE:
5227  return NULL;
5228  }
5229 
5230  if (ao2_container_count(hints) == 0) {
5231  ast_cli(a->fd, "There are no registered dialplan hints\n");
5232  return CLI_SUCCESS;
5233  }
5234  /* ... we have hints ... */
5235  ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n");
5236 
5237  i = ao2_iterator_init(hints, 0);
5238  for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
5239  ao2_lock(hint);
5240  if (!hint->exten) {
5241  /* The extension has already been destroyed */
5242  ao2_unlock(hint);
5243  continue;
5244  }
5245  watchers = ao2_container_count(hint->callbacks);
5246  snprintf(buf, sizeof(buf), "%s@%s",
5249 
5250  ast_cli(a->fd, "%-20.20s: %-20.20s State:%-15.15s Presence:%-15.15s Watchers %2d\n",
5251  buf,
5255  watchers);
5256 
5257  ao2_unlock(hint);
5258  num++;
5259  }
5261 
5262  ast_cli(a->fd, "----------------\n");
5263  ast_cli(a->fd, "- %d hints registered\n", num);
5264  return CLI_SUCCESS;
5265 }
struct ast_context * ast_get_extension_context(struct ast_exten *exten)
Definition: pbx.c:8543
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Definition: cli.h:152
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int last_presence_state
Definition: pbx.c:338
const int fd
Definition: cli.h:159
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_exten * exten
Hint extension.
Definition: pbx.c:331
int laststate
Definition: pbx.c:335
Structure for dial plan hints.
Definition: pbx.c:324
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
struct ao2_container * callbacks
Definition: pbx.c:332
#define AST_MAX_CONTEXT
Definition: channel.h:136
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8596
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
const char * ast_extension_state2str(int extension_state)
Return extension_state as string.
Definition: pbx.c:3126
const char * ast_presence_state2str(enum ast_presence_state state)
Convert presence state to text string for output.

◆ handle_unset_extenpatternmatchnew()

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

Definition at line 6133 of file pbx.c.

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

6134 {
6135  int oldval = 0;
6136 
6137  switch (cmd) {
6138  case CLI_INIT:
6139  e->command = "dialplan set extenpatternmatchnew false";
6140  e->usage =
6141  "Usage: dialplan set extenpatternmatchnew true|false\n"
6142  " Use the NEW extension pattern matching algorithm, true or false.\n";
6143  return NULL;
6144  case CLI_GENERATE:
6145  return NULL;
6146  }
6147 
6148  if (a->argc != 4)
6149  return CLI_SHOWUSAGE;
6150 
6151  oldval = pbx_set_extenpatternmatchnew(0);
6152 
6153  if (!oldval)
6154  ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
6155  else
6156  ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
6157 
6158  return CLI_SUCCESS;
6159 }
int pbx_set_extenpatternmatchnew(int newval)
Definition: pbx.c:4781
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const int fd
Definition: cli.h:159
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44

◆ hashtab_compare_exten_labels()

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

Definition at line 728 of file pbx.c.

References bc, ast_exten::label, and S_OR.

Referenced by ast_add_extension2_lockopt().

729 {
730  const struct ast_exten *ac = ah_a;
731  const struct ast_exten *bc = ah_b;
732  return strcmp(S_OR(ac->label, ""), S_OR(bc->label, ""));
733 }
const char * label
Definition: pbx.c:244
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
#define bc
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79

◆ hashtab_compare_exten_numbers()

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

Definition at line 721 of file pbx.c.

References bc, and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

722 {
723  const struct ast_exten *ac = ah_a;
724  const struct ast_exten *bc = ah_b;
725  return ac->priority != bc->priority;
726 }
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
#define bc
int priority
Definition: pbx.c:243

◆ hashtab_compare_extens()

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

Definition at line 693 of file pbx.c.

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

694 {
695  const struct ast_exten *ac = ah_a;
696  const struct ast_exten *bc = ah_b;
697  int x = strcmp(ac->exten, bc->exten);
698  if (x) { /* if exten names are diff, then return */
699  return x;
700  }
701 
702  /* but if they are the same, do the cidmatch values match? */
703  /* not sure which side may be using ast_ext_matchcid_types, so check both */
705  return 0;
706  }
708  return 0;
709  }
710  if (ac->matchcid != bc->matchcid) {
711  return 1;
712  }
713  /* all other cases already disposed of, match now required on callerid string (cidmatch) */
714  /* although ast_add_extension2_lockopt() enforces non-zero ptr, caller may not have */
716  return 0;
717  }
718  return strcmp(ac->cidmatch, bc->cidmatch);
719 }
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
#define bc
#define ast_strlen_zero(foo)
Definition: strings.h:52
int matchcid
Definition: pbx.c:240
char * exten
Definition: pbx.c:238
const char * cidmatch
Definition: pbx.c:241

◆ hashtab_hash_extens()

static unsigned int hashtab_hash_extens ( const void *  obj)
static

Definition at line 741 of file pbx.c.

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

742 {
743  const struct ast_exten *ac = obj;
744  unsigned int x = ast_hashtab_hash_string(ac->exten);
745  unsigned int y = 0;
746  if (ac->matchcid == AST_EXT_MATCHCID_ON)
748  return x+y;
749 }
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
int matchcid
Definition: pbx.c:240
char * exten
Definition: pbx.c:238
unsigned int ast_hashtab_hash_string(const void *obj)
Hashes a string to a number.
Definition: hashtab.c:153
const char * cidmatch
Definition: pbx.c:241

◆ hashtab_hash_labels()

static unsigned int hashtab_hash_labels ( const void *  obj)
static

Definition at line 757 of file pbx.c.

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

Referenced by ast_add_extension2_lockopt().

758 {
759  const struct ast_exten *ac = obj;
760  return ast_hashtab_hash_string(S_OR(ac->label, ""));
761 }
const char * label
Definition: pbx.c:244
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
unsigned int ast_hashtab_hash_string(const void *obj)
Hashes a string to a number.
Definition: hashtab.c:153
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79

◆ hashtab_hash_priority()

static unsigned int hashtab_hash_priority ( const void *  obj)
static

Definition at line 751 of file pbx.c.

References ast_hashtab_hash_int(), and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

752 {
753  const struct ast_exten *ac = obj;
754  return ast_hashtab_hash_int(ac->priority);
755 }
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
int priority
Definition: pbx.c:243
unsigned int ast_hashtab_hash_int(const int num)
Definition: hashtab.c:205

◆ hint_cmp()

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

Definition at line 8889 of file pbx.c.

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

Referenced by ast_pbx_init().

8890 {
8891  const struct ast_hint *hint = obj;
8892  const struct ast_exten *exten = arg;
8893 
8894  return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
8895 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
struct ast_exten * exten
Hint extension.
Definition: pbx.c:331
Structure for dial plan hints.
Definition: pbx.c:324

◆ hint_hash()

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

Definition at line 8869 of file pbx.c.

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

Referenced by ast_pbx_init().

8870 {
8871  const struct ast_hint *hint = obj;
8872  const char *exten_name;
8873  int res;
8874 
8875  exten_name = ast_get_extension_name(hint->exten);
8876  if (ast_strlen_zero(exten_name)) {
8877  /*
8878  * If the exten or extension name isn't set, return 0 so that
8879  * the ao2_find() search will start in the first bucket.
8880  */
8881  res = 0;
8882  } else {
8883  res = ast_str_case_hash(exten_name);
8884  }
8885 
8886  return res;
8887 }
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_exten * exten
Hint extension.
Definition: pbx.c:331
Structure for dial plan hints.
Definition: pbx.c:324
static const char exten_name[]
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:1250

◆ hint_id_cmp()

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

Definition at line 3891 of file pbx.c.

References CMP_MATCH, CMP_STOP, and ast_state_cb::id.

Referenced by ast_add_hint().

3892 {
3893  const struct ast_state_cb *cb = obj;
3894  int *id = arg;
3895 
3896  return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0;
3897 }
ast_state_cb: An extension state notify register item
Definition: pbx.c:301
int id
Definition: pbx.c:303

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

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

422 {
423  struct ast_hintdevice *left = obj;
424  struct ast_hintdevice *right = arg;
425  const char *right_key = arg;
426  int cmp;
427 
428  switch (flags & OBJ_SEARCH_MASK) {
429  case OBJ_SEARCH_OBJECT:
430  right_key = right->hintdevice;
431  /* Fall through */
432  case OBJ_SEARCH_KEY:
433  cmp = strcasecmp(left->hintdevice, right_key);
434  break;
436  /*
437  * We could also use a partial key struct containing a length
438  * so strlen() does not get called for every comparison instead.
439  */
440  cmp = strncmp(left->hintdevice, right_key, strlen(right_key));
441  break;
442  default:
443  ast_assert(0);
444  cmp = 0;
445  break;
446  }
447  return cmp ? 0 : CMP_MATCH;
448 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
char hintdevice[1]
Definition: pbx.c:376
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Structure for dial plan hint devices.
Definition: pbx.c:369
Search option field mask.
Definition: astobj2.h:1076

◆ hintdevice_destroy()

static void hintdevice_destroy ( void *  obj)
static

Definition at line 540 of file pbx.c.

References ao2_ref, ast_hintdevice::hint, and NULL.

Referenced by add_hintdevice().

541 {
542  struct ast_hintdevice *doomed = obj;
543 
544  if (doomed->hint) {
545  ao2_ref(doomed->hint, -1);
546  doomed->hint = NULL;
547  }
548 }
struct ast_hint * hint
Hint this hintdevice belongs to.
Definition: pbx.c:374
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Structure for dial plan hint devices.
Definition: pbx.c:369

◆ hintdevice_hash_cb()

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

Definition at line 395 of file pbx.c.

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

396 {
397  const struct ast_hintdevice *ext;
398  const char *key;
399 
400  switch (flags & OBJ_SEARCH_MASK) {
401  case OBJ_SEARCH_KEY:
402  key = obj;
403  break;
404  case OBJ_SEARCH_OBJECT:
405  ext = obj;
406  key = ext->hintdevice;
407  break;
408  default:
409  ast_assert(0);
410  return 0;
411  }
412 
413  return ast_str_case_hash(key);
414 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
const char * ext
Definition: http.c:147
char hintdevice[1]
Definition: pbx.c:376
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Structure for dial plan hint devices.
Definition: pbx.c:369
Search option field mask.
Definition: astobj2.h:1076
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:1250

◆ hintdevice_remove_cb()

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

Definition at line 504 of file pbx.c.

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

Referenced by remove_hintdevice().

505 {
506  struct ast_hintdevice *candidate = obj;
507  char *device = arg;
508  struct ast_hint *hint = data;
509 
510  if (!strcasecmp(candidate->hintdevice, device)
511  && candidate->hint == hint) {
512  return CMP_MATCH;
513  }
514  return 0;
515 }
struct ast_hint * hint
Hint this hintdevice belongs to.
Definition: pbx.c:374
char hintdevice[1]
Definition: pbx.c:376
Structure for dial plan hints.
Definition: pbx.c:324
Structure for dial plan hint devices.
Definition: pbx.c:369

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

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

Referenced by ast_pbx_run_args(), and ast_pbx_start().

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

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

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

Referenced by add_pattern_node().

1419 {
1420  struct match_char *curr, *lcurr;
1421 
1422  /* insert node into the tree at "current", so the alt_char list from current is
1423  sorted in increasing value as you go to the leaves */
1424  if (!(*parent_ptr)) {
1425  *parent_ptr = node;
1426  return;
1427  }
1428 
1429  if ((*parent_ptr)->specificity > node->specificity) {
1430  /* insert at head */
1431  node->alt_char = (*parent_ptr);
1432  *parent_ptr = node;
1433  return;
1434  }
1435 
1436  lcurr = *parent_ptr;
1437  for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
1438  if (curr->specificity > node->specificity) {
1439  node->alt_char = curr;
1440  lcurr->alt_char = node;
1441  break;
1442  }
1443  lcurr = curr;
1444  }
1445 
1446  if (!curr) {
1447  lcurr->alt_char = node;
1448  }
1449 
1450 }
int specificity
Definition: pbx.c:265
struct match_char * alt_char
Definition: pbx.c:266
match_char: forms a syntax tree for quick matching of extension patterns
Definition: pbx.c:261

◆ internal_extension_state_extended()

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

Definition at line 3141 of file pbx.c.

References ao2_lock, ao2_unlock, ast_exten::app, ast_add_extension(), ast_extension_state2(), ast_free_ptr(), ast_hint_extension(), ast_strdup, 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().

3143 {
3144  struct ast_exten *e;
3145 
3146  if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */
3147  return -1; /* No hint, return -1 */
3148  }
3149 
3150  if (e->exten[0] == '_') {
3151  /* Create this hint on-the-fly, we explicitly lock hints here to ensure the
3152  * same locking order as if this were done through configuration file - that is
3153  * hints is locked first and then (if needed) contexts is locked
3154  */
3155  ao2_lock(hints);
3156  ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
3157  e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
3158  e->registrar);
3159  ao2_unlock(hints);
3160  if (!(e = ast_hint_extension(c, context, exten))) {
3161  /* Improbable, but not impossible */
3162  return -1;
3163  }
3164  }
3165 
3166  return ast_extension_state2(e, device_state_info); /* Check all devices in the hint */
3167 }
const char * label
Definition: pbx.c:244
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1771
const char * registrar
Definition: pbx.c:253
int matchcid
Definition: pbx.c:240
int priority
Definition: pbx.c:243
static int ast_extension_state2(struct ast_exten *e, struct ao2_container *device_state_info)
Check state of extension by using hints.
Definition: pbx.c:3113
static struct ast_exten * ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
Definition: pbx.c:2997
#define ao2_lock(a)
Definition: astobj2.h:718
char * exten
Definition: pbx.c:238
char name[0]
Definition: pbx.c:297
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:6970
const char * cidmatch
Definition: pbx.c:241
const char * app
Definition: pbx.c:246
struct ast_context * parent
Definition: pbx.c:245
void * data
Definition: pbx.c:248
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ load_pbx()

int load_pbx ( void  )

Provided by pbx.c

Definition at line 8460 of file pbx.c.

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(), EVENT_FLAG_CALL, EVENT_FLAG_CONFIG, EVENT_FLAG_REPORTING, manager_show_dialplan(), NULL, presence_state_cb(), stasis_subscribe, stasis_subscription_accept_message_type(), STASIS_SUBSCRIPTION_FILTER_SELECTIVE, stasis_subscription_set_filter(), and unload_pbx().

Referenced by asterisk_daemon().

8461 {
8462  int res = 0;
8463 
8465 
8466  /* Initialize the PBX */
8467  ast_verb(1, "Asterisk PBX Core Initializing\n");
8468 
8469  ast_verb(2, "Registering builtin functions:\n");
8473 
8474  /* Register manager application */
8477 
8478  if (res) {
8479  return -1;
8480  }
8481 
8483  return -1;
8484  }
8486  stasis_subscription_accept_message_type(device_state_sub, hint_change_message_type());
8487  stasis_subscription_accept_message_type(device_state_sub, hint_remove_message_type());
8489 
8491  return -1;
8492  }
8495 
8496  return 0;
8497 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static struct stasis_subscription * presence_state_sub
Subscription for presence state change events.
Definition: pbx.c:770
#define EVENT_FLAG_CALL
Definition: manager.h:72
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:1079
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static struct ast_cli_entry pbx_cli[]
Definition: pbx.c:6164
#define NULL
Definition: resample.c:96
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:197
#define ast_verb(level,...)
Definition: logger.h:463
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
static void presence_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
Definition: pbx.c:8333
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
static struct ast_custom_function testtime_function
Definition: pbx.c:8316
static void unload_pbx(void)
Definition: pbx.c:8448
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:652
#define EVENT_FLAG_CONFIG
Definition: manager.h:78
static int manager_show_dialplan(struct mansession *s, const struct message *m)
Manager listing of dial plan.
Definition: pbx.c:6019
static void device_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
Definition: pbx.c:3584
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
Definition: devicestate.c:668
static int action_extensionstatelist(struct mansession *s, const struct message *m)
Definition: pbx.c:8383
static struct ast_custom_function exception_function
Definition: pbx.c:2852
#define EVENT_FLAG_REPORTING
Definition: manager.h:80
struct stasis_message_type * ast_presence_state_message_type(void)
Get presence state message type.
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:1025
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.
static struct stasis_subscription * device_state_sub
Subscription for device state change events.
Definition: pbx.c:768

◆ manager_dpsendack()

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

Send ack once.

Definition at line 5855 of file pbx.c.

References astman_send_listack().

Referenced by manager_show_dialplan(), and manager_show_dialplan_helper().

5856 {
5857  astman_send_listack(s, m, "DialPlan list will follow", "start");
5858 }
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:3201

◆ manager_show_dialplan()

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

Manager listing of dial plan.

Definition at line 6019 of file pbx.c.

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(), context, dialplan_counters::context_existence, ast_exten::exten, 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().

6020 {
6021  const char *exten, *context;
6022  const char *id = astman_get_header(m, "ActionID");
6023  const char *incstack[AST_PBX_MAX_STACK];
6024  char idtext[256];
6025 
6026  /* Variables used for different counters */
6027  struct dialplan_counters counters;
6028 
6029  if (!ast_strlen_zero(id))
6030  snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
6031  else
6032  idtext[0] = '\0';
6033 
6034  memset(&counters, 0, sizeof(counters));
6035 
6036  exten = astman_get_header(m, "Extension");
6037  context = astman_get_header(m, "Context");
6038 
6039  manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL, 0, incstack);
6040 
6041  if (!ast_strlen_zero(context) && !counters.context_existence) {
6042  char errorbuf[BUFSIZ];
6043 
6044  snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
6045  astman_send_error(s, m, errorbuf);
6046  return 0;
6047  }
6048  if (!ast_strlen_zero(exten) && !counters.extension_existence) {
6049  char errorbuf[BUFSIZ];
6050 
6051  if (!ast_strlen_zero(context))
6052  snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
6053  else
6054  snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
6055  astman_send_error(s, m, errorbuf);
6056  return 0;
6057  }
6058 
6059  if (!counters.total_items) {
6060  manager_dpsendack(s, m);
6061  }
6062 
6063  astman_send_list_complete_start(s, m, "ShowDialPlanComplete", counters.total_items);
6064  astman_append(s,
6065  "ListExtensions: %d\r\n"
6066  "ListPriorities: %d\r\n"
6067  "ListContexts: %d\r\n",
6068  counters.total_exten, counters.total_prio, counters.total_context);
6070 
6071  /* everything ok */
6072  return 0;
6073 }
static void manager_dpsendack(struct mansession *s, const struct message *m)
Send ack once.
Definition: pbx.c:5855
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
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:3237
#define NULL
Definition: resample.c:96
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
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&#39;s show dial...
Definition: pbx.c:5864
#define AST_PBX_MAX_STACK
Definition: extconf.h:226
Counters for the show dialplan manager command.
Definition: pbx.c:5477
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159

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

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, dialplan_counters::extension_existence, LOG_WARNING, manager_dpsendack(), 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().

5869 {
5870  struct ast_context *c;
5871  int res = 0, old_total_exten = dpc->total_exten;
5872 
5873  if (ast_strlen_zero(exten))
5874  exten = NULL;
5875  if (ast_strlen_zero(context))
5876  context = NULL;
5877 
5878  ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
5879 
5880  /* try to lock contexts */
5881  if (ast_rdlock_contexts()) {
5882  astman_send_error(s, m, "Failed to lock contexts");
5883  ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
5884  return -1;
5885  }
5886 
5887  c = NULL; /* walk all contexts ... */
5888  while ( (c = ast_walk_contexts(c)) ) {
5889  int idx;
5890  struct ast_exten *e;
5891 
5892  if (context && strcmp(ast_get_context_name(c), context) != 0)
5893  continue; /* not the name we want */
5894 
5895  dpc->context_existence = 1;
5896  dpc->total_context++;
5897 
5898  ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
5899 
5900  if (ast_rdlock_context(c)) { /* failed to lock */
5901  ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
5902  continue;
5903  }
5904 
5905  /* XXX note- an empty context is not printed */
5906  e = NULL; /* walk extensions in context */
5907  while ( (e = ast_walk_context_extensions(c, e)) ) {
5908  struct ast_exten *p;
5909 
5910  /* looking for extension? is this our extension? */
5912  /* not the one we are looking for, continue */
5913  ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
5914  continue;
5915  }
5916  ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
5917 
5918  dpc->extension_existence = 1;
5919 
5920  dpc->total_exten++;
5921 
5922  p = NULL; /* walk next extension peers */
5923  while ( (p = ast_walk_extension_priorities(e, p)) ) {
5924  int prio = ast_get_extension_priority(p);
5925 
5926  dpc->total_prio++;
5927  if (!dpc->total_items++)
5928  manager_dpsendack(s, m);
5929  astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
5930  astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
5931 
5932  /* XXX maybe make this conditional, if p != e ? */
5933  if (ast_get_extension_label(p))
5934  astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
5935 
5936  if (prio == PRIORITY_HINT) {
5937  astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
5938  } else {
5939  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));
5940  }
5941  astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
5942  }
5943  }
5944 
5945  for (idx = 0; idx < ast_context_includes_count(c); idx++) {
5946  const struct ast_include *i = ast_context_includes_get(c, idx);
5947 
5948  if (exten) {
5949  /* Check all includes for the requested extension */
5950  if (includecount >= AST_PBX_MAX_STACK) {
5951  ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
5952  } else {
5953  int dupe = 0;
5954  int x;
5955  for (x = 0; x < includecount; x++) {
5956  if (!strcasecmp(includes[x], ast_get_include_name(i))) {
5957  dupe++;
5958  break;
5959  }
5960  }
5961  if (!dupe) {
5962  includes[includecount] = ast_get_include_name(i);
5963  manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
5964  } else {
5965  ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
5966  }
5967  }
5968  } else {
5969  if (!dpc->total_items++)
5970  manager_dpsendack(s, m);
5971  astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
5972  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));
5973  astman_append(s, "\r\n");
5974  ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
5975  }
5976  }
5977 
5978  for (idx = 0; idx < ast_context_ignorepats_count(c); idx++) {
5979  const struct ast_ignorepat *ip = ast_context_ignorepats_get(c, idx);
5980  const char *ipname = ast_get_ignorepat_name(ip);
5981  char ignorepat[AST_MAX_EXTENSION];
5982 
5983  snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
5984  if (!exten || ast_extension_match(ignorepat, exten)) {
5985  if (!dpc->total_items++)
5986  manager_dpsendack(s, m);
5987  astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
5988  astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
5989  astman_append(s, "\r\n");
5990  }
5991  }
5992  if (!rinclude) {
5993  for (idx = 0; idx < ast_context_switches_count(c); idx++) {
5994  const struct ast_sw *sw = ast_context_switches_get(c, idx);
5995 
5996  if (!dpc->total_items++)
5997  manager_dpsendack(s, m);
5998  astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
5999  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));
6000  astman_append(s, "\r\n");
6001  ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
6002  }
6003  }
6004 
6005  ast_unlock_context(c);
6006  }
6008 
6009  if (dpc->total_exten == old_total_exten) {
6010  ast_debug(3, "manager_show_dialplan: Found nothing new\n");
6011  /* Nothing new under the sun */
6012  return -1;
6013  } else {
6014  return res;
6015  }
6016 }
static void manager_dpsendack(struct mansession *s, const struct message *m)
Send ack once.
Definition: pbx.c:5855
ast_include: include= support in extensions.conf
Definition: pbx_include.c:37
const char * ast_get_switch_name(const struct ast_sw *sw)
Definition: pbx_sw.c:48
const char * ast_get_switch_registrar(const struct ast_sw *sw)
Definition: pbx_sw.c:63
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
int ast_context_switches_count(const struct ast_context *con)
Definition: pbx.c:8652
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8530
int total_items
Definition: pbx.c:5478
int total_exten
Definition: pbx.c:5480
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition: pbx.c:8525
const char * ast_get_ignorepat_registrar(const struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:47
const struct ast_ignorepat * ast_context_ignorepats_get(const struct ast_context *con, int idx)
Definition: pbx.c:8745
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: pbx.c:8609
#define LOG_WARNING
Definition: logger.h:274
void * ast_get_extension_app_data(struct ast_exten *e)
Definition: pbx.c:8601
const struct ast_sw * ast_context_switches_get(const struct ast_context *con, int idx)
Definition: pbx.c:8657
int context_existence
Definition: pbx.c:5482
const char * ast_get_include_registrar(const struct ast_include *i)
Definition: pbx_include.c:60
static struct test_val c
#define NULL
Definition: resample.c:96
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8507
const char * ast_get_extension_registrar(struct ast_exten *e)
Definition: pbx.c:8571
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *exten)
Definition: pbx.c:8614
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
ast_sw: Switch statement in extensions.conf
Definition: pbx_sw.c:37
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define PRIORITY_HINT
Definition: pbx.h:54
const char * ast_get_ignorepat_name(const struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:42
int ast_context_ignorepats_count(const struct ast_context *con)
Definition: pbx.c:8740
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&#39;s show dial...
Definition: pbx.c:5864
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
ast_ignorepat: Ignore patterns in dial plan
Definition: pbx_ignorepat.c:37
int ast_extension_match(const char *pattern, const char *data)
Determine if a given extension matches a given pattern (in NXX format)
Definition: pbx.c:2413
#define AST_PBX_MAX_STACK
Definition: extconf.h:226
struct ast_exten * ast_walk_extension_priorities(struct ast_exten *exten, struct ast_exten *priority)
Definition: pbx.c:8662
const char * ast_get_switch_data(const struct ast_sw *sw)
Definition: pbx_sw.c:53
const char * ast_get_include_name(const struct ast_include *include)
Definition: pbx_include.c:50
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8596
int total_prio
Definition: pbx.c:5481
const struct ast_include * ast_context_includes_get(const struct ast_context *con, int idx)
Definition: pbx.c:8702
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
const char * ast_get_extension_label(struct ast_exten *exten)
Definition: pbx.c:8553
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
int total_context
Definition: pbx.c:5479
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
int ast_get_extension_priority(struct ast_exten *exten)
Definition: pbx.c:8558
int extension_existence
Definition: pbx.c:5483
int ast_context_includes_count(const struct ast_context *con)
Definition: pbx.c:8697

◆ matchcid()

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

Definition at line 2473 of file pbx.c.

References ast_extension_match(), and ast_strlen_zero.

2474 {
2475  /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
2476  failing to get a number should count as a match, otherwise not */
2477 
2478  if (ast_strlen_zero(callerid)) {
2479  return ast_strlen_zero(cidpattern) ? 1 : 0;
2480  }
2481 
2482  return ast_extension_match(cidpattern, callerid);
2483 }
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_extension_match(const char *pattern, const char *data)
Determine if a given extension matches a given pattern (in NXX format)
Definition: pbx.c:2413

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

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_MATCHER_CHK_MATCH, NEW_MATCHER_RECURSE, match_char::next_char, match_char::specificity, str, update_scoreboard(), and match_char::x.

Referenced by pbx_find_extension().

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

◆ parse_hint_device()

static char * parse_hint_device ( struct ast_str hint_args)
static

Definition at line 3056 of file pbx.c.

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

Referenced by ast_extension_state3(), and remove_hintdevice().

3057 {
3058  char *copy = ast_strdupa(ast_str_buffer(hint_args));
3059  char *tmp;
3060 
3061  if ((tmp = strrchr(copy, ','))) {
3062  *tmp = '\0';
3063  }
3064 
3065  ast_str_set(&hint_args, 0, "%s", copy);
3066  return ast_str_buffer(hint_args);
3067 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
static int tmp()
Definition: bt_open.c:389
static int copy(char *infile, char *outfile)
Utility function to copy a file.
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:1065
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300

◆ parse_hint_presence()

static char* parse_hint_presence ( struct ast_str hint_args)
static

Definition at line 3037 of file pbx.c.

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

Referenced by extension_presence_state_helper().

3038 {
3039  char *copy = ast_strdupa(ast_str_buffer(hint_args));
3040  char *tmp = "";
3041 
3042  if ((tmp = strrchr(copy, ','))) {
3043  *tmp = '\0';
3044  tmp++;
3045  } else {
3046  return NULL;
3047  }
3048  ast_str_set(&hint_args, 0, "%s", tmp);
3049  return ast_str_buffer(hint_args);
3050 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
static int tmp()
Definition: bt_open.c:389
static int copy(char *infile, char *outfile)
Utility function to copy a file.
#define NULL
Definition: resample.c:96
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:1065
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300

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

References ast_strlen_zero.

Referenced by _if_exec(), _macro_exec(), _while_exec(), acf_if(), execif_exec(), gosubif_exec(), macroif_exec(), pbx_builtin_gotoif(), and testtime_write().

8322 {
8323  int res;
8324  if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */
8325  return 0;
8326  } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
8327  return res;
8328  } else { /* Strings are true */
8329  return 1;
8330  }
8331 }
#define ast_strlen_zero(foo)
Definition: strings.h:52

◆ pbx_destroy()

static void pbx_destroy ( struct ast_pbx p)
static

Definition at line 985 of file pbx.c.

References ast_free.

Referenced by __ast_pbx_run().

986 {
987  ast_free(p);
988 }
#define ast_free(a)
Definition: astmm.h:182

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

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

7717 {
7718  enum ast_control_frame_type pbx_reason;
7719 
7720  if (dial_result == AST_DIAL_RESULT_ANSWERED) {
7721  /* Remote end answered. */
7722  pbx_reason = AST_CONTROL_ANSWER;
7723  } else if (dial_result == AST_DIAL_RESULT_HANGUP) {
7724  /* Caller hungup */
7725  pbx_reason = AST_CONTROL_HANGUP;
7726  } else {
7727  switch (cause) {
7728  case AST_CAUSE_USER_BUSY:
7729  pbx_reason = AST_CONTROL_BUSY;
7730  break;
7737  pbx_reason = AST_CONTROL_CONGESTION;
7738  break;
7740  case AST_CAUSE_NO_ANSWER:
7741  /* Remote end was ringing (but isn't anymore) */
7742  pbx_reason = AST_CONTROL_RINGING;
7743  break;
7744  case AST_CAUSE_UNALLOCATED:
7745  default:
7746  /* Call Failure (not BUSY, and not NO_ANSWER, maybe Circuit busy or down?) */
7747  pbx_reason = 0;
7748  break;
7749  }
7750  }
7751 
7752  return pbx_reason;
7753 }
#define AST_CAUSE_NORMAL_TEMPORARY_FAILURE
Definition: causes.h:121
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:122
#define AST_CAUSE_UNALLOCATED
Definition: causes.h:97
#define AST_CAUSE_NETWORK_OUT_OF_ORDER
Definition: causes.h:120
ast_control_frame_type
Internal control frame subtype field values.
#define AST_CAUSE_NORMAL_CIRCUIT_CONGESTION
Definition: causes.h:119
#define AST_CAUSE_ANSWERED_ELSEWHERE
Definition: causes.h:113
#define AST_CAUSE_NO_ANSWER
Definition: causes.h:108
#define AST_CAUSE_DESTINATION_OUT_OF_ORDER
Definition: causes.h:114
#define AST_CAUSE_USER_BUSY
Definition: causes.h:106
#define AST_CAUSE_CALL_REJECTED
Definition: causes.h:110

◆ pbx_extension_helper()

static int pbx_extension_helper ( struct ast_channel c,
struct ast_context con,
const char *  context,
const char *  exten,
int  priority,
const char *  label,
const char *  callerid,
enum ext_match_t  action,
int *  found,
int  combined_find_spawn 
)
static

The return value depends on the action:

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

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

Definition at line 2875 of file pbx.c.

References ast_exten::app, app_name(), ast_channel_context(), ast_channel_context_set(), ast_channel_exten(), ast_channel_exten_set(), ast_channel_name(), ast_channel_priority_set(), ast_copy_string(), ast_debug, ast_log, ast_rdlock_contexts(), ast_strdupa, ast_strlen_zero, ast_unlock_contexts(), ast_verb, 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(), ast_exten::priority, S_OR, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, pbx_find_info::swo, tmp(), and VERBOSITY_ATLEAST.

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

2878 {
2879  struct ast_exten *e;
2880  struct ast_app *app;
2881  char *substitute = NULL;
2882  struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
2883  char passdata[EXT_DATA_SIZE];
2884  int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
2885 
2887 
2888  if (!context) {
2889  context = con->name;
2890  }
2891 
2892  if (found)
2893  *found = 0;
2894 
2895  e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
2896  if (e) {
2897  if (found)
2898  *found = 1;
2899  if (matching_action) {
2901  return -1; /* success, we found it */
2902  } else if (action == E_FINDLABEL) { /* map the label to a priority */
2903  int res = e->priority;
2904 
2906 
2907  /* the priority we were looking for */
2908  return res;
2909  } else { /* spawn */
2910  if (!e->cached_app)
2911  e->cached_app = pbx_findapp(e->app);
2912  app = e->cached_app;
2913  if (ast_strlen_zero(e->data)) {
2914  *passdata = '\0';
2915  } else {
2916  const char *tmp;
2917  if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
2918  /* no variables to substitute, copy on through */
2919  ast_copy_string(passdata, e->data, sizeof(passdata));
2920  } else {
2921  /* save e->data on stack for later processing after lock released */
2922  substitute = ast_strdupa(e->data);
2923  }
2924  }
2926  if (!app) {
2927  ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
2928  return -1;
2929  }
2930  if (ast_channel_context(c) != context)
2932  if (ast_channel_exten(c) != exten)
2935  if (substitute) {
2936  pbx_substitute_variables_helper(c, substitute, passdata, sizeof(passdata)-1);
2937  }
2938  ast_debug(1, "Launching '%s'\n", app_name(app));
2939  if (VERBOSITY_ATLEAST(3)) {
2940  ast_verb(3, "Executing [%s@%s:%d] " COLORIZE_FMT "(\"" COLORIZE_FMT "\", \"" COLORIZE_FMT "\") %s\n",
2942  COLORIZE(COLOR_BRCYAN, 0, app_name(app)),
2944  COLORIZE(COLOR_BRMAGENTA, 0, passdata),
2945  "in new stack");
2946  }
2947  return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */
2948  }
2949  } else if (q.swo) { /* not found here, but in another switch */
2950  if (found)
2951  *found = 1;
2953  if (matching_action) {
2954  return -1;
2955  } else {
2956  if (!q.swo->exec) {
2957  ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
2958  return -1;
2959  }
2960  return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
2961  }
2962  } else { /* not found anywhere, see what happened */
2964  /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
2965  switch (q.status) {
2966  case STATUS_NO_CONTEXT:
2967  if (!matching_action && !combined_find_spawn)
2968  ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
2969  break;
2970  case STATUS_NO_EXTENSION:
2971  if (!matching_action && !combined_find_spawn)
2972  ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
2973  break;
2974  case STATUS_NO_PRIORITY:
2975  if (!matching_action && !combined_find_spawn)
2976  ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
2977  break;
2978  case STATUS_NO_LABEL:
2979  if (context && !combined_find_spawn)
2980  ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, ""));
2981  break;
2982  default:
2983  ast_debug(1, "Shouldn't happen!\n");
2984  }
2985 
2986  return (matching_action) ? 0 : -1;
2987  }
2988 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
ast_switch_f * exec
Definition: pbx.h:167
#define EXT_DATA_SIZE
Definition: pbx.c:216
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
#define STATUS_NO_PRIORITY
Definition: pbx.c:2469
#define LOG_WARNING
Definition: logger.h:274
#define VERBOSITY_ATLEAST(level)
Definition: logger.h:461
struct ast_app * cached_app
Definition: pbx.c:247
static int tmp()
Definition: bt_open.c:389
#define STATUS_NO_EXTENSION
Definition: pbx.c:2468
#define NULL
Definition: resample.c:96
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8507
static int priority
#define ast_verb(level,...)
Definition: logger.h:463
#define COLOR_BRCYAN
Definition: term.h:60
#define COLORIZE(fg, bg, str)
Definition: term.h:68
#define ast_strlen_zero(foo)
Definition: strings.h:52
const char * name
Definition: pbx.h:162
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
int priority
Definition: pbx.c:243
#define ast_log
Definition: astobj2.c:42
const char * data
Definition: extconf.h:241
#define COLORIZE_FMT
Shortcut macros for coloring a set of text.
Definition: term.h:67
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define STATUS_NO_LABEL
Definition: pbx.c:2470
const char * ast_channel_exten(const struct ast_channel *chan)
#define COLOR_BRMAGENTA
Definition: term.h:58
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
char name[0]
Definition: pbx.c:297
#define STATUS_NO_CONTEXT
Definition: pbx.c:2467
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
#define LOG_NOTICE
Definition: logger.h:263
const char * foundcontext
Definition: extconf.h:242
int stacklen
Definition: extconf.h:238
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
const char * app
Definition: pbx.c:246
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
ast_app: A registered application
Definition: pbx_app.c:45
const char * ast_channel_name(const struct ast_channel *chan)
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: ael_main.c:211
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:2485
struct ast_switch * swo
Definition: extconf.h:240
const char * ast_channel_context(const struct ast_channel *chan)
void * data
Definition: pbx.c:248
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
void ast_channel_priority_set(struct ast_channel *chan, int value)
static const char app[]
Definition: app_mysql.c:62

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

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, context, create_match_char_tree(), pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_switch::exists, ast_exten::exten, scoreboard::exten, 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(), ast_exten::matchcid, ast_switch::matchmore, ast_exten::name, ast_context::name, new_find_extension(), scoreboard::node, NULL, ast_context::pattern_tree, pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, strsep(), switch_data, pbx_find_info::swo, tmp(), scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().

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

2489 {
2490  int x, res;
2491  struct ast_context *tmp = NULL;
2492  struct ast_exten *e = NULL, *eroot = NULL;
2493  struct ast_exten pattern = {NULL, };
2494  struct scoreboard score = {0, };
2495  struct ast_str *tmpdata = NULL;
2496  int idx;
2497 
2498  pattern.label = label;
2499  pattern.priority = priority;
2500 #ifdef NEED_DEBUG_HERE
2501  ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
2502 #endif
2503 
2504  /* Initialize status if appropriate */
2505  if (q->stacklen == 0) {
2507  q->swo = NULL;
2508  q->data = NULL;
2509  q->foundcontext = NULL;
2510  } else if (q->stacklen >= AST_PBX_MAX_STACK) {
2511  ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
2512  return NULL;
2513  }
2514 
2515  /* Check first to see if we've already been checked */
2516  for (x = 0; x < q->stacklen; x++) {
2517  if (!strcasecmp(q->incstack[x], context))
2518  return NULL;
2519  }
2520 
2521  if (bypass) { /* bypass means we only look there */
2522  tmp = bypass;
2523  } else { /* look in contexts */
2524  tmp = find_context(context);
2525  if (!tmp) {
2526  return NULL;
2527  }
2528  }
2529 
2530  if (q->status < STATUS_NO_EXTENSION)
2532 
2533  /* Do a search for matching extension */
2534 
2535  eroot = NULL;
2536  score.total_specificity = 0;
2537  score.exten = 0;
2538  score.total_length = 0;
2539  if (!tmp->pattern_tree && tmp->root_table) {
2541 #ifdef NEED_DEBUG
2542  ast_debug(1, "Tree Created in context %s:\n", context);
2543  log_match_char_tree(tmp->pattern_tree," ");
2544 #endif
2545  }
2546 #ifdef NEED_DEBUG
2547  ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
2548  log_match_char_tree(tmp->pattern_tree, ":: ");
2549 #endif
2550 
2551  do {
2553  char *osw = ast_strdupa(overrideswitch), *name;
2554  struct ast_switch *asw;
2555  ast_switch_f *aswf = NULL;
2556  char *datap;
2557  int eval = 0;
2558 
2559  name = strsep(&osw, "/");
2560  asw = pbx_findswitch(name);
2561 
2562  if (!asw) {
2563  ast_log(LOG_WARNING, "No such switch '%s'\n", name);
2564  break;
2565  }
2566 
2567  if (osw && strchr(osw, '$')) {
2568  eval = 1;
2569  }
2570 
2571  if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
2572  ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n");
2573  break;
2574  } else if (eval) {
2575  /* Substitute variables now */
2576  pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
2577  datap = ast_str_buffer(tmpdata);
2578  } else {
2579  datap = osw;
2580  }
2581 
2582  /* equivalent of extension_match_core() at the switch level */
2583  if (action == E_CANMATCH)
2584  aswf = asw->canmatch;
2585  else if (action == E_MATCHMORE)
2586  aswf = asw->matchmore;
2587  else /* action == E_MATCH */
2588  aswf = asw->exists;
2589  if (!aswf) {
2590  res = 0;
2591  } else {
2592  if (chan) {
2593  ast_autoservice_start(chan);
2594  }
2595  res = aswf(chan, context, exten, priority, callerid, datap);
2596  if (chan) {
2597  ast_autoservice_stop(chan);
2598  }
2599  }
2600  if (res) { /* Got a match */
2601  q->swo = asw;
2602  q->data = datap;
2603  q->foundcontext = context;
2604  /* XXX keep status = STATUS_NO_CONTEXT ? */
2605  return NULL;
2606  }
2607  }
2608  } while (0);
2609 
2610  if (extenpatternmatchnew) {
2611  new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
2612  eroot = score.exten;
2613 
2614  if (score.last_char == '!' && action == E_MATCHMORE) {
2615  /* We match an extension ending in '!'.
2616  * The decision in this case is final and is NULL (no match).
2617  */
2618 #ifdef NEED_DEBUG_HERE
2619  ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
2620 #endif
2621  return NULL;
2622  }
2623 
2624  if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
2625  q->status = STATUS_SUCCESS;
2626 #ifdef NEED_DEBUG_HERE
2627  ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
2628 #endif
2629  return score.canmatch_exten;
2630  }
2631 
2632  if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) {
2633  if (score.node) {
2634  struct ast_exten *z = trie_find_next_match(score.node);
2635  if (z) {
2636 #ifdef NEED_DEBUG_HERE
2637  ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
2638 #endif
2639  } else {
2640  if (score.canmatch_exten) {
2641 #ifdef NEED_DEBUG_HERE
2642  ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
2643 #endif
2644  return score.canmatch_exten;
2645  } else {
2646 #ifdef NEED_DEBUG_HERE
2647  ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
2648 #endif
2649  }
2650  }
2651  return z;
2652  }
2653 #ifdef NEED_DEBUG_HERE
2654  ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
2655 #endif
2656  return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */
2657  }
2658 
2659  if (eroot) {
2660  /* found entry, now look for the right priority */
2661  if (q->status < STATUS_NO_PRIORITY)
2663  e = NULL;
2664  if (action == E_FINDLABEL && label ) {
2665  if (q->status < STATUS_NO_LABEL)
2666  q->status = STATUS_NO_LABEL;
2667  e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
2668  } else {
2669  e = ast_hashtab_lookup(eroot->peer_table, &pattern);
2670  }
2671  if (e) { /* found a valid match */
2672  q->status = STATUS_SUCCESS;
2673  q->foundcontext = context;
2674 #ifdef NEED_DEBUG_HERE
2675  ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
2676 #endif
2677  return e;
2678  }
2679  }
2680  } else { /* the old/current default exten pattern match algorithm */
2681 
2682  /* scan the list trying to match extension and CID */
2683  eroot = NULL;
2684  while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
2685  int match = extension_match_core(eroot->exten, exten, action);
2686  /* 0 on fail, 1 on match, 2 on earlymatch */
2687 
2688  if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
2689  continue; /* keep trying */
2690  if (match == 2 && action == E_MATCHMORE) {
2691  /* We match an extension ending in '!'.
2692  * The decision in this case is final and is NULL (no match).
2693  */
2694  return NULL;
2695  }
2696  /* found entry, now look for the right priority */
2697  if (q->status < STATUS_NO_PRIORITY)
2699  e = NULL;
2700  if (action == E_FINDLABEL && label ) {
2701  if (q->status < STATUS_NO_LABEL)
2702  q->status = STATUS_NO_LABEL;
2703  e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
2704  } else {
2705  e = ast_hashtab_lookup(eroot->peer_table, &pattern);
2706  }
2707  if (e) { /* found a valid match */
2708  q->status = STATUS_SUCCESS;
2709  q->foundcontext = context;
2710  return e;
2711  }
2712  }
2713  }
2714 
2715  /* Check alternative switches */
2716  for (idx = 0; idx < ast_context_switches_count(tmp); idx++) {
2717  const struct ast_sw *sw = ast_context_switches_get(tmp, idx);
2718  struct ast_switch *asw = pbx_findswitch(ast_get_switch_name(sw));
2719  ast_switch_f *aswf = NULL;
2720  const char *datap;
2721 
2722  if (!asw) {
2723  ast_log(LOG_WARNING, "No such switch '%s'\n", ast_get_switch_name(sw));
2724  continue;
2725  }
2726 
2727  /* Substitute variables now */
2728  if (ast_get_switch_eval(sw)) {
2729  if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
2730  ast_log(LOG_WARNING, "Can't evaluate switch?!\n");
2731  continue;
2732  }
2734  ast_str_buffer(tmpdata), ast_str_size(tmpdata));
2735  datap = ast_str_buffer(tmpdata);
2736  } else {
2737  datap = ast_get_switch_data(sw);
2738  }
2739 
2740  /* equivalent of extension_match_core() at the switch level */
2741  if (action == E_CANMATCH)
2742  aswf = asw->canmatch;
2743  else if (action == E_MATCHMORE)
2744  aswf = asw->matchmore;
2745  else /* action == E_MATCH */
2746  aswf = asw->exists;
2747  if (!aswf)
2748  res = 0;
2749  else {
2750  if (chan)
2751  ast_autoservice_start(chan);
2752  res = aswf(chan, context, exten, priority, callerid, datap);
2753  if (chan)
2754  ast_autoservice_stop(chan);
2755  }
2756  if (res) { /* Got a match */
2757  q->swo = asw;
2758  q->data = datap;
2759  q->foundcontext = context;
2760  /* XXX keep status = STATUS_NO_CONTEXT ? */
2761  return NULL;
2762  }
2763  }
2764  q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */
2765  /* Now try any includes we have in this context */
2766  for (idx = 0; idx < ast_context_includes_count(tmp); idx++) {
2767  const struct ast_include *i = ast_context_includes_get(tmp, idx);
2768 
2769  if (include_valid(i)) {
2770  if ((e = pbx_find_extension(chan, bypass, q, include_rname(i), exten, priority, label, callerid, action))) {
2771 #ifdef NEED_DEBUG_HERE
2772  ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
2773 #endif
2774  return e;
2775  }
2776  if (q->swo)
2777  return NULL;
2778  }
2779  }
2780  return NULL;
2781 }
const char * label
Definition: pbx.c:244
ast_include: include= support in extensions.conf
Definition: pbx_include.c:37
const char * ast_get_switch_name(const struct ast_sw *sw)
Definition: pbx_sw.c:48
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
int ast_context_switches_count(const struct ast_context *con)
Definition: pbx.c:8652
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition: hashtab.c:486
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
#define STATUS_NO_PRIORITY
Definition: pbx.c:2469
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:699
const char * include_rname(const struct ast_include *inc)
Definition: pbx_include.c:55
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:1231
ast_switch_f * matchmore
Definition: pbx.h:168
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
static int tmp()
Definition: bt_open.c:389
const struct ast_sw * ast_context_switches_get(const struct ast_context *con, int idx)
Definition: pbx.c:8657
char last_char
Definition: pbx.c:276
#define STATUS_NO_EXTENSION
Definition: pbx.c:2468
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:2315
#define NULL
Definition: resample.c:96
char * incstack[AST_PBX_MAX_STACK]
Definition: extconf.h:237
int include_valid(const struct ast_include *inc)
Definition: pbx_include.c:65
static int priority
ast_switch_f * exists
Definition: pbx.h:165
ast_switch_f * canmatch
Definition: pbx.h:166
static struct ast_exten * trie_find_next_match(struct match_char *node)
Definition: pbx.c:1160
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_get_switch_eval(const struct ast_sw *sw)
Definition: pbx_sw.c:58
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *exten)
Definition: pbx.c:8614
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
int priority
Definition: pbx.c:243
#define ast_log
Definition: astobj2.c:42
ast_sw: Switch statement in extensions.conf
Definition: pbx_sw.c:37
const char * data
Definition: extconf.h:241
static void create_match_char_tree(struct ast_context *con)
Definition: pbx.c:1756
struct ast_switch * pbx_findswitch(const char *sw)
Definition: pbx_switch.c:40
struct ast_exten * canmatch_exten
Definition: pbx.c:279
static struct ast_threadstorage switch_data
Definition: pbx.c:228
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define STATUS_SUCCESS
Definition: pbx.c:2471
int total_specificity
Definition: pbx.c:274
int() ast_switch_f(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
All switch functions have the same interface, so define a type for them.
Definition: pbx.h:156
#define STATUS_NO_LABEL
Definition: pbx.c:2470
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
Definition: pbx.c:2400
char * exten
Definition: pbx.c:238
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
char name[0]
Definition: pbx.c:297
#define STATUS_NO_CONTEXT
Definition: pbx.c:2467
#define AST_PBX_MAX_STACK
Definition: extconf.h:226
#define LOG_NOTICE
Definition: logger.h:263
static int extenpatternmatchnew
Definition: pbx.c:764
static int matchcid(const char *cidpattern, const char *callerid)
Definition: pbx.c:2473
static const char name[]
Definition: cdr_mysql.c:74
static struct ast_context * find_context(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4804
const char * foundcontext
Definition: extconf.h:242
int stacklen
Definition: extconf.h:238
const char * ast_get_switch_data(const struct ast_sw *sw)
Definition: pbx_sw.c:53
struct match_char * node
Definition: pbx.c:278
char * strsep(char **str, const char *delims)
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: ael_main.c:211
static char * overrideswitch
Definition: pbx.c:765
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:2485
struct ast_switch * swo
Definition: extconf.h:240
struct ast_hashtab * root_table
Definition: pbx.c:287
const struct ast_include * ast_context_includes_get(const struct ast_context *con, int idx)
Definition: pbx.c:8702
int total_length
Definition: pbx.c:275
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:861
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_exten * exten
Definition: pbx.c:280
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
struct match_char * pattern_tree
Definition: pbx.c:288
int ast_context_includes_count(const struct ast_context *con)
Definition: pbx.c:8697

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

References ao2_alloc, ao2_cleanup, ao2_lock, ao2_object_get_lockaddr(), ao2_ref, ao2_unlock, 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, outgoing::context, ast_channel::dialed, outgoing::exten, ast_party_connected_line::id, LOG_WARNING, ast_exten::name, ast_party_id::name, NULL, ast_party_id::number, pbx_dial_reason(), pbx_outgoing_destroy(), pbx_outgoing_exec(), pbx_outgoing_state_callback(), ast_party_name::presentation, ast_party_number::presentation, outgoing::priority, ast_exten::priority, RAII_VAR, S_COR, ast_party_name::str, ast_party_number::str, thread, tmp(), ast_party_name::valid, and ast_party_number::valid.

Referenced by ast_pbx_outgoing_app_predial(), and ast_pbx_outgoing_exten_predial().

7761 {
7763  struct ast_channel *dialed;
7764  pthread_t thread;
7765  char tmp_cid_name[128];
7766  char tmp_cid_num[128];
7767 
7769  if (!outgoing) {
7770  return -1;
7771  }
7772  ast_cond_init(&outgoing->cond, NULL);
7773 
7774  if (!ast_strlen_zero(app)) {
7775  ast_copy_string(outgoing->app, app, sizeof(outgoing->app));
7776  outgoing->appdata = ast_strdup(appdata);
7777  } else {
7781  }
7782 
7783  if (!(outgoing->dial = ast_dial_create())) {
7784  return -1;
7785  }
7786 
7787  if (ast_dial_append(outgoing->dial, type, addr, assignedids)) {
7788  return -1;
7789  }
7790 
7792 
7793  if (!ast_strlen_zero(predial_callee)) {
7794  /* note casting to void * here to suppress compiler warning message (passing const to non-const function) */
7795  ast_dial_option_global_enable(outgoing->dial, AST_DIAL_OPTION_PREDIAL, (void *)predial_callee);
7796  }
7797 
7798  if (ast_dial_prerun(outgoing->dial, NULL, cap)) {
7799  if (synchronous && reason) {
7801  ast_dial_reason(outgoing->dial, 0));
7802  }
7803  return -1;
7804  }
7805 
7806  dialed = ast_dial_get_channel(outgoing->dial, 0);
7807  if (!dialed) {
7808  return -1;
7809  }
7810 
7811  ast_channel_lock(dialed);
7812  if (vars) {
7813  ast_set_variables(dialed, vars);
7814  }
7815  if (!ast_strlen_zero(account)) {
7817  ast_channel_accountcode_set(dialed, account);
7818  ast_channel_peeraccount_set(dialed, account);
7820  }
7822 
7823  if (!ast_strlen_zero(predial_callee)) {
7824  char *tmp = NULL;
7825  /*
7826  * The predial sub routine may have set callerid so set this into the new channel
7827  * Note... cid_num and cid_name parameters to this function will always be NULL if
7828  * predial_callee is non-NULL so we are not overwriting anything here.
7829  */
7830  tmp = S_COR(ast_channel_caller(dialed)->id.number.valid, ast_channel_caller(dialed)->id.number.str, NULL);
7831  if (tmp) {
7832  ast_copy_string(tmp_cid_num, tmp, sizeof(tmp_cid_num));
7833  cid_num = tmp_cid_num;
7834  }
7835  tmp = S_COR(ast_channel_caller(dialed)->id.name.valid, ast_channel_caller(dialed)->id.name.str, NULL);
7836  if (tmp) {
7837  ast_copy_string(tmp_cid_name, tmp, sizeof(tmp_cid_name));
7838  cid_name = tmp_cid_name;
7839  }
7840  }
7841  ast_channel_unlock(dialed);
7842 
7845 
7846  /*
7847  * It seems strange to set the CallerID on an outgoing call leg
7848  * to whom we are calling, but this function's callers are doing
7849  * various Originate methods. This call leg goes to the local
7850  * user. Once the called party answers, the dialplan needs to
7851  * be able to access the CallerID from the CALLERID function as
7852  * if the called party had placed this call.
7853  */
7855 
7857  if (!ast_strlen_zero(cid_num)) {
7858  connected.id.number.valid = 1;
7859  connected.id.number.str = (char *) cid_num;
7860  connected.id.number.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
7861  }
7862  if (!ast_strlen_zero(cid_name)) {
7863  connected.id.name.valid = 1;
7864  connected.id.name.str = (char *) cid_name;
7866  }
7868  }
7869 
7870  if (early_media) {
7872  }
7873 
7874  if (locked_channel) {
7875  /*
7876  * Keep a dialed channel ref since the caller wants
7877  * the channel returned. We must get the ref before
7878  * spawning off pbx_outgoing_exec().
7879  */
7880  ast_channel_ref(dialed);
7881  if (!synchronous) {
7882  /*
7883  * Lock it now to hold off pbx_outgoing_exec() in case the
7884  * calling function needs the channel state/snapshot before
7885  * dialing actually happens.
7886  */
7887  ast_channel_lock(dialed);
7888  }
7889  }
7890 
7891  /* This extra reference is dereferenced by pbx_outgoing_exec */
7892  ao2_ref(outgoing, +1);
7893 
7894  if (synchronous == AST_OUTGOING_WAIT_COMPLETE) {
7895  /*
7896  * Because we are waiting until this is complete anyway, there is no
7897  * sense in creating another thread that we will just need to wait
7898  * for, so instead we commandeer the current thread.
7899  */
7901  } else {
7902  outgoing->in_separate_thread = 1;
7903 
7905  ast_log(LOG_WARNING, "Unable to spawn dialing thread for '%s/%s'\n", type, addr);
7906  ao2_ref(outgoing, -1);
7907  if (locked_channel) {
7908  if (!synchronous) {
7909  ast_channel_unlock(dialed);
7910  }
7911  ast_channel_unref(dialed);
7912  }
7913  return -1;
7914  }
7915 
7916  if (synchronous) {
7917  ao2_lock(outgoing);
7918  /* Wait for dialing to complete */
7919  while (!outgoing->dialed) {
7921  }
7923  }
7924  }
7925 
7926  if (synchronous) {
7927  /* Determine the outcome of the dialing attempt up to it being answered. */
7928  if (reason) {
7929  *reason = pbx_dial_reason(outgoing->dial_res,
7930  ast_dial_reason(outgoing->dial, 0));
7931  }
7932 
7933  if (outgoing->dial_res != AST_DIAL_RESULT_ANSWERED) {
7934  /* The dial operation failed. */
7935  if (locked_channel) {
7936  ast_channel_unref(dialed);
7937  }
7938  return -1;
7939  }
7940  if (locked_channel) {
7941  ast_channel_lock(dialed);
7942  }
7943  }
7944 
7945  if (locked_channel) {
7946  *locked_channel = dialed;
7947  }
7948  return 0;
7949 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
static const char type[]
Definition: chan_ooh323.c:109
pthread_t thread
Definition: app_meetme.c:1089
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:7434
#define ast_channel_lock(chan)
Definition: channel.h:2945
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
int ast_dial_option_global_enable(struct ast_dial *dial, enum ast_dial_option option, void *data)
Enables an option globally.
Definition: dial.c:1151
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:563
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:1313
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide)
Initialize the given connected line structure using the given guide for a set update operation...
Definition: channel.c:2045
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:274
int priority
Definition: pbx_spool.c:96
static int timeout
Definition: cdr_mysql.c:86
static int tmp()
Definition: bt_open.c:389
void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars)
adds a list of channel variables to a channel
Definition: channel.c:8217
const ast_string_field app
Definition: pbx_spool.c:95
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
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:7716
static int priority
#define AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED
Definition: callerid.h:329
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:164
const ast_string_field context
Definition: pbx_spool.c:95
#define ast_strlen_zero(foo)
Definition: strings.h:52
const ast_string_field exten
Definition: pbx_spool.c:95
Number structure.
Definition: app_followme.c:154
void ast_dial_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback)
Set a callback for state changes.
Definition: dial.c:1293
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition: astobj2.c:476
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:7627
#define ast_log
Definition: astobj2.c:42
#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:911
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#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:85
#define ao2_lock(a)
Definition: astobj2.h:718
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:7690
struct ast_party_dialed dialed
Dialed/Called information.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
Connected Line/Party information.
Definition: channel.h:457
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:282
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
Structure which contains information about an outgoing dial.
Definition: pbx.c:7589
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static const char name[]
Definition: cdr_mysql.c:74
struct ast_dial * ast_dial_create(void)
New dialing structure.
Definition: dial.c:225
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:1282
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:165
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
int ast_dial_reason(struct ast_dial *dial, int num)
Get the reason an outgoing channel has failed.
Definition: dial.c:1271
static const char app[]
Definition: app_mysql.c:62
char connected
Definition: eagi_proxy.c:82
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:8404
static void pbx_outgoing_destroy(void *obj)
Destructor for outgoing structure.
Definition: pbx.c:7613
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:433

◆ pbx_outgoing_destroy()

static void pbx_outgoing_destroy ( void *  obj)
static

Destructor for outgoing structure.

Definition at line 7613 of file pbx.c.

References pbx_outgoing::appdata, ast_cond_destroy, ast_dial_destroy(), ast_free, pbx_outgoing::cond, and pbx_outgoing::dial.

Referenced by pbx_outgoing_attempt().

7614 {
7615  struct pbx_outgoing *outgoing = obj;
7616 
7617  if (outgoing->dial) {
7618  ast_dial_destroy(outgoing->dial);
7619  }
7620 
7621  ast_cond_destroy(&outgoing->cond);
7622 
7623  ast_free(outgoing->appdata);
7624 }
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition: dial.c:1091
char * appdata
Application data to pass to application.
Definition: pbx.c:7597
ast_cond_t cond
Condition for synchronous dialing.
Definition: pbx.c:7593
struct ast_dial * dial
Dialing structure being used.
Definition: pbx.c:7591
#define ast_cond_destroy(cond)
Definition: lock.h:200
Structure which contains information about an outgoing dial.
Definition: pbx.c:7589
#define ast_free(a)
Definition: astmm.h:182

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

References ao2_cleanup, ao2_lock, ao2_unlock, outgoing::app, ast_exten::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().

7628 {
7629  RAII_VAR(struct pbx_outgoing *, outgoing, data, ao2_cleanup);
7630  enum ast_dial_result res;
7631  struct ast_channel *chan;
7632 
7633  res = ast_dial_run(outgoing->dial, NULL, 0);
7634 
7635  if (outgoing->in_separate_thread) {
7636  /* Notify anyone interested that dialing is complete */
7637  ao2_lock(outgoing);
7638  outgoing->dial_res = res;
7639  outgoing->dialed = 1;
7640  ast_cond_signal(&outgoing->cond);
7642  } else {
7643  /* We still need the dial result, but we don't need to lock */
7644  outgoing->dial_res = res;
7645  }
7646 
7647  /* If the outgoing leg was not answered we can immediately return and go no further */
7648  if (res != AST_DIAL_RESULT_ANSWERED) {
7649  return NULL;
7650  }
7651 
7652  /* We steal the channel so we get ownership of when it is hung up */
7653  chan = ast_dial_answered_steal(outgoing->dial);
7654 
7655  if (!ast_strlen_zero(outgoing->app)) {
7656  struct ast_app *app = pbx_findapp(outgoing->app);
7657 
7658  if (app) {
7659  ast_verb(4, "Launching %s(%s) on %s\n", outgoing->app, S_OR(outgoing->appdata, ""),
7660  ast_channel_name(chan));
7661  pbx_exec(chan, app, outgoing->appdata);
7662  } else {
7663  ast_log(LOG_WARNING, "No such application '%s'\n", outgoing->app);
7664  }
7665 
7666  ast_hangup(chan);
7667  } else {
7668  if (!ast_strlen_zero(outgoing->context)) {
7670  }
7671 
7672  if (!ast_strlen_zero(outgoing->exten)) {
7674  }
7675 
7676  if (outgoing->priority > 0) {
7678  }
7679 
7680  if (ast_pbx_run(chan)) {
7681  ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(chan));
7682  ast_hangup(chan);
7683  }
7684  }
7685 
7686  return NULL;
7687 }
Main Channel structure associated with a channel.
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
#define LOG_WARNING
Definition: logger.h:274
int priority
Definition: pbx_spool.c:96
const ast_string_field app
Definition: pbx_spool.c:95
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ast_cond_signal(cond)
Definition: lock.h:201
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4759
const ast_string_field context
Definition: pbx_spool.c:95
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_strlen_zero(foo)
Definition: strings.h:52
const ast_string_field exten
Definition: pbx_spool.c:95
#define ast_log
Definition: astobj2.c:42
ast_dial_result
List of return codes for dial run API calls.
Definition: dial.h:54
#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:911
#define ao2_lock(a)
Definition: astobj2.h:718
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:939
#define LOG_ERROR
Definition: logger.h:285
Structure which contains information about an outgoing dial.
Definition: pbx.c:7589
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
struct ast_channel * ast_dial_answered_steal(struct ast_dial *dial)
Steal the channel that answered.
Definition: dial.c:993
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_channel_context_set(struct ast_channel *chan, const char *value)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
ast_app: A registered application
Definition: pbx_app.c:45
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
void ast_channel_priority_set(struct ast_channel *chan, int value)
static const char app[]
Definition: app_mysql.c:62

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

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

7691 {
7692  struct ast_channel *channel;
7693 
7695  return;
7696  }
7697 
7698  if (!(channel = ast_dial_get_channel(dial, 0))) {
7699  return;
7700  }
7701 
7702  ast_verb(4, "Treating progress as answer on '%s' due to early media option\n",
7703  ast_channel_name(channel));
7704 
7706 }
Main Channel structure associated with a channel.
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
Definition: muted.c:95
#define ast_verb(level,...)
Definition: logger.h:463
enum ast_dial_result ast_dial_state(struct ast_dial *dial)
Return state of dial.
Definition: dial.c:1012
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:1282
const char * ast_channel_name(const struct ast_channel *chan)

◆ pbx_parseable_goto()

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

Definition at line 8803 of file pbx.c.

References ast_async_goto(), ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_priority(), ast_explicit_goto(), ast_findlabel_extension(), ast_log, ast_strdupa, ast_strlen_zero, context, ast_exten::exten, LOG_WARNING, NULL, S_COR, and strsep().

Referenced by ast_async_parseable_goto(), and ast_parseable_goto().

8804 {
8805  char *exten, *pri, *context;
8806  char *stringp;
8807  int ipri;
8808  int mode = 0;
8809  char rest[2] = "";
8810 
8811  if (ast_strlen_zero(goto_string)) {
8812  ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
8813  return -1;
8814  }
8815  stringp = ast_strdupa(goto_string);
8816  context = strsep(&stringp, ","); /* guaranteed non-null */
8817  exten = strsep(&stringp, ",");
8818  pri = strsep(&stringp, ",");
8819  if (!exten) { /* Only a priority in this one */
8820  pri = context;
8821  exten = NULL;
8822  context = NULL;
8823  } else if (!pri) { /* Only an extension and priority in this one */
8824  pri = exten;
8825  exten = context;
8826  context = NULL;
8827  }
8828  if (*pri == '+') {
8829  mode = 1;
8830  pri++;
8831  } else if (*pri == '-') {
8832  mode = -1;
8833  pri++;
8834  }
8835  if (sscanf(pri, "%30d%1s", &ipri, rest) != 1) {
8836  ipri = ast_findlabel_extension(chan, context ? context : ast_channel_context(chan),
8837  exten ? exten : ast_channel_exten(chan), pri,
8838  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
8839  if (ipri < 1) {
8840  ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
8841  return -1;
8842  } else
8843  mode = 0;
8844  }
8845  /* At this point we have a priority and maybe an extension and a context */
8846 
8847  if (mode)
8848  ipri = ast_channel_priority(chan) + (ipri * mode);
8849 
8850  if (async)
8851  ast_async_goto(chan, context, exten, ipri);
8852  else
8853  ast_explicit_goto(chan, context, exten, ipri);
8854 
8855  return 0;
8856 
8857 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:6987
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
int ast_channel_priority(const struct ast_channel *chan)
#define ast_strlen_zero(foo)
Definition: strings.h:52
Number structure.
Definition: app_followme.c:154
#define ast_log
Definition: astobj2.c: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:85
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char * ast_channel_exten(const struct ast_channel *chan)
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:7011
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:4184
char * strsep(char **str, const char *delims)
const char * ast_channel_context(const struct ast_channel *chan)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

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

References autofallthrough.

Referenced by pbx_load_module().

4775 {
4776  int oldval = autofallthrough;
4777  autofallthrough = newval;
4778  return oldval;
4779 }
static int autofallthrough
Definition: pbx.c:763

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

References extenpatternmatchnew.

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

4782 {
4783  int oldval = extenpatternmatchnew;
4784  extenpatternmatchnew = newval;
4785  return oldval;
4786 }
static int extenpatternmatchnew
Definition: pbx.c:764

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

References ast_free, ast_strdup, ast_strlen_zero, and NULL.

Referenced by pbx_load_module().

4789 {
4790  if (overrideswitch) {
4792  }
4793  if (!ast_strlen_zero(newval)) {
4794  overrideswitch = ast_strdup(newval);
4795  } else {
4796  overrideswitch = NULL;
4797  }
4798 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_free(a)
Definition: astmm.h:182
static char * overrideswitch
Definition: pbx.c:765

◆ pbx_shutdown()

static void pbx_shutdown ( void  )
static

Definition at line 8909 of file pbx.c.

References ao2_container_unregister(), ao2_ref, ast_hashtab_destroy(), NULL, and STASIS_MESSAGE_TYPE_CLEANUP.

Referenced by ast_pbx_init().

8910 {
8911  STASIS_MESSAGE_TYPE_CLEANUP(hint_change_message_type);
8912  STASIS_MESSAGE_TYPE_CLEANUP(hint_remove_message_type);
8913 
8914  if (hints) {
8915  ao2_container_unregister("hints");
8916  ao2_ref(hints, -1);
8917  hints = NULL;
8918  }
8919  if (hintdevices) {
8920  ao2_container_unregister("hintdevices");
8921  ao2_ref(hintdevices, -1);
8922  hintdevices = NULL;
8923  }
8924  if (autohints) {
8925  ao2_container_unregister("autohints");
8926  ao2_ref(autohints, -1);
8927  autohints = NULL;
8928  }
8929  if (statecbs) {
8930  ao2_container_unregister("statecbs");
8931  ao2_ref(statecbs, -1);
8932  statecbs = NULL;
8933  }
8934  if (contexts_table) {
8936  }
8937 }
static struct ast_hashtab * contexts_table
Definition: pbx.c:777
static struct ao2_container * hintdevices
Container for hint devices.
Definition: pbx.c:363
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1523
#define NULL
Definition: resample.c:96
void ao2_container_unregister(const char *name)
Unregister a container for CLI stats and integrity check.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct ao2_container * statecbs
Definition: pbx.c:803
static struct ao2_container * autohints
Container for autohint contexts.
Definition: pbx.c:380
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

◆ pbx_thread()

static void* pbx_thread ( void *  data)
static

Definition at line 4692 of file pbx.c.

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

Referenced by ast_pbx_start().

4693 {
4694  /* Oh joyeous kernel, we're a new thread, with nothing to do but
4695  answer this channel and get it going.
4696  */
4697  /* NOTE:
4698  The launcher of this function _MUST_ increment 'countcalls'
4699  before invoking the function; it will be decremented when the
4700  PBX has finished running on the channel
4701  */
4702  struct ast_channel *c = data;
4703 
4704  __ast_pbx_run(c, NULL);
4706 
4707  pthread_exit(NULL);
4708 
4709  return NULL;
4710 }
Main Channel structure associated with a channel.
static void decrease_call_count(void)
Definition: pbx.c:4670
static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c, struct ast_pbx_args *args)
Definition: pbx.c:4310
static struct test_val c
#define NULL
Definition: resample.c:96
const char * data

◆ presence_state_cb()

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

Definition at line 8333 of file pbx.c.

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(), NULL, OBJ_MULTIPLE, OBJ_POINTER, presence_state_notify_callbacks(), stasis_message_data(), and stasis_message_type().

Referenced by load_pbx().

8334 {
8335  struct ast_presence_state_message *presence_state;
8336  struct ast_str *hint_app = NULL;
8337  struct ast_hintdevice *device;
8338  struct ast_hintdevice *cmpdevice;
8339  struct ao2_iterator *dev_iter;
8340 
8342  return;
8343  }
8344 
8345  presence_state = stasis_message_data(msg);
8346 
8347  if (ao2_container_count(hintdevices) == 0) {
8348  /* There are no hints monitoring devices. */
8349  return;
8350  }
8351 
8352  hint_app = ast_str_create(1024);
8353  if (!hint_app) {
8354  return;
8355  }
8356 
8357  cmpdevice = ast_alloca(sizeof(*cmpdevice) + strlen(presence_state->provider));
8358  strcpy(cmpdevice->hintdevice, presence_state->provider);
8359 
8360  ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
8361  dev_iter = ao2_t_callback(hintdevices,
8364  cmpdevice,
8365  "find devices in container");
8366  if (!dev_iter) {
8368  ast_free(hint_app);
8369  return;
8370  }
8371 
8372  for (; (device = ao2_iterator_next(dev_iter)); ao2_t_ref(device, -1, "Next device")) {
8373  if (device->hint) {
8374  presence_state_notify_callbacks(device->hint, &hint_app, presence_state);
8375  }
8376  }
8377  ao2_iterator_destroy(dev_iter);
8379 
8380  ast_free(hint_app);
8381 }
#define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:463
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define OBJ_POINTER
Definition: astobj2.h:1154
static struct ao2_container * hintdevices
Container for hint devices.
Definition: pbx.c:363
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct ast_hint * hint
Hint this hintdevice belongs to.
Definition: pbx.c:374
Stasis message payload representing a presence state update.
#define ast_mutex_lock(a)
Definition: lock.h:187
static ast_mutex_t context_merge_lock
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
Definition: pbx.c:790
#define NULL
Definition: resample.c:96
static void presence_state_notify_callbacks(struct ast_hint *hint, struct ast_str **hint_app, struct ast_presence_state_message *presence_state)
Definition: pbx.c:3464
char hintdevice[1]
Definition: pbx.c:376
static int hintdevice_cmp_multiple(void *obj, void *arg, int flags)
Definition: pbx.c:421
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:1714
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ast_free(a)
Definition: astmm.h:182
Structure for dial plan hint devices.
Definition: pbx.c:369
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
struct stasis_message_type * ast_presence_state_message_type(void)
Get presence state message type.
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ presence_state_notify_callbacks()

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

Definition at line 3464 of file pbx.c.

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, and ast_presence_state_message::state.

Referenced by handle_hint_change_message_type(), and presence_state_cb().

3466 {
3467  struct ao2_iterator cb_iter;
3468  struct ast_state_cb *state_cb;
3471 
3472  ao2_lock(hint);
3473  if (!hint->exten) {
3474  /* The extension has already been destroyed */
3475  ao2_unlock(hint);
3476  return;
3477  }
3478 
3479  /*
3480  * Save off strings in case the hint extension gets destroyed
3481  * while we are notifying the watchers.
3482  */
3483  ast_copy_string(context_name,
3485  sizeof(context_name));
3486  ast_copy_string(exten_name, ast_get_extension_name(hint->exten),
3487  sizeof(exten_name));
3488  ast_str_set(hint_app, 0, "%s", ast_get_extension_app(hint->exten));
3489  ao2_unlock(hint);
3490 
3491  /* Check to see if update is necessary */
3492  if ((hint->last_presence_state == presence_state->state) &&
3493  ((hint->last_presence_subtype && presence_state->subtype &&
3494  !strcmp(hint->last_presence_subtype, presence_state->subtype)) ||
3495  (!hint->last_presence_subtype && !presence_state->subtype)) &&
3496  ((hint->last_presence_message && presence_state->message &&
3497  !strcmp(hint->last_presence_message, presence_state->message)) ||
3498  (!hint->last_presence_message && !presence_state->message))) {
3499  /* this update is the same as the last, do nothing */
3500  return;
3501  }
3502 
3503  /* update new values */
3506  hint->last_presence_state = presence_state->state;
3507  hint->last_presence_subtype = presence_state->subtype ? ast_strdup(presence_state->subtype) : NULL;
3508  hint->last_presence_message = presence_state->message ? ast_strdup(presence_state->message) : NULL;
3509 
3510  /* For general callbacks */
3511  cb_iter = ao2_iterator_init(statecbs, 0);
3512  for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3514  context_name,
3515  exten_name,
3516  state_cb->data,
3518  hint,
3519  NULL);
3520  }
3521  ao2_iterator_destroy(&cb_iter);
3522 
3523  /* For extension callbacks */
3524  cb_iter = ao2_iterator_init(hint->callbacks, 0);
3525  for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_cleanup(state_cb)) {
3527  context_name,
3528  exten_name,
3529  state_cb->data,
3531  hint,
3532  NULL);
3533  }
3534  ao2_iterator_destroy(&cb_iter);
3535 }
struct ast_context * ast_get_extension_context(struct ast_exten *exten)
Definition: pbx.c:8543
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
void * data
Definition: pbx.c:305
ast_state_cb: An extension state notify register item
Definition: pbx.c:301
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
ast_state_cb_type change_cb
Definition: pbx.c:309
int last_presence_state
Definition: pbx.c:338
static const char context_name[]
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:1065
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_exten * exten
Hint extension.
Definition: pbx.c:331
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
struct ao2_container * callbacks
Definition: pbx.c:332
#define AST_MAX_CONTEXT
Definition: channel.h:136
#define ast_free(a)
Definition: astmm.h:182
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8596
static struct ao2_container * statecbs
Definition: pbx.c:803
enum ast_presence_state state
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
char * last_presence_message
Definition: pbx.c:340
static int execute_state_callback(ast_state_cb_type cb, const char *context, const char *exten, void *data, enum ast_state_cb_update_reason reason, struct ast_hint *hint, struct ao2_container *device_state_info)
Definition: pbx.c:3250
static const char exten_name[]
char * last_presence_subtype
Definition: pbx.c:339
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ print_autohint_key()

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

Definition at line 8962 of file pbx.c.

References ast_autohint::context.

Referenced by ast_pbx_init().

8963 {
8964  struct ast_autohint *autohint = v_obj;
8965 
8966  if (!autohint) {
8967  return;
8968  }
8969  prnt(where, "%s", autohint->context);
8970 }
char context[1]
Name of the context.
Definition: pbx.c:389
Structure for dial plan autohints.
Definition: pbx.c:385

◆ print_ext()

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

helper function to print an extension

Definition at line 5487 of file pbx.c.

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

Referenced by show_dialplan_helper().

5488 {
5489  int prio = ast_get_extension_priority(e);
5490  if (prio == PRIORITY_HINT) {
5491  snprintf(buf, buflen, "hint: %s",
5493  } else {
5494  snprintf(buf, buflen, "%d. %s(%s)",
5495  prio, ast_get_extension_app(e),
5497  }
5498 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
void * ast_get_extension_app_data(struct ast_exten *e)
Definition: pbx.c:8601
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define PRIORITY_HINT
Definition: pbx.h:54
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8596
int ast_get_extension_priority(struct ast_exten *exten)
Definition: pbx.c:8558

◆ print_hintdevices_key()

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

Definition at line 8950 of file pbx.c.

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

Referenced by ast_pbx_init().

8951 {
8952  struct ast_hintdevice *hintdevice = v_obj;
8953 
8954  if (!hintdevice) {
8955  return;
8956  }
8957  prnt(where, "%s => %s@%s", hintdevice->hintdevice,
8958  ast_get_extension_name(hintdevice->hint->exten),
8960 }
struct ast_context * ast_get_extension_context(struct ast_exten *exten)
Definition: pbx.c:8543
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
struct ast_hint * hint
Hint this hintdevice belongs to.
Definition: pbx.c:374
char hintdevice[1]
Definition: pbx.c:376
struct ast_exten * exten
Hint extension.
Definition: pbx.c:331
Structure for dial plan hint devices.
Definition: pbx.c:369
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538

◆ print_hints_key()

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

Definition at line 8939 of file pbx.c.

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

Referenced by ast_pbx_init().

8940 {
8941  struct ast_hint *hint = v_obj;
8942 
8943  if (!hint) {
8944  return;
8945  }
8946  prnt(where, "%s@%s", ast_get_extension_name(hint->exten),
8948 }
struct ast_context * ast_get_extension_context(struct ast_exten *exten)
Definition: pbx.c:8543
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
struct ast_exten * exten
Hint extension.
Definition: pbx.c:331
Structure for dial plan hints.
Definition: pbx.c:324
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538

◆ print_statecbs_key()

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

Definition at line 8972 of file pbx.c.

References ast_state_cb::id.

Referenced by ast_pbx_init().

8973 {
8974  struct ast_state_cb *state_cb = v_obj;
8975 
8976  if (!state_cb) {
8977  return;
8978  }
8979  prnt(where, "%d", state_cb->id);
8980 }
ast_state_cb: An extension state notify register item
Definition: pbx.c:301
int id
Definition: pbx.c:303

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

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

Referenced by ast_change_hint().

4075 {
4076  struct stasis_message *message;
4077 
4078  if (!hint_change_message_type()) {
4079  return -1;
4080  }
4081 
4082  if (!(message = stasis_message_create(hint_change_message_type(), hint))) {
4083  ao2_ref(hint, -1);
4084  return -1;
4085  }
4086 
4089 
4090  ao2_ref(message, -1);
4091 
4092  return 0;
4093 }
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
Definition: devicestate.c:668
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
struct stasis_topic * ast_presence_state_topic_all(void)
Get presence state topic.

◆ publish_hint_remove()

static int publish_hint_remove ( struct ast_hint hint)
static

Publish a hint removed event.

Definition at line 3924 of file pbx.c.

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

Referenced by ast_remove_hint().

3925 {
3926  struct stasis_message *message;
3927 
3928  if (!hint_remove_message_type()) {
3929  return -1;
3930  }
3931 
3932  if (!(message = stasis_message_create(hint_remove_message_type(), hint))) {
3933  ao2_ref(hint, -1);
3934  return -1;
3935  }
3936 
3938 
3939  ao2_ref(message, -1);
3940 
3941  return 0;
3942 }
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
Definition: devicestate.c:668
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511

◆ raise_exception()

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

pbx.c functions needed by pbx_builtins.c

Definition at line 2806 of file pbx.c.

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

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

2807 {
2809  struct pbx_exception *exception = NULL;
2810 
2811  if (!ds) {
2813  if (!ds)
2814  return -1;
2815  if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
2816  ast_datastore_free(ds);
2817  return -1;
2818  }
2819  ds->data = exception;
2820  ast_channel_datastore_add(chan, ds);
2821  } else
2822  exception = ds->data;
2823 
2824  ast_string_field_set(exception, reason, reason);
2826  ast_string_field_set(exception, exten, ast_channel_exten(chan));
2827  exception->priority = ast_channel_priority(chan);
2828  set_ext_pri(chan, "e", priority);
2829  return 0;
2830 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:426
Structure for a data store object.
Definition: datastore.h:68
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:2404
#define NULL
Definition: resample.c:96
static int priority
int ast_channel_priority(const struct ast_channel *chan)
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
const ast_string_field reason
Definition: pbx.c:625
int priority
Definition: pbx.c:627
static const struct ast_datastore_info exception_store_info
Definition: pbx.c:2790
const char * ast_channel_exten(const struct ast_channel *chan)
void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
Definition: pbx.c:4268
void * data
Definition: datastore.h:70
const char * ast_channel_context(const struct ast_channel *chan)
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ remove_hintdevice()

static int remove_hintdevice ( struct ast_hint hint)
static

Definition at line 517 of file pbx.c.

References ao2_t_callback_data, ast_free, AST_VECTOR_GET, AST_VECTOR_REMOVE_UNORDERED, AST_VECTOR_SIZE, hintdevice_remove_cb(), OBJ_NODATA, OBJ_SEARCH_KEY, OBJ_UNLINK, and parse_hint_device().

Referenced by ast_change_hint(), and ast_remove_hint().

518 {
519  while (AST_VECTOR_SIZE(&hint->devices) > 0) {
520  char *device = AST_VECTOR_GET(&hint->devices, 0);
521 
523  hintdevice_remove_cb, device, hint, "Remove device from container");
524  AST_VECTOR_REMOVE_UNORDERED(&hint->devices, 0);
525  ast_free(device);
526  }
527 
528  return 0;
529 }
static int hintdevice_remove_cb(void *obj, void *arg, void *data, int flags)
Definition: pbx.c:504
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
static struct ao2_container * hintdevices
Container for hint devices.
Definition: pbx.c:363
#define AST_VECTOR_REMOVE_UNORDERED(vec, idx)
Remove an element from an unordered vector by index.
Definition: vector.h:438
#define ast_free(a)
Definition: astmm.h:182
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
#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:1741
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

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

References ast_channel_exten_set(), ast_channel_lock, ast_channel_priority_set(), and ast_channel_unlock.

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

4269 {
4270  ast_channel_lock(c);
4272  ast_channel_priority_set(c, pri);
4273  ast_channel_unlock(c);
4274 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
void ast_channel_priority_set(struct ast_channel *chan, int value)

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

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, ast_context::name, NULL, ast_context::pattern_tree, dialplan_counters::total_context, and dialplan_counters::total_exten.

Referenced by handle_debug_dialplan().

5678 {
5679  struct ast_context *c = NULL;
5680  int res = 0, old_total_exten = dpc->total_exten;
5681 
5682  ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
5683 
5684  ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
5685  ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
5686  ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
5687  ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
5688  ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
5689  ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
5690  ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
5692 
5693  /* walk all contexts ... */
5694  while ( (c = ast_walk_contexts(c)) ) {
5695  int context_info_printed = 0;
5696 
5697  if (context && strcmp(ast_get_context_name(c), context))
5698  continue; /* skip this one, name doesn't match */
5699 
5700  dpc->context_existence = 1;
5701 
5702  if (!c->pattern_tree) {
5703  /* Ignore check_return warning from Coverity for ast_exists_extension below */
5704  ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
5705  }
5706 
5707  ast_rdlock_context(c);
5708 
5709  dpc->total_context++;
5710  ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
5712  context_info_printed = 1;
5713 
5714  if (c->pattern_tree)
5715  {
5716  cli_match_char_tree(c->pattern_tree, " ", fd);
5717  } else {
5718  ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
5719  }
5720 
5721  ast_unlock_context(c);
5722 
5723  /* if we print something in context, make an empty line */
5724  if (context_info_printed)
5725  ast_cli(fd, "\n");
5726  }
5728 
5729  return (dpc->total_exten == old_total_exten) ? -1 : res;
5730 }
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8530
int total_exten
Definition: pbx.c:5480
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition: pbx.c:8525
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: pbx.c:8609
int context_existence
Definition: pbx.c:5482
static struct test_val c
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8507
const char * ast_get_context_registrar(struct ast_context *c)
Definition: pbx.c:8566
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:4179
static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
Definition: pbx.c:1111
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
char name[0]
Definition: pbx.c:297
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
int total_context
Definition: pbx.c:5479
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
struct match_char * pattern_tree
Definition: pbx.c:288

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

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(), ast_context::autohints, buf, buf2, c, ast_exten::cidmatch, dialplan_counters::context_existence, el, dialplan_counters::extension_existence, LOG_WARNING, ast_exten::matchcid, NULL, print_ext(), show_dialplan_helper_extension_output(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.

Referenced by handle_show_dialplan().

5517 {
5518  struct ast_context *c = NULL;
5519  int res = 0, old_total_exten = dpc->total_exten;
5520 
5522 
5523  /* walk all contexts ... */
5524  while ( (c = ast_walk_contexts(c)) ) {
5525  int idx;
5526  struct ast_exten *e;
5527 #ifndef LOW_MEMORY
5528  char buf[1024], buf2[1024];
5529 #else
5530  char buf[256], buf2[256];
5531 #endif
5532  int context_info_printed = 0;
5533 
5534  if (context && strcmp(ast_get_context_name(c), context))
5535  continue; /* skip this one, name doesn't match */
5536 
5537  dpc->context_existence = 1;
5538 
5539  ast_rdlock_context(c);
5540 
5541  /* are we looking for exten too? if yes, we print context
5542  * only if we find our extension.
5543  * Otherwise print context even if empty ?
5544  * XXX i am not sure how the rinclude is handled.
5545  * I think it ought to go inside.
5546  */
5547  if (!exten) {
5548  dpc->total_context++;
5549  ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
5551  if (c->autohints) {
5552  ast_cli(fd, "Autohints support enabled\n");
5553  }
5554  context_info_printed = 1;
5555  }
5556 
5557  /* walk extensions ... */
5558  e = NULL;
5559  while ( (e = ast_walk_context_extensions(c, e)) ) {
5560  struct ast_exten *p;
5561 
5563  continue; /* skip, extension match failed */
5564 
5565  dpc->extension_existence = 1;
5566 
5567  /* may we print context info? */
5568  if (!context_info_printed) {
5569  dpc->total_context++;
5570  if (rinclude) { /* TODO Print more info about rinclude */
5571  ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
5573  } else {
5574  ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
5576  if (c->autohints) {
5577  ast_cli(fd, "Autohints support enabled\n");
5578  }
5579  }
5580  context_info_printed = 1;
5581  }
5582  dpc->total_prio++;
5583 
5584  /* write extension name and first peer */
5585  if (e->matchcid == AST_EXT_MATCHCID_ON)
5586  snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
5587  else
5588  snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
5589 
5590  print_ext(e, buf2, sizeof(buf2));
5591 
5592  show_dialplan_helper_extension_output(fd, buf, buf2, e);
5593 
5594  dpc->total_exten++;
5595  /* walk next extension peers */
5596  p = e; /* skip the first one, we already got it */
5597  while ( (p = ast_walk_extension_priorities(e, p)) ) {
5598  const char *el = ast_get_extension_label(p);
5599  dpc->total_prio++;
5600  if (el)
5601  snprintf(buf, sizeof(buf), " [%s]", el);
5602  else
5603  buf[0] = '\0';
5604  print_ext(p, buf2, sizeof(buf2));
5605 
5606  show_dialplan_helper_extension_output(fd, buf, buf2, p);
5607  }
5608  }
5609 
5610  /* walk included and write info ... */
5611  for (idx = 0; idx < ast_context_includes_count(c); idx++) {
5612  const struct ast_include *i = ast_context_includes_get(c, idx);
5613 
5614  snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
5615  if (exten) {
5616  /* Check all includes for the requested extension */
5617  if (includecount >= AST_PBX_MAX_STACK) {
5618  ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
5619  } else {
5620  int dupe = 0;
5621  int x;
5622  for (x = 0; x < includecount; x++) {
5623  if (!strcasecmp(includes[x], ast_get_include_name(i))) {
5624  dupe++;
5625  break;
5626  }
5627  }
5628  if (!dupe) {
5629  includes[includecount] = ast_get_include_name(i);
5630  show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
5631  } else {
5632  ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
5633  }
5634  }
5635  } else {
5636  ast_cli(fd, " Include => %-45s [%s]\n",
5637  buf, ast_get_include_registrar(i));
5638  }
5639  }
5640 
5641  /* walk ignore patterns and write info ... */
5642  for (idx = 0; idx < ast_context_ignorepats_count(c); idx++) {
5643  const struct ast_ignorepat *ip = ast_context_ignorepats_get(c, idx);
5644  const char *ipname = ast_get_ignorepat_name(ip);
5645  char ignorepat[AST_MAX_EXTENSION];
5646 
5647  snprintf(buf, sizeof(buf), "'%s'", ipname);
5648  snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
5649  if (!exten || ast_extension_match(ignorepat, exten)) {
5650  ast_cli(fd, " Ignore pattern => %-45s [%s]\n",
5651  buf, ast_get_ignorepat_registrar(ip));
5652  }
5653  }
5654  if (!rinclude) {
5655  for (idx = 0; idx < ast_context_switches_count(c); idx++) {
5656  const struct ast_sw *sw = ast_context_switches_get(c, idx);
5657 
5658  snprintf(buf, sizeof(buf), "'%s/%s'",
5659  ast_get_switch_name(sw),
5660  ast_get_switch_data(sw));
5661  ast_cli(fd, " Alt. Switch => %-45s [%s]\n",
5662  buf, ast_get_switch_registrar(sw));
5663  }
5664  }
5665 
5666  ast_unlock_context(c);
5667 
5668  /* if we print something in context, make an empty line */
5669  if (context_info_printed)
5670  ast_cli(fd, "\n");
5671  }
5673 
5674  return (dpc->total_exten == old_total_exten) ? -1 : res;
5675 }
ast_include: include= support in extensions.conf
Definition: pbx_include.c:37
const char * ast_get_switch_name(const struct ast_sw *sw)
Definition: pbx_sw.c:48
const char * ast_get_switch_registrar(const struct ast_sw *sw)
Definition: pbx_sw.c:63
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
int ast_context_switches_count(const struct ast_context *con)
Definition: pbx.c:8652
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8530
int total_exten
Definition: pbx.c:5480
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition: pbx.c:8525
const char * ast_get_ignorepat_registrar(const struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:47
const struct ast_ignorepat * ast_context_ignorepats_get(const struct ast_context *con, int idx)
Definition: pbx.c:8745
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: pbx.c:8609
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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:5501
#define LOG_WARNING
Definition: logger.h:274
const struct ast_sw * ast_context_switches_get(const struct ast_context *con, int idx)
Definition: pbx.c:8657
static EditLine * el
Definition: asterisk.c:340
static struct ast_threadstorage buf2
int context_existence
Definition: pbx.c:5482
const char * ast_get_include_registrar(const struct ast_include *i)
Definition: pbx_include.c:60
static struct test_val c
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8507
int autohints
Definition: pbx.c:295
int matchcid
Definition: pbx.c:240
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *exten)
Definition: pbx.c:8614
#define ast_log
Definition: astobj2.c:42
const char * ast_get_context_registrar(struct ast_context *c)
Definition: pbx.c:8566
ast_sw: Switch statement in extensions.conf
Definition: pbx_sw.c:37
#define AST_MAX_EXTENSION
Definition: channel.h:135
static void print_ext(struct ast_exten *e, char *buf, int buflen)
helper function to print an extension
Definition: pbx.c:5487
const char * ast_get_ignorepat_name(const struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:42
int ast_context_ignorepats_count(const struct ast_context *con)
Definition: pbx.c:8740
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
ast_ignorepat: Ignore patterns in dial plan
Definition: pbx_ignorepat.c:37
int ast_extension_match(const char *pattern, const char *data)
Determine if a given extension matches a given pattern (in NXX format)
Definition: pbx.c:2413
#define AST_PBX_MAX_STACK
Definition: extconf.h:226
struct ast_exten * ast_walk_extension_priorities(struct ast_exten *exten, struct ast_exten *priority)
Definition: pbx.c:8662
const char * ast_get_switch_data(const struct ast_sw *sw)
Definition: pbx_sw.c:53
const char * cidmatch
Definition: pbx.c:241
const char * ast_get_include_name(const struct ast_include *include)
Definition: pbx_include.c:50
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:5516
int total_prio
Definition: pbx.c:5481
const struct ast_include * ast_context_includes_get(const struct ast_context *con, int idx)
Definition: pbx.c:8702
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
const char * ast_get_extension_label(struct ast_exten *exten)
Definition: pbx.c:8553
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
int total_context
Definition: pbx.c:5479
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
int extension_existence
Definition: pbx.c:5483
int ast_context_includes_count(const struct ast_context *con)
Definition: pbx.c:8697

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

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

Referenced by show_dialplan_helper().

5502 {
5503  if (ast_get_extension_registrar_file(exten)) {
5504  ast_cli(fd, " %-17s %-45s [%s:%d]\n",
5505  buf1, buf2,
5508  return;
5509  }
5510 
5511  ast_cli(fd, " %-17s %-45s [%s]\n",
5513 }
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:8576
static struct ast_threadstorage buf2
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const char * ast_get_extension_registrar(struct ast_exten *e)
Definition: pbx.c:8571
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:8581
static struct ast_threadstorage buf1

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

References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.

Referenced by ast_pbx_init().

8898 {
8899  const struct ast_state_cb *state_cb = obj;
8901 
8902  return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0;
8903 }
ast_state_cb: An extension state notify register item
Definition: pbx.c:301
ast_state_cb_type change_cb
Definition: pbx.c:309
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

◆ trie_find_next_match()

static struct ast_exten* trie_find_next_match ( struct match_char node)
static

Definition at line 1160 of file pbx.c.

References match_char::alt_char, E_CANMATCH, E_FINDLABEL, E_MATCH, E_MATCHMORE, E_SPAWN, match_char::exten, match_char::next_char, NULL, and match_char::x.

Referenced by pbx_find_extension().

1161 {
1162  struct match_char *m3;
1163  struct match_char *m4;
1164  struct ast_exten *e3;
1165 
1166  if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */
1167  return node->exten;
1168  }
1169 
1170  if (node && node->x[0] == '!' && !node->x[1]) {
1171  return node->exten;
1172  }
1173 
1174  if (!node || !node->next_char) {
1175  return NULL;
1176  }
1177 
1178  m3 = node->next_char;
1179 
1180  if (m3->exten) {
1181  return m3->exten;
1182  }
1183  for (m4 = m3->alt_char; m4; m4 = m4->alt_char) {
1184  if (m4->exten) {
1185  return m4->exten;
1186  }
1187  }
1188  for (m4 = m3; m4; m4 = m4->alt_char) {
1189  e3 = trie_find_next_match(m3);
1190  if (e3) {
1191  return e3;
1192  }
1193  }
1194 
1195  return NULL;
1196 }
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
struct ast_exten * exten
Definition: pbx.c:268
struct match_char * alt_char
Definition: pbx.c:266
#define NULL
Definition: resample.c:96
char x[1]
Definition: pbx.c:269
static struct ast_exten * trie_find_next_match(struct match_char *node)
Definition: pbx.c:1160
struct match_char * next_char
Definition: pbx.c:267
match_char: forms a syntax tree for quick matching of extension patterns
Definition: pbx.c:261

◆ unload_pbx()

static void unload_pbx ( void  )
static

Definition at line 8448 of file pbx.c.

References ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_manager_unregister(), and stasis_unsubscribe_and_join().

Referenced by load_pbx().

8449 {
8452 
8453  ast_manager_unregister("ShowDialPlan");
8454  ast_manager_unregister("ExtensionStateList");
8458 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
static struct stasis_subscription * presence_state_sub
Subscription for presence state change events.
Definition: pbx.c:770
static struct ast_cli_entry pbx_cli[]
Definition: pbx.c:6164
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
static struct ast_custom_function testtime_function
Definition: pbx.c:8316
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1136
static struct ast_custom_function exception_function
Definition: pbx.c:2852
static struct stasis_subscription * device_state_sub
Subscription for device state change events.
Definition: pbx.c:768

◆ unreference_cached_app()

void unreference_cached_app ( struct ast_app app)

pbx.c function needed by pbx_app.c

Definition at line 6179 of file pbx.c.

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

Referenced by ast_unregister_application().

6180 {
6181  struct ast_context *context = NULL;
6182  struct ast_exten *eroot = NULL, *e = NULL;
6183 
6185  while ((context = ast_walk_contexts(context))) {
6186  while ((eroot = ast_walk_context_extensions(context, eroot))) {
6187  while ((e = ast_walk_extension_priorities(eroot, e))) {
6188  if (e->cached_app == app)
6189  e->cached_app = NULL;
6190  }
6191  }
6192  }
6194 
6195  return;
6196 }
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: pbx.c:8609
#define NULL
Definition: resample.c:96
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8507
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *exten)
Definition: pbx.c:8614
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
struct ast_exten * ast_walk_extension_priorities(struct ast_exten *exten, struct ast_exten *priority)
Definition: pbx.c:8662
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

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

References match_char::alt_char, ast_debug, ast_log, ast_str_alloca, ast_str_buffer(), ast_str_set(), match_char::deleted, ast_exten::exten, match_char::exten, scoreboard::exten, match_char::is_pattern, last, scoreboard::last_char, LOG_NOTICE, match_char::next_char, scoreboard::node, prefix, match_char::specificity, scoreboard::total_length, scoreboard::total_specificity, and match_char::x.

Referenced by new_find_extension().

1065 {
1066  /* if this extension is marked as deleted, then skip this -- if it never shows
1067  on the scoreboard, it will never be found, nor will halt the traversal. */
1068  if (deleted)
1069  return;
1070  board->total_specificity = spec;
1071  board->total_length = length;
1072  board->exten = exten;
1073  board->last_char = last;
1074  board->node = node;
1075 #ifdef NEED_DEBUG_HERE
1076  ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec);
1077 #endif
1078 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
char last_char
Definition: pbx.c:276
#define ast_log
Definition: astobj2.c:42
struct sla_ringing_trunk * last
Definition: app_meetme.c:1092
int total_specificity
Definition: pbx.c:274
char * exten
Definition: pbx.c:238
#define LOG_NOTICE
Definition: logger.h:263
struct match_char * node
Definition: pbx.c:278
int total_length
Definition: pbx.c:275
struct ast_exten * exten
Definition: pbx.c:280

◆ wait_for_hangup()

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

Definition at line 8267 of file pbx.c.

References ast_frfree, ast_read(), ast_safe_sleep(), ast_strlen_zero, and ast_waitfor().

Referenced by indicate_busy(), and indicate_congestion().

8268 {
8269  int res;
8270  struct ast_frame *f;
8271  double waitsec;
8272  int waittime;
8273 
8274  if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
8275  waitsec = -1;
8276  if (waitsec > -1) {
8277  waittime = waitsec * 1000.0;
8278  ast_safe_sleep(chan, waittime);
8279  } else do {
8280  res = ast_waitfor(chan, -1);
8281  if (res < 0)
8282  return;
8283  f = ast_read(chan);
8284  if (f)
8285  ast_frfree(f);
8286  } while(f);
8287 }
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1574
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
#define ast_frfree(fr)
Data structure associated with a single frame of data.
union ast_frame::@263 data

Variable Documentation

◆ autofallthrough

int autofallthrough = 1
static

Definition at line 763 of file pbx.c.

Referenced by pbx_set_autofallthrough().

◆ autohints

struct ao2_container* autohints
static

Container for autohint contexts.

Definition at line 380 of file pbx.c.

◆ conlock

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

Lock for the ast_context list.

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

Definition at line 785 of file pbx.c.

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

◆ context_merge_lock

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

Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.

Definition at line 790 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

Definition at line 777 of file pbx.c.

Referenced by ast_merge_contexts_and_delete().

◆ countcalls

int countcalls
static

Definition at line 773 of file pbx.c.

Referenced by ast_active_calls().

◆ device_state_sub

struct stasis_subscription* device_state_sub
static

Subscription for device state change events.

Definition at line 768 of file pbx.c.

◆ exception_function

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

Definition at line 2852 of file pbx.c.

◆ exception_store_info

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

Definition at line 2790 of file pbx.c.

◆ extenpatternmatchnew

int extenpatternmatchnew = 0
static

Definition at line 764 of file pbx.c.

Referenced by pbx_set_extenpatternmatchnew().

◆ extension_states

const struct cfextension_states extension_states[]
static

Referenced by ast_extension_state2str().

◆ extensionstate_buf

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

Definition at line 229 of file pbx.c.

Referenced by ast_extension_state2(), and extension_presence_state_helper().

◆ hintdevice_data

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

Definition at line 352 of file pbx.c.

Referenced by add_hintdevice().

◆ hintdevices

struct ao2_container* hintdevices
static

Container for hint devices.

Definition at line 363 of file pbx.c.

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

Referenced by lua_register_hints(), and pvalExtenSetHints().

◆ maxcalllock

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

Definition at line 772 of file pbx.c.

Referenced by decrease_call_count(), and increase_call_count().

◆ overrideswitch

char* overrideswitch = NULL
static

Definition at line 765 of file pbx.c.

Referenced by handle_cli_dialplan_save().

◆ pbx_cli

struct ast_cli_entry pbx_cli[]
static

Definition at line 6164 of file pbx.c.

◆ presence_state_sub

struct stasis_subscription* presence_state_sub
static

Subscription for presence state change events.

Definition at line 770 of file pbx.c.

◆ statecbs

struct ao2_container* statecbs
static

Definition at line 803 of file pbx.c.

◆ stateid

int stateid = 1
static

Definition at line 792 of file pbx.c.

◆ switch_data

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

Definition at line 228 of file pbx.c.

Referenced by pbx_find_extension().

◆ testtime_function

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

Definition at line 8316 of file pbx.c.

◆ totalcalls

int totalcalls
static

Definition at line 774 of file pbx.c.

Referenced by ast_processed_calls(), and timing_read().