Asterisk - The Open Source Telephony Project  GIT-master-1f78ee9
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"

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

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

8754 {
8755  int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
8756 
8757  if (!chan)
8758  return -2;
8759 
8760  if (context == NULL)
8761  context = ast_channel_context(chan);
8762  if (exten == NULL)
8763  exten = ast_channel_exten(chan);
8764 
8765  goto_func = (async) ? ast_async_goto : ast_explicit_goto;
8766  if (ast_exists_extension(chan, context, exten, priority,
8767  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)))
8768  return goto_func(chan, context, exten, priority);
8769  else {
8770  return AST_PBX_GOTO_FAILED;
8771  }
8772 }
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:6978
#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:4170
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:7002
#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 8031 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().

8032 {
8033  struct ast_exten *e, *el, *en;
8034  struct ast_context *tmp = con;
8035 
8036  /* Free includes */
8038  AST_VECTOR_FREE(&tmp->includes);
8039 
8040  /* Free ignorepats */
8042  AST_VECTOR_FREE(&tmp->ignorepats);
8043 
8044  /* Free switches */
8046  AST_VECTOR_FREE(&tmp->alts);
8047 
8048  if (tmp->registrar)
8049  ast_free(tmp->registrar);
8050 
8051  /* destroy the hash tabs */
8052  if (tmp->root_table) {
8054  }
8055  /* and destroy the pattern tree */
8056  if (tmp->pattern_tree)
8058 
8059  for (e = tmp->root; e;) {
8060  for (en = e->peer; en;) {
8061  el = en;
8062  en = en->peer;
8063  destroy_exten(el);
8064  }
8065  el = e;
8066  e = e->next;
8067  destroy_exten(el);
8068  }
8069  tmp->root = NULL;
8070  ast_rwlock_destroy(&tmp->lock);
8072  ast_free(tmp);
8073 }
#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:861
static void destroy_exten(struct ast_exten *e)
Definition: pbx.c:4669
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 4301 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().

4303 {
4304  int found = 0; /* set if we find at least one match */
4305  int res = 0;
4306  int autoloopflag;
4307  int error = 0; /* set an error conditions */
4308  struct ast_pbx *pbx;
4309  ast_callid callid;
4310 
4311  /* A little initial setup here */
4312  if (ast_channel_pbx(c)) {
4313  ast_log(LOG_WARNING, "%s already has PBX structure??\n", ast_channel_name(c));
4314  /* XXX and now what ? */
4316  }
4317  if (!(pbx = ast_calloc(1, sizeof(*pbx)))) {
4318  return AST_PBX_FAILED;
4319  }
4320 
4321  callid = ast_read_threadstorage_callid();
4322  /* If the thread isn't already associated with a callid, we should create that association. */
4323  if (!callid) {
4324  /* Associate new PBX thread with the channel call id if it is availble.
4325  * If not, create a new one instead.
4326  */
4327  callid = ast_channel_callid(c);
4328  if (!callid) {
4329  callid = ast_create_callid();
4330  if (callid) {
4331  ast_channel_lock(c);
4332  ast_channel_callid_set(c, callid);
4333  ast_channel_unlock(c);
4334  }
4335  }
4337  callid = 0;
4338  }
4339 
4340  ast_channel_pbx_set(c, pbx);
4341  /* Set reasonable defaults */
4342  ast_channel_pbx(c)->rtimeoutms = 10000;
4343  ast_channel_pbx(c)->dtimeoutms = 5000;
4344 
4345  ast_channel_lock(c);
4346  autoloopflag = ast_test_flag(ast_channel_flags(c), AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */
4348  ast_channel_unlock(c);
4349 
4351  /* If not successful fall back to 's' - but only if there is no given exten */
4352  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));
4353  /* XXX the original code used the existing priority in the call to
4354  * ast_exists_extension(), and reset it to 1 afterwards.
4355  * I believe the correct thing is to set it to 1 immediately.
4356  */
4357  set_ext_pri(c, "s", 1);
4358  }
4359 
4360  for (;;) {
4361  char dst_exten[256]; /* buffer to accumulate digits */
4362  int pos = 0; /* XXX should check bounds */
4363  int digit = 0;
4364  int invalid = 0;
4365  int timeout = 0;
4366 
4367  /* No digits pressed yet */
4368  dst_exten[pos] = '\0';
4369 
4370  /* loop on priorities in this context/exten */
4372  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL),
4373  &found, 1))) {
4374 
4375  if (!ast_check_hangup(c)) {
4377  continue;
4378  }
4379 
4380  /* Check softhangup flags. */
4382  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
4383  continue;
4384  }
4386  if (ast_exists_extension(c, ast_channel_context(c), "T", 1,
4387  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4388  set_ext_pri(c, "T", 1);
4389  /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4390  memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
4391  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
4392  continue;
4393  } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4394  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4395  raise_exception(c, "ABSOLUTETIMEOUT", 1);
4396  /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4397  memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
4398  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
4399  continue;
4400  }
4401 
4402  /* Call timed out with no special extension to jump to. */
4403  error = 1;
4404  break;
4405  }
4406  ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
4408  error = 1;
4409  break;
4410  } /* end while - from here on we can use 'break' to go out */
4411  if (found && res) {
4412  /* Something bad happened, or a hangup has been requested. */
4413  if (strchr("0123456789ABCDEF*#", res)) {
4414  ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
4415  pos = 0;
4416  dst_exten[pos++] = digit = res;
4417  dst_exten[pos] = '\0';
4418  } else if (res == AST_PBX_INCOMPLETE) {
4419  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));
4420  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));
4421 
4422  /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
4424  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4425  invalid = 1;
4426  } else {
4427  ast_copy_string(dst_exten, ast_channel_exten(c), sizeof(dst_exten));
4428  digit = 1;
4429  pos = strlen(dst_exten);
4430  }
4431  } else {
4432  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));
4433  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));
4434 
4435  if ((res == AST_PBX_ERROR)
4436  && ast_exists_extension(c, ast_channel_context(c), "e", 1,
4437  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4438  /* if we are already on the 'e' exten, don't jump to it again */
4439  if (!strcmp(ast_channel_exten(c), "e")) {
4440  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));
4441  error = 1;
4442  } else {
4443  raise_exception(c, "ERROR", 1);
4444  continue;
4445  }
4446  }
4447 
4448  if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_ASYNCGOTO) {
4449  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
4450  continue;
4451  }
4452  if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_TIMEOUT) {
4453  if (ast_exists_extension(c, ast_channel_context(c), "T", 1,
4454  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4455  set_ext_pri(c, "T", 1);
4456  /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4457  memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
4458  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
4459  continue;
4460  } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4461  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4462  raise_exception(c, "ABSOLUTETIMEOUT", 1);
4463  /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4464  memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
4465  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
4466  continue;
4467  }
4468  /* Call timed out with no special extension to jump to. */
4469  }
4470  error = 1;
4471  break;
4472  }
4473  }
4474  if (error)
4475  break;
4476 
4477  /*!\note
4478  * We get here on a failure of some kind: non-existing extension or
4479  * hangup. We have options, here. We can either catch the failure
4480  * and continue, or we can drop out entirely. */
4481 
4482  if (invalid
4483  || (ast_strlen_zero(dst_exten) &&
4485  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL)))) {
4486  /*!\note
4487  * If there is no match at priority 1, it is not a valid extension anymore.
4488  * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
4489  * neither exist.
4490  */
4491  if (ast_exists_extension(c, ast_channel_context(c), "i", 1,
4492  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4493  ast_verb(3, "Channel '%s' sent to invalid extension: context,exten,priority=%s,%s,%d\n",
4495  pbx_builtin_setvar_helper(c, "INVALID_EXTEN", ast_channel_exten(c));
4496  set_ext_pri(c, "i", 1);
4497  } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4498  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4499  raise_exception(c, "INVALID", 1);
4500  } else {
4501  ast_log(LOG_WARNING, "Channel '%s' sent to invalid extension but no invalid handler: context,exten,priority=%s,%s,%d\n",
4503  error = 1; /* we know what to do with it */
4504  break;
4505  }
4506  } else if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_TIMEOUT) {
4507  /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
4508  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
4509  } else { /* keypress received, get more digits for a full extension */
4510  int waittime = 0;
4511  if (digit)
4512  waittime = ast_channel_pbx(c)->dtimeoutms;
4513  else if (!autofallthrough)
4514  waittime = ast_channel_pbx(c)->rtimeoutms;
4515  if (!waittime) {
4516  const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
4517  if (!status)
4518  status = "UNKNOWN";
4519  ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", ast_channel_name(c), status);
4520  if (!strcasecmp(status, "CONGESTION"))
4521  res = indicate_congestion(c, "10");
4522  else if (!strcasecmp(status, "CHANUNAVAIL"))
4523  res = indicate_congestion(c, "10");
4524  else if (!strcasecmp(status, "BUSY"))
4525  res = indicate_busy(c, "10");
4526  error = 1; /* XXX disable message */
4527  break; /* exit from the 'for' loop */
4528  }
4529 
4530  if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
4531  break;
4532  if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
4533  timeout = 1;
4534  if (!timeout
4535  && ast_exists_extension(c, ast_channel_context(c), dst_exten, 1,
4536  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) { /* Prepare the next cycle */
4537  set_ext_pri(c, dst_exten, 1);
4538  } else {
4539  /* No such extension */
4540  if (!timeout && !ast_strlen_zero(dst_exten)) {
4541  /* An invalid extension */
4542  if (ast_exists_extension(c, ast_channel_context(c), "i", 1,
4543  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4544  ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, ast_channel_context(c), ast_channel_name(c));
4545  pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
4546  set_ext_pri(c, "i", 1);
4547  } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4548  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4549  raise_exception(c, "INVALID", 1);
4550  } else {
4552  "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
4553  dst_exten, ast_channel_context(c));
4554  found = 1; /* XXX disable message */
4555  break;
4556  }
4557  } else {
4558  /* A simple timeout */
4559  if (ast_exists_extension(c, ast_channel_context(c), "t", 1,
4560  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4561  ast_verb(3, "Timeout on %s\n", ast_channel_name(c));
4562  set_ext_pri(c, "t", 1);
4563  } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4564  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4565  raise_exception(c, "RESPONSETIMEOUT", 1);
4566  } else {
4568  "Timeout, but no rule 't' or 'e' in context '%s'\n",
4569  ast_channel_context(c));
4570  found = 1; /* XXX disable message */
4571  break;
4572  }
4573  }
4574  }
4575  }
4576  }
4577 
4578  if (!found && !error) {
4579  ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", ast_channel_name(c));
4580  }
4581 
4582  if (!args || !args->no_hangup_chan) {
4585  && ast_exists_extension(c, ast_channel_context(c), "h", 1,
4586  S_COR(ast_channel_caller(c)->id.number.valid,
4587  ast_channel_caller(c)->id.number.str, NULL))) {
4589  }
4591  }
4592 
4593  ast_channel_lock(c);
4595  ast_clear_flag(ast_channel_flags(c), AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
4596  ast_channel_unlock(c);
4599 
4600  if (!args || !args->no_hangup_chan) {
4601  ast_hangup(c);
4602  }
4603 
4604  return AST_PBX_SUCCESS;
4605 }
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:4195
char digit
#define ast_channel_lock(chan)
Definition: channel.h:2837
#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:455
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:1870
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:1892
int indicate_congestion(struct ast_channel *chan, const char *data)
Definition: pbx_builtins.c:726
Definition: pbx.h:211
#define AST_PBX_ERROR
Definition: pbx.h:50
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#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:2412
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:2451
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:4170
int indicate_busy(struct ast_channel *chan, const char *data)
Definition: pbx_builtins.c:708
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:441
#define AST_PBX_INCOMPLETE
Definition: pbx.h:51
void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
Definition: pbx.c:4259
ast_callid ast_create_callid(void)
factory function to create a new uniquely identifying callid.
Definition: logger.c:1865
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:4274
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_channel_unlock(chan)
Definition: channel.h:2838
#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:2523
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:4190
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:4200
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:2379
#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 8364 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().

8365 {
8366  const char *action_id = astman_get_header(m, "ActionID");
8367  struct ast_hint *hint;
8368  struct ao2_iterator it_hints;
8369  int hint_count = 0;
8370 
8371  if (!hints) {
8372  astman_send_error(s, m, "No dialplan hints are available");
8373  return 0;
8374  }
8375 
8376  astman_send_listack(s, m, "Extension Statuses will follow", "start");
8377 
8378  ao2_lock(hints);
8379  it_hints = ao2_iterator_init(hints, 0);
8380  for (; (hint = ao2_iterator_next(&it_hints)); ao2_ref(hint, -1)) {
8381 
8382  ao2_lock(hint);
8383 
8384  /* Ignore pattern matching hints; they are stored in the
8385  * hints container but aren't real from the perspective of
8386  * an AMI user
8387  */
8388  if (hint->exten->exten[0] == '_') {
8389  ao2_unlock(hint);
8390  continue;
8391  }
8392 
8393  ++hint_count;
8394 
8395  astman_append(s, "Event: ExtensionStatus\r\n");
8396  if (!ast_strlen_zero(action_id)) {
8397  astman_append(s, "ActionID: %s\r\n", action_id);
8398  }
8399  astman_append(s,
8400  "Exten: %s\r\n"
8401  "Context: %s\r\n"
8402  "Hint: %s\r\n"
8403  "Status: %d\r\n"
8404  "StatusText: %s\r\n\r\n",
8405  hint->exten->exten,
8406  hint->exten->parent->name,
8407  hint->exten->app,
8408  hint->laststate,
8410  ao2_unlock(hint);
8411  }
8412 
8413  ao2_iterator_destroy(&it_hints);
8414  ao2_unlock(hints);
8415 
8416  astman_send_list_complete_start(s, m, "ExtensionStateListComplete", hint_count);
8418 
8419  return 0;
8420 }
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
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
#define ast_strlen_zero(a)
Definition: muted.c:73
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:444
#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 7100 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().

7102 {
7103  struct ast_exten *ep;
7104  struct ast_exten *eh=e;
7105  int repeated_label = 0; /* Track if this label is a repeat, assume no. */
7106 
7107  for (ep = NULL; e ; ep = e, e = e->peer) {
7108  if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
7109  if (strcmp(e->name, tmp->name)) {
7111  "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n",
7112  tmp->name, tmp->priority, con->name, tmp->label, e->name, e->priority);
7113  } else {
7115  "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n",
7116  tmp->name, tmp->priority, con->name, tmp->label, e->priority);
7117  }
7118  repeated_label = 1;
7119  }
7120  if (e->priority >= tmp->priority) {
7121  break;
7122  }
7123  }
7124 
7125  if (repeated_label) { /* Discard the label since it's a repeat. */
7126  tmp->label = NULL;
7127  }
7128 
7129  if (!e) { /* go at the end, and ep is surely set because the list is not empty */
7131 
7132  if (tmp->label) {
7134  }
7135  ep->peer = tmp;
7136  return 0; /* success */
7137  }
7138  if (e->priority == tmp->priority) {
7139  /* Can't have something exactly the same. Is this a
7140  replacement? If so, replace, otherwise, bonk. */
7141  if (!replace) {
7142  if (strcmp(e->name, tmp->name)) {
7144  "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n",
7145  tmp->name, tmp->priority, con->name, e->name);
7146  } else {
7148  "Unable to register extension '%s' priority %d in '%s', already in use\n",
7149  tmp->name, tmp->priority, con->name);
7150  }
7151 
7152  return -1;
7153  }
7154  /* we are replacing e, so copy the link fields and then update
7155  * whoever pointed to e to point to us
7156  */
7157  tmp->next = e->next; /* not meaningful if we are not first in the peer list */
7158  tmp->peer = e->peer; /* always meaningful */
7159  if (ep) { /* We're in the peer list, just insert ourselves */
7161 
7162  if (e->label) {
7164  }
7165 
7167  if (tmp->label) {
7169  }
7170 
7171  ep->peer = tmp;
7172  } else if (el) { /* We're the first extension. Take over e's functions */
7173  struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
7174  tmp->peer_table = e->peer_table;
7175  tmp->peer_label_table = e->peer_label_table;
7178  if (e->label) {
7180  }
7181  if (tmp->label) {
7183  }
7184 
7187  el->next = tmp;
7188  /* The pattern trie points to this exten; replace the pointer,
7189  and all will be well */
7190  if (x) { /* if the trie isn't formed yet, don't sweat this */
7191  if (x->exten) { /* this test for safety purposes */
7192  x->exten = tmp; /* replace what would become a bad pointer */
7193  } else {
7194  ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
7195  }
7196  }
7197  } else { /* We're the very first extension. */
7198  struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
7201  tmp->peer_table = e->peer_table;
7202  tmp->peer_label_table = e->peer_label_table;
7205  if (e->label) {
7207  }
7208  if (tmp->label) {
7210  }
7211 
7214  con->root = tmp;
7215  /* The pattern trie points to this exten; replace the pointer,
7216  and all will be well */
7217  if (x) { /* if the trie isn't formed yet; no problem */
7218  if (x->exten) { /* this test for safety purposes */
7219  x->exten = tmp; /* replace what would become a bad pointer */
7220  } else {
7221  ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
7222  }
7223  }
7224  }
7225  if (tmp->priority == PRIORITY_HINT)
7226  ast_change_hint(e,tmp);
7227  /* Destroy the old one */
7228  if (e->datad)
7229  e->datad(e->data);
7230  ast_free(e);
7231  } else { /* Slip ourselves in just before e */
7232  tmp->peer = e;
7233  tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
7234  if (ep) { /* Easy enough, we're just in the peer list */
7235  if (tmp->label) {
7237  }
7239  ep->peer = tmp;
7240  } else { /* we are the first in some peer list, so link in the ext list */
7241  tmp->peer_table = e->peer_table;
7242  tmp->peer_label_table = e->peer_label_table;
7243  e->peer_table = 0;
7244  e->peer_label_table = 0;
7246  if (tmp->label) {
7248  }
7251  if (el)
7252  el->next = tmp; /* in the middle... */
7253  else
7254  con->root = tmp; /* ... or at the head */
7255  e->next = NULL; /* e is no more at the head, so e->next must be reset */
7256  }
7257  /* And immediately return success. */
7258  if (tmp->priority == PRIORITY_HINT) {
7259  ast_add_hint(tmp);
7260  }
7261  }
7262  return 0;
7263 }
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:3973
static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
Change hint for an extension.
Definition: pbx.c:4087
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 4755 of file pbx.c.

References countcalls.

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

4756 {
4757  return countcalls;
4758 }
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
datad
registrarwho registered the extension
Return values
0success
-1failure

Definition at line 6961 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().

6964 {
6965  int ret = -1;
6966  struct ast_context *c;
6967 
6969  if (c) {
6970  ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
6971  application, data, datad, registrar, NULL, 0);
6973  }
6974 
6975  return ret;
6976 }
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:7290
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:8493
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:4809
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 7290 of file pbx.c.

References ast_add_extension2_lockopt(), and ast_exten::datad.

Referenced by ast_add_extension(), and context_merge().

7294 {
7295  return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
7296  application, data, datad, registrar, registrar_file, registrar_line, 1);
7297 }
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:7316
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 7316 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().

7320 {
7321  /*
7322  * Sort extensions (or patterns) according to the rules indicated above.
7323  * These are implemented by the function ext_cmp()).
7324  * All priorities for the same ext/pattern/cid are kept in a list,
7325  * using the 'peer' field as a link field..
7326  */
7327  struct ast_exten *tmp, *tmp2, *e, *el = NULL;
7328  int res;
7329  int length;
7330  char *p;
7331  char expand_buf[VAR_BUF_SIZE];
7332  struct ast_exten dummy_exten = {0};
7333  char dummy_name[1024];
7334  int exten_fluff;
7335  int callerid_fluff;
7336 
7337  if (ast_strlen_zero(extension)) {
7338  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",
7339  con->name);
7340  return -1;
7341  }
7342 
7343  /* If we are adding a hint evalulate in variables and global variables */
7344  if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') {
7345  int inhibited;
7347 
7348  if (c) {
7350  ast_channel_context_set(c, con->name);
7351  }
7352 
7353  /*
7354  * We can allow dangerous functions when adding a hint since
7355  * altering dialplan is itself a privileged activity. Otherwise,
7356  * we could never execute dangerous functions.
7357  */
7358  inhibited = ast_thread_inhibit_escalations_swap(0);
7359  pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
7360  if (0 < inhibited) {
7362  }
7363 
7364  application = expand_buf;
7365  if (c) {
7366  ast_channel_unref(c);
7367  }
7368  }
7369 
7370  exten_fluff = ext_fluff_count(extension);
7371  callerid_fluff = callerid ? ext_fluff_count(callerid) : 0;
7372 
7373  length = sizeof(struct ast_exten);
7374  length += strlen(extension) + 1;
7375  if (exten_fluff) {
7376  length += strlen(extension) + 1 - exten_fluff;
7377  }
7378  length += strlen(application) + 1;
7379  if (label) {
7380  length += strlen(label) + 1;
7381  }
7382  if (callerid) {
7383  length += strlen(callerid) + 1;
7384  if (callerid_fluff) {
7385  length += strlen(callerid) + 1 - callerid_fluff;
7386  }
7387  } else {
7388  length ++; /* just the '\0' */
7389  }
7390  if (registrar_file) {
7391  length += strlen(registrar_file) + 1;
7392  }
7393 
7394  /* Be optimistic: Build the extension structure first */
7395  if (!(tmp = ast_calloc(1, length)))
7396  return -1;
7397 
7398  if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
7399  label = 0;
7400 
7401  /* use p as dst in assignments, as the fields are const char * */
7402  p = tmp->stuff;
7403  if (label) {
7404  tmp->label = p;
7405  strcpy(p, label);
7406  p += strlen(label) + 1;
7407  }
7408  tmp->name = p;
7409  p += ext_strncpy(p, extension, strlen(extension) + 1, 0);
7410  if (exten_fluff) {
7411  tmp->exten = p;
7412  p += ext_strncpy(p, extension, strlen(extension) + 1 - exten_fluff, 1);
7413  } else {
7414  /* no fluff, we don't need a copy. */
7415  tmp->exten = tmp->name;
7416  }
7417  tmp->priority = priority;
7418  tmp->cidmatch_display = tmp->cidmatch = p; /* but use p for assignments below */
7419 
7420  /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */
7421  if (callerid) {
7422  p += ext_strncpy(p, callerid, strlen(callerid) + 1, 0);
7423  if (callerid_fluff) {
7424  tmp->cidmatch = p;
7425  p += ext_strncpy(p, callerid, strlen(callerid) + 1 - callerid_fluff, 1);
7426  }
7428  } else {
7429  *p++ = '\0';
7431  }
7432 
7433  if (registrar_file) {
7434  tmp->registrar_file = p;
7435  strcpy(p, registrar_file);
7436  p += strlen(registrar_file) + 1;
7437  } else {
7438  tmp->registrar_file = NULL;
7439  }
7440 
7441  tmp->app = p;
7442  strcpy(p, application);
7443  tmp->parent = con;
7444  tmp->data = data;
7445  tmp->datad = datad;
7446  tmp->registrar = registrar;
7448 
7449  if (lock_context) {
7450  ast_wrlock_context(con);
7451  }
7452 
7453  if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
7454  an extension, and the trie exists, then we need to incrementally add this pattern to it. */
7455  ext_strncpy(dummy_name, tmp->exten, sizeof(dummy_name), 1);
7456  dummy_exten.exten = dummy_name;
7457  dummy_exten.matchcid = AST_EXT_MATCHCID_OFF;
7458  dummy_exten.cidmatch = 0;
7459  tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
7460  if (!tmp2) {
7461  /* hmmm, not in the trie; */
7462  add_exten_to_pattern_tree(con, tmp, 0);
7463  ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
7464  }
7465  }
7466  res = 0; /* some compilers will think it is uninitialized otherwise */
7467  for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */
7468  res = ext_cmp(e->exten, tmp->exten);
7469  if (res == 0) { /* extension match, now look at cidmatch */
7471  res = 0;
7472  else if (tmp->matchcid == AST_EXT_MATCHCID_ON && e->matchcid == AST_EXT_MATCHCID_OFF)
7473  res = 1;
7474  else if (e->matchcid == AST_EXT_MATCHCID_ON && tmp->matchcid == AST_EXT_MATCHCID_OFF)
7475  res = -1;
7476  else
7477  res = ext_cmp(e->cidmatch, tmp->cidmatch);
7478  }
7479  if (res >= 0)
7480  break;
7481  }
7482  if (e && res == 0) { /* exact match, insert in the priority chain */
7483  res = add_priority(con, tmp, el, e, replace);
7484  if (res < 0) {
7485  if (con->pattern_tree) {
7486  struct match_char *x = add_exten_to_pattern_tree(con, tmp, 1);
7487 
7488  if (x->exten) {
7489  x->deleted = 1;
7490  x->exten = 0;
7491  }
7492 
7494  }
7495 
7496  if (tmp->datad) {
7497  tmp->datad(tmp->data);
7498  /* if you free this, null it out */
7499  tmp->data = NULL;
7500  }
7501 
7502  ast_free(tmp);
7503  }
7504  if (lock_context) {
7505  ast_unlock_context(con);
7506  }
7507  if (res < 0) {
7508  errno = EEXIST;
7509  return -1;
7510  }
7511  } else {
7512  /*
7513  * not an exact match, this is the first entry with this pattern,
7514  * so insert in the main list right before 'e' (if any)
7515  */
7516  tmp->next = e;
7517  tmp->peer_table = ast_hashtab_create(13,
7522  0);
7528  0);
7529 
7530  if (el) { /* there is another exten already in this context */
7531  el->next = tmp;
7532  } else { /* this is the first exten in this context */
7533  if (!con->root_table) {
7534  con->root_table = ast_hashtab_create(27,
7539  0);
7540  }
7541  con->root = tmp;
7542  }
7543  if (label) {
7545  }
7548 
7549  if (lock_context) {
7550  ast_unlock_context(con);
7551  }
7552  if (tmp->priority == PRIORITY_HINT) {
7553  ast_add_hint(tmp);
7554  }
7555  }
7556  if (DEBUG_ATLEAST(1)) {
7557  if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
7558  ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
7559  tmp->name, tmp->priority, tmp->cidmatch_display, con->name, con);
7560  } else {
7561  ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s (%p)\n",
7562  tmp->name, tmp->priority, con->name, con);
7563  }
7564  }
7565 
7566  return 0;
7567 }
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:7059
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8511
static int ast_add_hint(struct ast_exten *e)
Add hint to hint list, check initial extension state.
Definition: pbx.c:3973
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:2873
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
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:1266
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:8501
static char * registrar
Definition: pbx_ael.c:78
#define ast_strlen_zero(a)
Definition: muted.c:73
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:7100
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:433
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_extension2()

Definition at line 7299 of file pbx.c.

References ast_add_extension2_lockopt(), and ast_exten::datad.

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

7303 {
7304  return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
7305  application, data, datad, registrar, registrar_file, registrar_line, 0);
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:7316
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 6941 of file pbx.c.

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

Referenced by ast_merge_contexts_and_delete().

6944 {
6945  int ret = -1;
6946  struct ast_context *c;
6947 
6948  c = find_context(context);
6949  if (c) {
6950  ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
6951  application, data, datad, registrar, NULL, 0, 1);
6952  }
6953 
6954  return ret;
6955 }
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:7316
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:4795
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 3973 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().

3974 {
3975  struct ast_hint *hint_new;
3976  struct ast_hint *hint_found;
3977  char *message = NULL;
3978  char *subtype = NULL;
3979  int presence_state;
3980 
3981  if (!e) {
3982  return -1;
3983  }
3984 
3985  /*
3986  * We must create the hint we wish to add before determining if
3987  * it is already in the hints container to avoid possible
3988  * deadlock when getting the current extension state.
3989  */
3990  hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint);
3991  if (!hint_new) {
3992  return -1;
3993  }
3994  AST_VECTOR_INIT(&hint_new->devices, 8);
3995 
3996  /* Initialize new hint. */
3998  if (!hint_new->callbacks) {
3999  ao2_ref(hint_new, -1);
4000  return -1;
4001  }
4002  hint_new->exten = e;
4003  if (strstr(e->app, "${") && e->exten[0] == '_') {
4004  /* The hint is dynamic and hasn't been evaluted yet */
4005  hint_new->laststate = AST_DEVICE_INVALID;
4007  } else {
4008  hint_new->laststate = ast_extension_state2(e, NULL);
4009  if ((presence_state = extension_presence_state_helper(e, &subtype, &message)) > 0) {
4010  hint_new->last_presence_state = presence_state;
4011  hint_new->last_presence_subtype = subtype;
4012  hint_new->last_presence_message = message;
4013  }
4014  }
4015 
4016  /* Prevent multiple add hints from adding the same hint at the same time. */
4017  ao2_lock(hints);
4018 
4019  /* Search if hint exists, do nothing */
4020  hint_found = ao2_find(hints, e, 0);
4021  if (hint_found) {
4022  ao2_ref(hint_found, -1);
4023  ao2_unlock(hints);
4024  ao2_ref(hint_new, -1);
4025  ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n",
4027  return -1;
4028  }
4029 
4030  /* Add new hint to the hints container */
4031  ast_debug(2, "HINTS: Adding hint %s: %s\n",
4033  ao2_link(hints, hint_new);
4034  if (add_hintdevice(hint_new, ast_get_extension_app(e))) {
4035  ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
4038  }
4039 
4040  /* if not dynamic */
4041  if (!(strstr(e->app, "${") && e->exten[0] == '_')) {
4042  struct ast_state_cb *state_cb;
4043  struct ao2_iterator cb_iter;
4044 
4045  /* For general callbacks */
4046  cb_iter = ao2_iterator_init(statecbs, 0);
4047  for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
4051  state_cb->data,
4053  hint_new,
4054  NULL);
4055  }
4056  ao2_iterator_destroy(&cb_iter);
4057  }
4058  ao2_unlock(hints);
4059  ao2_ref(hint_new, -1);
4060 
4061  return 0;
4062 }
struct ast_context * ast_get_extension_context(struct ast_exten *exten)
Definition: pbx.c:8524
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8529
void * data
Definition: pbx.c:305
static int extension_presence_state_helper(struct ast_exten *e, char **subtype, char **message)
Definition: pbx.c:3195
#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:3898
#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:444
#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:8577
static struct ao2_container * statecbs
Definition: pbx.c:803
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8519
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:3243
char * last_presence_subtype
Definition: pbx.c:339
static int hint_id_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:3882
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 7002 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().

7003 {
7004  struct ast_channel *newchan;
7005 
7006  ast_channel_lock(chan);
7007  /* Channels in a bridge or running a PBX can be sent directly to the specified destination */
7008  if (ast_channel_is_bridged(chan) || ast_channel_pbx(chan)) {
7010  priority += 1;
7011  }
7014  ast_channel_unlock(chan);
7015  return 0;
7016  }
7017  ast_channel_unlock(chan);
7018 
7019  /* Otherwise, we need to gain control of the channel first */
7020  newchan = ast_channel_yank(chan);
7021  if (!newchan) {
7022  ast_log(LOG_WARNING, "Unable to gain control of channel %s\n", ast_channel_name(chan));
7023  return -1;
7024  }
7026  if (ast_pbx_start(newchan)) {
7027  ast_hangup(newchan);
7028  ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(newchan));
7029  return -1;
7030  }
7031 
7032  return 0;
7033 }
#define ast_channel_lock(chan)
Definition: channel.h:2837
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:6978
#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:10627
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:4703
int ast_softhangup_nolock(struct ast_channel *chan, int reason)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2438
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10579
#define ast_channel_unlock(chan)
Definition: channel.h:2838
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2523
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 7035 of file pbx.c.

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

7036 {
7037  struct ast_channel *chan;
7038  int res = -1;
7039 
7040  if ((chan = ast_channel_get_by_name(channame))) {
7041  res = ast_async_goto(chan, context, exten, priority);
7042  chan = ast_channel_unref(chan);
7043  }
7044 
7045  return res;
7046 }
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:2873
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:7002
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:1439

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

References __ast_goto_if_exists().

8780 {
8781  return __ast_goto_if_exists(chan, context, exten, priority, 1);
8782 }
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:8753
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 8845 of file pbx.c.

References pbx_parseable_goto().

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

8846 {
8847  return pbx_parseable_goto(chan, goto_string, 1);
8848 }
static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string, int async)
Definition: pbx.c:8784

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

4186 {
4187  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
4188 }
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 4087 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().

4088 {
4089  struct ast_hint *hint;
4090 
4091  if (!oe || !ne) {
4092  return -1;
4093  }
4094 
4095  ao2_lock(hints);/* Locked to hold off others while we move the hint around. */
4096 
4097  /*
4098  * Unlink the hint from the hints container as the extension
4099  * name (which is the hash value) could change.
4100  */
4101  hint = ao2_find(hints, oe, OBJ_UNLINK);
4102  if (!hint) {
4103  ao2_unlock(hints);
4105  return -1;
4106  }
4107 
4108  remove_hintdevice(hint);
4109 
4110  /* Update the hint and put it back in the hints container. */
4111  ao2_lock(hint);
4112  hint->exten = ne;
4113 
4114  ao2_unlock(hint);
4115 
4116  ao2_link(hints, hint);
4117  if (add_hintdevice(hint, ast_get_extension_app(ne))) {
4118  ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
4121  }
4122  ao2_unlock(hints);
4123 
4124  publish_hint_change(hint, ne);
4125 
4126  ao2_ref(hint, -1);
4127 
4128  return 0;
4129 }
struct ast_context * ast_get_extension_context(struct ast_exten *exten)
Definition: pbx.c:8524
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8529
#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:4065
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8577
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8519
#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 6868 of file pbx.c.

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

Referenced by handle_cli_dialplan_add_ignorepat().

6869 {
6870  int ret = -1;
6871  struct ast_context *c;
6872 
6874  if (c) {
6877  }
6878  return ret;
6879 }
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:6881
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8493
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:4809
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 6881 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().

6882 {
6883  struct ast_ignorepat *ignorepat = ignorepat_alloc(value, registrar);
6884  int idx;
6885 
6886  if (!ignorepat) {
6887  return -1;
6888  }
6889 
6890  ast_wrlock_context(con);
6891  for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6892  const struct ast_ignorepat *i = ast_context_ignorepats_get(con, idx);
6893 
6894  if (!strcasecmp(ast_get_ignorepat_name(i), value)) {
6895  /* Already there */
6896  ast_unlock_context(con);
6897  ignorepat_free(ignorepat);
6898  errno = EEXIST;
6899  return -1;
6900  }
6901  }
6902  if (AST_VECTOR_APPEND(&con->ignorepats, ignorepat)) {
6903  ignorepat_free(ignorepat);
6904  ast_unlock_context(con);
6905  return -1;
6906  }
6907  ast_unlock_context(con);
6908 
6909  return 0;
6910 }
struct ast_ignorepats ignorepats
Definition: pbx.c:291
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8511
const struct ast_ignorepat * ast_context_ignorepats_get(const struct ast_context *con, int idx)
Definition: pbx.c:8726
#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:8721
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:8501
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 6697 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().

6698 {
6699  int ret = -1;
6700  struct ast_context *c;
6701 
6703  if (c) {
6704  ret = ast_context_add_include2(c, include, registrar);
6706  }
6707  return ret;
6708 }
int ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
Add a context include.
Definition: pbx.c:6717
static struct test_val c
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8493
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:4809
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 6717 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().

6719 {
6720  struct ast_include *new_include;
6721  int idx;
6722 
6723  /* allocate new include structure ... */
6724  new_include = include_alloc(value, registrar);
6725  if (!new_include) {
6726  return -1;
6727  }
6728 
6729  ast_wrlock_context(con);
6730 
6731  /* ... go to last include and check if context is already included too... */
6732  for (idx = 0; idx < ast_context_includes_count(con); idx++) {
6733  const struct ast_include *i = ast_context_includes_get(con, idx);
6734 
6735  if (!strcasecmp(ast_get_include_name(i), ast_get_include_name(new_include))) {
6736  include_free(new_include);
6737  ast_unlock_context(con);
6738  errno = EEXIST;
6739  return -1;
6740  }
6741  }
6742 
6743  /* ... include new context into context list, unlock, return */
6744  if (AST_VECTOR_APPEND(&con->includes, new_include)) {
6745  include_free(new_include);
6746  ast_unlock_context(con);
6747  return -1;
6748  }
6749  ast_debug(1, "Including context '%s' in context '%s'\n",
6750  ast_get_include_name(new_include), ast_get_context_name(con));
6751 
6752  ast_unlock_context(con);
6753 
6754  return 0;
6755 }
ast_include: include= support in extensions.conf
Definition: pbx_include.c:37
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8511
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:444
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:8501
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:8683
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8519
int ast_context_includes_count(const struct ast_context *con)
Definition: pbx.c:8678

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

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

6763 {
6764  int ret = -1;
6765  struct ast_context *c;
6766 
6768  if (c) { /* found, add switch to this context */
6769  ret = ast_context_add_switch2(c, sw, data, eval, registrar);
6771  }
6772  return ret;
6773 }
static struct test_val c
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8493
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:4809
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:6782
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 6782 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().

6784 {
6785  int idx;
6786  struct ast_sw *new_sw;
6787 
6788  /* allocate new sw structure ... */
6789  if (!(new_sw = sw_alloc(value, data, eval, registrar))) {
6790  return -1;
6791  }
6792 
6793  /* ... try to lock this context ... */
6794  ast_wrlock_context(con);
6795 
6796  /* ... go to last sw and check if context is already swd too... */
6797  for (idx = 0; idx < ast_context_switches_count(con); idx++) {
6798  const struct ast_sw *i = ast_context_switches_get(con, idx);
6799 
6800  if (!strcasecmp(ast_get_switch_name(i), ast_get_switch_name(new_sw)) &&
6801  !strcasecmp(ast_get_switch_data(i), ast_get_switch_data(new_sw))) {
6802  sw_free(new_sw);
6803  ast_unlock_context(con);
6804  errno = EEXIST;
6805  return -1;
6806  }
6807  }
6808 
6809  /* ... sw new context into context list, unlock, return */
6810  if (AST_VECTOR_APPEND(&con->alts, new_sw)) {
6811  sw_free(new_sw);
6812  ast_unlock_context(con);
6813  return -1;
6814  }
6815 
6816  ast_verb(3, "Including switch '%s/%s' in context '%s'\n",
6818 
6819  ast_unlock_context(con);
6820 
6821  return 0;
6822 }
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:8633
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8511
const struct ast_sw * ast_context_switches_get(const struct ast_context *con, int idx)
Definition: pbx.c:8638
#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:455
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:8501
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:8519
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 8241 of file pbx.c.

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

Referenced by ast_context_destroy_by_name().

8242 {
8246 }
void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
Definition: pbx.c:8076
static struct ast_hashtab * contexts_table
Definition: pbx.c:777
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8483
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8493
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 8225 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().

8226 {
8227  struct ast_context *con;
8228  int ret = -1;
8229 
8231  con = ast_context_find(context);
8232  if (con) {
8234  ret = 0;
8235  }
8237 
8238  return ret;
8239 }
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:8241
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8483
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8493
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:8590
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:8488
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8493
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 6189 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().

6190 {
6191  struct ast_context *tmp, **local_contexts;
6192  struct fake_context search;
6193  int length = sizeof(struct ast_context) + strlen(name) + 1;
6194 
6195  if (!contexts_table) {
6196  /* Protect creation of contexts_table from reentrancy. */
6198  if (!contexts_table) {
6204  0);
6205  }
6207  }
6208 
6209  ast_copy_string(search.name, name, sizeof(search.name));
6210  if (!extcontexts) {
6212  local_contexts = &contexts;
6213  tmp = ast_hashtab_lookup(contexts_table, &search);
6214  if (tmp) {
6215  tmp->refcount++;
6217  return tmp;
6218  }
6219  } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
6220  local_contexts = extcontexts;
6221  tmp = ast_hashtab_lookup(exttable, &search);
6222  if (tmp) {
6223  tmp->refcount++;
6224  return tmp;
6225  }
6226  }
6227 
6228  if ((tmp = ast_calloc(1, length))) {
6229  ast_rwlock_init(&tmp->lock);
6230  ast_mutex_init(&tmp->macrolock);
6231  strcpy(tmp->name, name);
6232  tmp->root = NULL;
6233  tmp->root_table = NULL;
6234  tmp->registrar = ast_strdup(registrar);
6235  AST_VECTOR_INIT(&tmp->includes, 0);
6236  AST_VECTOR_INIT(&tmp->ignorepats, 0);
6237  AST_VECTOR_INIT(&tmp->alts, 0);
6238  tmp->refcount = 1;
6239  } else {
6240  ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
6241  if (!extcontexts) {
6243  }
6244  return NULL;
6245  }
6246 
6247  if (!extcontexts) {
6248  tmp->next = *local_contexts;
6249  *local_contexts = tmp;
6250  ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
6252  } else {
6253  tmp->next = *local_contexts;
6254  if (exttable)
6255  ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
6256 
6257  *local_contexts = tmp;
6258  }
6259  ast_debug(1, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
6260  return tmp;
6261 }
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:8488
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:8483
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#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:8493
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 5153 of file pbx.c.

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

Referenced by _macro_exec().

5154 {
5155  struct ast_context *c;
5156  int ret = -1;
5157 
5159  if (c) {
5161 
5162  /* if we found context, lock macrolock */
5163  ret = ast_mutex_lock(&c->macrolock);
5164  }
5165 
5166  return ret;
5167 }
#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:8493
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4809
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 4943 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().

4944 {
4946 }
#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:4948

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

References ast_context_remove_extension_callerid2(), AST_EXT_MATCHCID_ANY, and NULL.

Referenced by add_extension(), and add_hints().

4974 {
4976 }
#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:4978

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

4949 {
4950  int ret = -1; /* default error return */
4951  struct ast_context *c;
4952 
4954  if (c) { /* ... remove extension ... */
4956  matchcallerid, registrar, 0);
4958  }
4959 
4960  return ret;
4961 }
static struct test_val c
static int priority
structure to hold extensions
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8493
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:4809
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:4978
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 4978 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().

4979 {
4980  struct ast_exten *exten, *prev_exten = NULL;
4981  struct ast_exten *peer;
4982  struct ast_exten ex, *exten2, *exten3;
4983  char dummy_name[1024];
4984  char dummy_cid[1024];
4985  struct ast_exten *previous_peer = NULL;
4986  struct ast_exten *next_peer = NULL;
4987  int found = 0;
4988 
4989  if (!already_locked)
4990  ast_wrlock_context(con);
4991 
4992 #ifdef NEED_DEBUG
4993  ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
4994 #endif
4995 #ifdef CONTEXT_DEBUG
4996  check_contexts(__FILE__, __LINE__);
4997 #endif
4998  /* find this particular extension */
4999  ex.exten = dummy_name;
5000  ext_strncpy(dummy_name, extension, sizeof(dummy_name), 1);
5001  ex.matchcid = matchcallerid;
5002  if (callerid) {
5003  ex.cidmatch = dummy_cid;
5004  ext_strncpy(dummy_cid, callerid, sizeof(dummy_cid), 1);
5005  } else {
5006  ex.cidmatch = NULL;
5007  }
5008  exten = ast_hashtab_lookup(con->root_table, &ex);
5009  if (exten) {
5010  if (priority == 0) {
5011  exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
5012  if (!exten2)
5013  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);
5014  if (con->pattern_tree) {
5015  struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
5016 
5017  if (x->exten) { /* this test for safety purposes */
5018  x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
5019  x->exten = 0; /* get rid of what will become a bad pointer */
5020  } else {
5021