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

Macros

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

Functions

void __ast_context_destroy (struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
 
static int __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
 
static void __ast_internal_context_destroy (struct ast_context *con)
 
static enum ast_pbx_result __ast_pbx_run (struct ast_channel *c, struct ast_pbx_args *args)
 
static void __init_extensionstate_buf (void)
 
static void __init_hintdevice_data (void)
 
static void __init_switch_data (void)
 
static int _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
 
static int acf_exception_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
 
static int action_extensionstatelist (struct mansession *s, const struct message *m)
 
static struct match_charadd_exten_to_pattern_tree (struct ast_context *con, struct ast_exten *e1, int findonly)
 
static int add_hintdevice (struct ast_hint *hint, const char *devicelist)
 add hintdevice structure and link it into the container.
 
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.
 
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.
 
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.
 
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.
 
int ast_context_add_ignorepat (const char *context, const char *value, const char *registrar)
 Add an ignorepat. More...
 
int ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar)
 
int ast_context_add_include (const char *context, const char *include, const char *registrar)
 Add a context include. More...
 
int ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar)
 Add a context include. More...
 
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
 Add a switch. More...
 
int ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
 Adds a switch (first param is a ast_context) More...
 
void ast_context_destroy (struct ast_context *con, const char *registrar)
 Destroy a context (matches the specified context or ANY context if NULL) More...
 
int ast_context_destroy_by_name (const char *context, const char *registrar)
 Destroy a context by name. More...
 
struct ast_contextast_context_find (const char *name)
 Find a context. More...
 
struct ast_contextast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
 Register a new context or find an existing one. More...
 
int ast_context_ignorepats_count (const struct ast_context *con)
 
const struct ast_ignorepatast_context_ignorepats_get (const struct ast_context *con, int idx)
 
int ast_context_includes_count (const struct ast_context *con)
 
const struct ast_includeast_context_includes_get (const struct ast_context *con, int idx)
 
int ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar)
 Simply remove extension from context. More...
 
int ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
 This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return. More...
 
int ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar)
 
int ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked)
 
int ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar)
 Remove an ignorepat. More...
 
int ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
 
int ast_context_remove_include (const char *context, const char *include, const char *registrar)
 Remove included contexts. This function locks contexts list by &conlist, search for the right context structure, leave context list locked and call ast_context_remove_include2 which removes include, unlock contexts list and return ... More...
 
int ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar)
 Locks context, remove included contexts, unlocks context. When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault. More...
 
int ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar)
 Remove a switch. More...
 
int ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar)
 This function locks given context, removes switch, unlock context and return. More...
 
void ast_context_set_autohints (struct ast_context *con, int enabled)
 Enable or disable autohints support on a context. More...
 
int ast_context_switches_count (const struct ast_context *con)
 
const struct ast_swast_context_switches_get (const struct ast_context *con, int idx)
 
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure. More...
 
enum ast_extension_states ast_devstate_to_extenstate (enum ast_device_state devstate)
 Map devstate to an extension state. More...
 
int ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Determine whether an extension exists. More...
 
int ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
 
int ast_extension_close (const char *pattern, const char *data, int needmore)
 
int ast_extension_cmp (const char *a, const char *b)
 Determine if one extension should match before another. More...
 
int ast_extension_match (const char *pattern, const char *extension)
 Determine if a given extension matches a given pattern (in NXX format) More...
 
int ast_extension_state (struct ast_channel *c, const char *context, const char *exten)
 Check extension state for an extension by using hint. More...
 
static int ast_extension_state2 (struct ast_exten *e, struct ao2_container *device_state_info)
 Check state of extension by using hints.
 
const char * ast_extension_state2str (int extension_state)
 Return extension_state as string. More...
 
static int ast_extension_state3 (struct ast_str *hint_app, struct ao2_container *device_state_info)
 
int ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
 Add watcher for extension states. More...
 
int ast_extension_state_add_destroy (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
 Add watcher for extension states with destructor. More...
 
int ast_extension_state_add_destroy_extended (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
 Add watcher for extended extension states with destructor. More...
 
int ast_extension_state_add_extended (const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
 Add watcher for extended extension states. More...
 
int ast_extension_state_del (int id, ast_state_cb_type change_cb)
 Deletes a state change watcher by ID. More...
 
int ast_extension_state_extended (struct ast_channel *c, const char *context, const char *exten, struct ao2_container **device_state_info)
 Check extended extension state for an extension by using hint. More...
 
int ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label. More...
 
int ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label. More...
 
const char * ast_get_context_name (struct ast_context *con)
 
const char * ast_get_context_registrar (struct ast_context *c)
 
const char * ast_get_extension_app (struct ast_exten *e)
 
void * ast_get_extension_app_data (struct ast_exten *e)
 
const char * ast_get_extension_cidmatch (struct ast_exten *e)
 
struct ast_contextast_get_extension_context (struct ast_exten *exten)
 
int ast_get_extension_data (char *buf, int bufsize, struct ast_channel *c, const char *context, const char *exten, int priority)
 Fill a string buffer with the data at a dialplan extension. More...
 
const char * ast_get_extension_label (struct ast_exten *exten)
 
int ast_get_extension_matchcid (struct ast_exten *e)
 
const char * ast_get_extension_name (struct ast_exten *exten)
 
int ast_get_extension_priority (struct ast_exten *exten)
 
const char * ast_get_extension_registrar (struct ast_exten *e)
 
const char * ast_get_extension_registrar_file (struct ast_exten *e)
 Get name of configuration file used by registrar to register this extension. More...
 
int ast_get_extension_registrar_line (struct ast_exten *e)
 Get line number of configuration file used by registrar to register this extension. More...
 
int ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
 Get hint for channel. More...
 
int ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
 
int ast_hashtab_compare_contexts (const void *ah_a, const void *ah_b)
 hashtable functions for contexts
 
unsigned int ast_hashtab_hash_contexts (const void *obj)
 
static struct ast_extenast_hint_extension (struct ast_channel *c, const char *context, const char *exten)
 
static struct ast_extenast_hint_extension_nolock (struct ast_channel *c, const char *context, const char *exten)
 Find hint for given extension in context.
 
int ast_hint_presence_state (struct ast_channel *c, const char *context, const char *exten, char **subtype, char **message)
 Uses hint and presence state callback to get the presence state of an extension. 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.
 
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.
 
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'
 
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.
 
static struct ast_extenget_canmatch_exten (struct match_char *node)
 
static void get_device_state_causing_channels (struct ao2_container *c)
 
static const char * get_pattern_node (struct pattern_node *node, const char *src, int pattern, const char *extenbuf)
 
static char * handle_debug_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Send ack once.
 
static int handle_hint_change_message_type (struct stasis_message *msg, enum ast_state_cb_update_reason reason)
 
static char * handle_set_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_show_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_show_hint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_hint: CLI support for listing registered dial plan hint
 
static char * handle_show_hints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_hints: CLI support for listing registered dial plan hints
 
static char * handle_unset_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int hashtab_compare_exten_labels (const void *ah_a, const void *ah_b)
 
static int hashtab_compare_exten_numbers (const void *ah_a, const void *ah_b)
 
static int hashtab_compare_extens (const void *ha_a, const void *ah_b)
 
static unsigned int hashtab_hash_extens (const void *obj)
 
static unsigned int hashtab_hash_labels (const void *obj)
 
static unsigned int hashtab_hash_priority (const void *obj)
 
static int hint_cmp (void *obj, void *arg, int flags)
 
static int hint_hash (const void *obj, const int flags)
 
static int hint_id_cmp (void *obj, void *arg, int flags)
 
static int hintdevice_cmp_multiple (void *obj, void *arg, int flags)
 
static void hintdevice_destroy (void *obj)
 
static int hintdevice_hash_cb (const void *obj, const int flags)
 
static int hintdevice_remove_cb (void *obj, void *arg, void *data, int flags)
 
static int increase_call_count (const struct ast_channel *c)
 Increase call count for channel. 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.
 
static int manager_show_dialplan (struct mansession *s, const struct message *m)
 Manager listing of dial plan.
 
static int manager_show_dialplan_helper (struct mansession *s, const struct message *m, const char *actionidtext, const char *context, const char *exten, struct dialplan_counters *dpc, const struct ast_include *rinclude, int includecount, const char *includes[])
 Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dialplan. Must check whether the difference is intentional or not.
 
static int matchcid (const char *cidpattern, const char *callerid)
 
static void new_find_extension (const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action)
 
static char * parse_hint_device (struct ast_str *hint_args)
 
static char * parse_hint_presence (struct ast_str *hint_args)
 
int pbx_checkcondition (const char *condition)
 Evaluate a condition. 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.
 
static void * pbx_outgoing_exec (void *data)
 Internal function which dials an outgoing leg and sends it to a provided extension or application.
 
static void pbx_outgoing_state_callback (struct ast_dial *dial)
 Internal dialing state callback which causes early media to trigger an answer.
 
int pbx_parse_location (struct ast_channel *chan, char **contextp, char **extenp, char **prip, int *ipri, int *mode, char *rest)
 Parses a dialplan location into context, extension, priority. 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
 
static void print_hintdevices_key (void *v_obj, void *where, ao2_prnt_fn *prnt)
 
static void print_hints_key (void *v_obj, void *where, ao2_prnt_fn *prnt)
 
static void print_statecbs_key (void *v_obj, void *where, ao2_prnt_fn *prnt)
 
static int publish_hint_change (struct ast_hint *hint, struct ast_exten *ne)
 Publish a hint changed event.
 
static int publish_hint_remove (struct ast_hint *hint)
 Publish a hint removed event.
 
int raise_exception (struct ast_channel *chan, const char *reason, int priority)
 
static int remove_hintdevice (struct ast_hint *hint)
 
void set_ext_pri (struct ast_channel *c, const char *exten, int pri)
 
static int show_debug_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
 
static int show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, const struct ast_include *rinclude, int includecount, const char *includes[])
 
static void show_dialplan_helper_extension_output (int fd, char *buf1, char *buf2, struct ast_exten *exten)
 Writes CLI output of a single extension for show dialplan.
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (hint_change_message_type)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (hint_remove_message_type)
 
static int statecbs_cmp (void *obj, void *arg, int flags)
 
static int testtime_write (struct ast_channel *chan, const char *cmd, char *var, const char *value)
 
static struct ast_extentrie_find_next_match (struct match_char *node)
 
static void unload_pbx (void)
 
void unreference_cached_app (struct ast_app *app)
 
static void update_scoreboard (struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node)
 
void wait_for_hangup (struct ast_channel *chan, const void *data)
 

Variables

static int autofallthrough = 1
 
static struct ao2_containerautohints
 Container for autohint contexts.
 
static ast_mutex_t conlock = { 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.
 
static struct ast_contextcontexts
 
static struct ast_hashtabcontexts_table = NULL
 
static int countcalls
 
static struct stasis_subscriptiondevice_state_sub
 Subscription for device state change events.
 
static struct ast_custom_function exception_function
 
static const struct ast_datastore_info exception_store_info
 
static int extenpatternmatchnew = 0
 
static const struct cfextension_states extension_states []
 
static struct 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.
 
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.
 
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

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

Function Documentation

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

Definition at line 4306 of file pbx.c.

References ast_callid_threadassoc_add(), ast_calloc, ast_channel_callid_set(), ast_channel_clear_softhangup(), ast_check_hangup(), ast_copy_string(), ast_create_callid(), ast_debug, ast_exists_extension(), AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, ast_hangup(), ast_matchmore_extension(), AST_PBX_ERROR, ast_pbx_h_exten_run(), ast_pbx_hangup_handler_run(), AST_PBX_INCOMPLETE, ast_read_threadstorage_callid(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), collect_digits(), ast_pbx::dtimeoutms, indicate_congestion(), ast_pbx_args::no_hangup_chan, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), raise_exception(), ast_pbx::rtimeoutms, S_COR, and set_ext_pri().

Referenced by ast_pbx_run_args().

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

add the extension in the priority chain.

Return values
0on success.
-1on failure.

Definition at line 7067 of file pbx.c.

References ast_add_hint(), ast_change_hint(), ast_hashtab_remove_object_via_lookup(), ast_exten::label, ast_exten::name, ast_context::name, ast_exten::next, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, PRIORITY_HINT, ast_context::root, and ast_context::root_table.

Referenced by ast_add_extension2_lockopt().

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

Add and extension to an extension context.

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

Definition at line 6928 of file pbx.c.

References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().

Referenced by app_create(), ast_hint_presence_state(), handle_cli_dialplan_add_extension(), and join_conference_bridge().

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

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

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

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

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

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

Definition at line 7257 of file pbx.c.

References ast_add_extension2_lockopt().

Referenced by ast_add_extension(), lua_register_hints(), and pbx_load_users().

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

Same as ast_add_extension2() but controls the context locking.

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

Definition at line 7283 of file pbx.c.

References add_priority(), ast_exten::app, ast_add_hint(), ast_calloc, ast_channel_unref, ast_dummy_channel_alloc, AST_EXT_MATCHCID_OFF, AST_EXT_MATCHCID_ON, ast_hashtab_create, ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_remove_this_object(), ast_hashtab_resize_java(), ast_thread_inhibit_escalations(), ast_thread_inhibit_escalations_swap(), ast_unlock_context(), ast_wrlock_context(), ast_exten::cidmatch, ast_exten::cidmatch_display, ast_exten::data, ast_state_cb::data, ast_exten::datad, ext_cmp(), ext_strncpy(), ast_exten::exten, ast_exten::label, ast_exten::matchcid, ast_exten::name, ast_context::name, ast_exten::next, ast_exten::parent, ast_context::pattern_tree, 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, and ast_context::root_table.

Referenced by ast_add_extension2(), and ast_add_extension2_nolock().

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

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

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

Definition at line 7266 of file pbx.c.

References ast_add_extension2_lockopt().

7270 {
7271  return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
7272  application, data, datad, registrar, registrar_file, registrar_line, 0);
7273 }
static int ast_add_extension2_lockopt(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, const char *registrar_file, int registrar_line, int lock_context)
Same as ast_add_extension2() but controls the context locking.
Definition: pbx.c:7283
structure to hold extensions
int ast_async_goto ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority 
)

Set the channel to next execute the specified dialplan location.

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

Definition at line 6969 of file pbx.c.

References ast_channel_is_bridged(), ast_channel_yank(), ast_explicit_goto(), AST_FLAG_IN_AUTOLOOP, ast_hangup(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, and ast_softhangup_nolock().

Referenced by action_redirect(), ast_async_goto_by_name(), chan_pjsip_cng_tone_detected(), comeback_goto(), and fax_detect_framehook().

6970 {
6971  struct ast_channel *newchan;
6972 
6973  ast_channel_lock(chan);
6974  /* Channels in a bridge or running a PBX can be sent directly to the specified destination */
6975  if (ast_channel_is_bridged(chan) || ast_channel_pbx(chan)) {
6976  if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP)) {
6977  priority += 1;
6978  }
6981  ast_channel_unlock(chan);
6982  return 0;
6983  }
6984  ast_channel_unlock(chan);
6985 
6986  /* Otherwise, we need to gain control of the channel first */
6987  newchan = ast_channel_yank(chan);
6988  if (!newchan) {
6989  ast_log(LOG_WARNING, "Unable to gain control of channel %s\n", ast_channel_name(chan));
6990  return -1;
6991  }
6993  if (ast_pbx_start(newchan)) {
6994  ast_hangup(newchan);
6995  ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(newchan));
6996  return -1;
6997  }
6998 
6999  return 0;
7000 }
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:6945
char context[AST_MAX_CONTEXT]
struct ast_channel * ast_channel_yank(struct ast_channel *yankee)
Gain control of a channel in the system.
Definition: channel.c:10593
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4708
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10545
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2458
char exten[AST_MAX_EXTENSION]
int ast_async_goto_if_exists ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority 
)
Note
This function will handle locking the channel as needed.

Definition at line 8786 of file pbx.c.

8787 {
8788  return __ast_goto_if_exists(chan, context, exten, priority, 1);
8789 }
char context[AST_MAX_CONTEXT]
char exten[AST_MAX_EXTENSION]
int ast_async_parseable_goto ( struct ast_channel chan,
const char *  goto_string 
)
Note
This function will handle locking the channel as needed.

Definition at line 8871 of file pbx.c.

Referenced by handle_redirect().

8872 {
8873  return pbx_parseable_goto(chan, goto_string, 1);
8874 }
int ast_canmatch_extension ( struct ast_channel c,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid 
)

Looks for a valid matching extension.

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

Definition at line 4190 of file pbx.c.

References pbx_extension_helper().

Referenced by leave_voicemail(), and valid_exit().

4191 {
4192  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
4193 }
char context[AST_MAX_CONTEXT]
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
char exten[AST_MAX_EXTENSION]
int ast_context_add_ignorepat ( const char *  context,
const char *  ignorepat,
const char *  registrar 
)

Add an ignorepat.

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

Adds an ignore pattern to a particular context.

Return values
0on success
-1on failure

Definition at line 6835 of file pbx.c.

References ast_unlock_contexts(), and find_context_locked().

Referenced by handle_cli_dialplan_add_ignorepat().

6836 {
6837  int ret = -1;
6838  struct ast_context *c;
6839 
6840  c = find_context_locked(context);
6841  if (c) {
6842  ret = ast_context_add_ignorepat2(c, value, registrar);
6844  }
6845  return ret;
6846 }
const char * registrar
Definition: pbx.c:286
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4814
ast_context: An extension context
Definition: pbx.c:284
int ast_context_add_include ( const char *  context,
const char *  include,
const char *  registrar 
)

Add a context include.

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

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

Return values
0on success
-1on error

Definition at line 6664 of file pbx.c.

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

Referenced by handle_cli_dialplan_add_include().

6665 {
6666  int ret = -1;
6667  struct ast_context *c;
6668 
6669  c = find_context_locked(context);
6670  if (c) {
6671  ret = ast_context_add_include2(c, include, registrar);
6673  }
6674  return ret;
6675 }
int ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
Add a context include.
Definition: pbx.c:6684
const char * registrar
Definition: pbx.c:286
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4814
ast_context: An extension context
Definition: pbx.c:284
int ast_context_add_include2 ( struct ast_context con,
const char *  value,
const char *  registrar 
)

Add a context include.

Adds an include taking a struct ast_context as the first parameter

Note
See ast_context_add_include for information on arguments

Definition at line 6684 of file pbx.c.

References ast_debug, ast_unlock_context(), AST_VECTOR_APPEND, ast_wrlock_context(), include_alloc(), include_free(), and ast_context::includes.

Referenced by ast_context_add_include().

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

Add a switch.

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

This function registers a switch with the asterisk switch architecture

Return values
0on success
-1on failure

Definition at line 6729 of file pbx.c.

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

6730 {
6731  int ret = -1;
6732  struct ast_context *c;
6733 
6734  c = find_context_locked(context);
6735  if (c) { /* found, add switch to this context */
6736  ret = ast_context_add_switch2(c, sw, data, eval, registrar);
6738  }
6739  return ret;
6740 }
const char * registrar
Definition: pbx.c:286
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4814
int ast_context_add_switch2(struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
Adds a switch (first param is a ast_context)
Definition: pbx.c:6749
ast_context: An extension context
Definition: pbx.c:284
char data[]
Definition: pbx.c:304
int ast_context_add_switch2 ( struct ast_context con,
const char *  value,
const char *  data,
int  eval,
const char *  registrar 
)

Adds a switch (first param is a ast_context)

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

Definition at line 6749 of file pbx.c.

References ast_context::alts, ast_unlock_context(), AST_VECTOR_APPEND, and ast_wrlock_context().

Referenced by ast_context_add_switch().

6751 {
6752  int idx;
6753  struct ast_sw *new_sw;
6754 
6755  /* allocate new sw structure ... */
6756  if (!(new_sw = sw_alloc(value, data, eval, registrar))) {
6757  return -1;
6758  }
6759 
6760  /* ... try to lock this context ... */
6761  ast_wrlock_context(con);
6762 
6763  /* ... go to last sw and check if context is already swd too... */
6764  for (idx = 0; idx < ast_context_switches_count(con); idx++) {
6765  const struct ast_sw *i = ast_context_switches_get(con, idx);
6766 
6767  if (!strcasecmp(ast_get_switch_name(i), ast_get_switch_name(new_sw)) &&
6768  !strcasecmp(ast_get_switch_data(i), ast_get_switch_data(new_sw))) {
6769  sw_free(new_sw);
6770  ast_unlock_context(con);
6771  errno = EEXIST;
6772  return -1;
6773  }
6774  }
6775 
6776  /* ... sw new context into context list, unlock, return */
6777  if (AST_VECTOR_APPEND(&con->alts, new_sw)) {
6778  sw_free(new_sw);
6779  ast_unlock_context(con);
6780  return -1;
6781  }
6782 
6783  ast_verb(3, "Including switch '%s/%s' in context '%s'\n",
6784  ast_get_switch_name(new_sw), ast_get_switch_data(new_sw), ast_get_context_name(con));
6785 
6786  ast_unlock_context(con);
6787 
6788  return 0;
6789 }
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8491
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
const char * registrar
Definition: pbx_sw.c:40
ast_sw: Switch statement in extensions.conf
Definition: pbx_sw.c:37
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition: pbx.c:8481
struct ast_sws alts
Definition: pbx.c:295
const char * data
Definition: pbx_sw.c:42
void ast_context_destroy ( struct ast_context con,
const char *  registrar 
)

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

Parameters
concontext to destroy
registrarwho registered it

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

Definition at line 8221 of file pbx.c.

References ast_unlock_contexts(), and ast_wrlock_contexts().

Referenced by ast_context_destroy_by_name(), lua_find_extension(), parking_lot_cfg_remove_extensions(), and unload_module().

8222 {
8224  __ast_context_destroy(contexts, contexts_table, con,registrar);
8226 }
const char * registrar
Definition: pbx_sw.c:40
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8463
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
int ast_context_destroy_by_name ( const char *  context,
const char *  registrar 
)

Destroy a context by name.

Parameters
contextName of the context to destroy
registrarwho registered it

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

Return values
-1context not found
0Success

Definition at line 8205 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_context().

8206 {
8207  struct ast_context *con;
8208  int ret = -1;
8209 
8211  con = ast_context_find(context);
8212  if (con) {
8214  ret = 0;
8215  }
8217 
8218  return ret;
8219 }
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: pbx.c:2439
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
Definition: pbx.c:8221
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8463
const char * registrar
Definition: pbx.c:286
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
ast_context: An extension context
Definition: pbx.c:284
struct ast_context* ast_context_find ( const char *  name)

Find a context.

Parameters
namename of the context to find

Will search for the context with the given name.

Returns
the ast_context on success, NULL on failure.

Definition at line 2439 of file pbx.c.

References ast_context_find(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), and ast_context::name.

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

2440 {
2441  struct ast_context *tmp;
2442  struct ast_context item = {
2443  .name = name,
2444  };
2445 
2446  if (!name) {
2447  return NULL;
2448  }
2450  if (contexts_table) {
2451  tmp = ast_hashtab_lookup(contexts_table, &item);
2452  } else {
2453  tmp = NULL;
2454  while ((tmp = ast_walk_contexts(tmp))) {
2455  if (!strcasecmp(name, tmp->name)) {
2456  break;
2457  }
2458  }
2459  }
2461  return tmp;
2462 }
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition: main/hashtab.c:486
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8468
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
const char * name
Definition: pbx.c:285
ast_context: An extension context
Definition: pbx.c:284
struct ast_context* ast_context_find_or_create ( struct ast_context **  extcontexts,
struct ast_hashtab exttable,
const char *  name,
const char *  registrar 
)

Register a new context or find an existing one.

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

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

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

Returns
NULL on failure, and an ast_context structure on success

Definition at line 6149 of file pbx.c.

References ast_context::alts, ast_calloc, ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create, ast_hashtab_insert_immediate, ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_rdlock_contexts(), ast_rwlock_init, ast_unlock_contexts(), AST_VECTOR_INIT, ast_wrlock_contexts(), ast_context::data, ast_context::ignorepats, ast_context::includes, ast_context::lock, ast_context::name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.

Referenced by app_create(), handle_cli_dialplan_add_extension(), handle_cli_dialplan_add_include(), lua_register_hints(), lua_register_switches(), parking_lot_cfg_create_extensions(), pbx_load_users(), and set_config().

6150 {
6151  struct ast_context *tmp, **local_contexts;
6152  struct ast_context search = {
6153  .name = name,
6154  };
6155  size_t name_bytes = strlen(name);
6156  size_t registrar_bytes = strlen(registrar);
6157  int length = sizeof(struct ast_context) + name_bytes + registrar_bytes + 2;
6158 
6159  if (!contexts_table) {
6160  /* Protect creation of contexts_table from reentrancy. */
6162  if (!contexts_table) {
6163  contexts_table = ast_hashtab_create(17,
6167  ast_hashtab_hash_contexts,
6168  0);
6169  }
6171  }
6172 
6173  if (!extcontexts) {
6175  local_contexts = &contexts;
6176  tmp = ast_hashtab_lookup(contexts_table, &search);
6177  if (tmp) {
6178  tmp->refcount++;
6180  return tmp;
6181  }
6182  } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
6183  local_contexts = extcontexts;
6184  tmp = ast_hashtab_lookup(exttable, &search);
6185  if (tmp) {
6186  tmp->refcount++;
6187  return tmp;
6188  }
6189  }
6190 
6191  if ((tmp = ast_calloc(1, length))) {
6192  ast_rwlock_init(&tmp->lock);
6193  tmp->name = memcpy(&tmp->data[0], name, name_bytes);
6194  tmp->registrar = memcpy(&tmp->data[name_bytes + 1], registrar, registrar_bytes);
6195  tmp->root = NULL;
6196  tmp->root_table = NULL;
6197  AST_VECTOR_INIT(&tmp->includes, 0);
6198  AST_VECTOR_INIT(&tmp->ignorepats, 0);
6199  AST_VECTOR_INIT(&tmp->alts, 0);
6200  tmp->refcount = 1;
6201 
6202  /* The context 'name' must be stored at the beginning of 'data.' The
6203  * order of subsequent strings (currently only 'registrar') is not
6204  * relevant. */
6205  ast_assert(tmp->name == &tmp->data[0]);
6206  } else {
6207  ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
6208  if (!extcontexts) {
6210  }
6211  return NULL;
6212  }
6213 
6214  if (!extcontexts) {
6215  tmp->next = *local_contexts;
6216  *local_contexts = tmp;
6217  ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
6219  } else {
6220  tmp->next = *local_contexts;
6221  if (exttable)
6222  ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
6223 
6224  *local_contexts = tmp;
6225  }
6226  ast_debug(1, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
6227  return tmp;
6228 }
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition: main/hashtab.c:486
int ast_hashtab_newsize_java(struct ast_hashtab *tab)
Create a prime number roughly 2x the current table size.
Definition: main/hashtab.c:127
struct ast_exten * root
Definition: pbx.c:289
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
Definition: lock.h:224
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8468
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: main/hashtab.c:84
struct ast_context * next
Definition: pbx.c:292
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8463
#define ast_hashtab_insert_immediate(tab, obj)
Insert without checking.
Definition: hashtab.h:290
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
const char * registrar
Definition: pbx.c:286
#define ast_debug(level,...)
Log a DEBUG message.
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
struct ast_ignorepats ignorepats
Definition: pbx.c:294
ast_rwlock_t lock
Definition: pbx.c:288
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
struct ast_includes includes
Definition: pbx.c:293
const char * name
Definition: pbx.c:285
int refcount
Definition: pbx.c:296
struct ast_hashtab * root_table
Definition: pbx.c:290
#define ast_hashtab_create(initial_buckets, compare, resize, newsize, hash, do_locking)
Create the hashtable list.
Definition: hashtab.h:254
struct ast_sws alts
Definition: pbx.c:295
ast_context: An extension context
Definition: pbx.c:284
char data[]
Definition: pbx.c:304
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
hashtable functions for contexts
Definition: pbx.c:688
int ast_context_remove_extension ( const char *  context,
const char *  extension,
int  priority,
const char *  registrar 
)

Simply remove extension from context.

Note
This function will lock conlock.

Definition at line 4948 of file pbx.c.

References AST_EXT_MATCHCID_ANY.

Referenced by conf_ended().

4949 {
4950  return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar);
4951 }
const char * registrar
Definition: pbx.c:286
structure to hold extensions
int ast_context_remove_extension2 ( struct ast_context con,
const char *  extension,
int  priority,
const char *  registrar,
int  already_locked 
)

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

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

Definition at line 4978 of file pbx.c.

References AST_EXT_MATCHCID_ANY.

4979 {
4980  return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked);
4981 }
const char * registrar
Definition: pbx.c:286
structure to hold extensions
int ast_context_remove_ignorepat ( const char *  context,
const char *  ignorepat,
const char *  registrar 
)

Remove an ignorepat.

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

This removes the given ignorepattern

Return values
0on success
-1on failure

Definition at line 6795 of file pbx.c.

References ast_unlock_contexts(), and find_context_locked().

6796 {
6797  int ret = -1;
6798  struct ast_context *c;
6799 
6800  c = find_context_locked(context);
6801  if (c) {
6802  ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
6804  }
6805  return ret;
6806 }
const char * registrar
Definition: pbx.c:286
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4814
ast_context: An extension context
Definition: pbx.c:284
int ast_context_remove_include ( const char *  context,
const char *  include,
const char *  registrar 
)

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

Remove a context include.

Definition at line 4836 of file pbx.c.

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

Referenced by handle_cli_dialplan_remove_include().

4837 {
4838  int ret = -1;
4839  struct ast_context *c;
4840 
4841  c = find_context_locked(context);
4842  if (c) {
4843  /* found, remove include from this context ... */
4844  ret = ast_context_remove_include2(c, include, registrar);
4846  }
4847  return ret;
4848 }
int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
Locks context, remove included contexts, unlocks context. When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault.
Definition: pbx.c:4859
const char * registrar
Definition: pbx.c:286
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4814
ast_context: An extension context
Definition: pbx.c:284
int ast_context_remove_include2 ( struct ast_context con,
const char *  include,
const char *  registrar 
)

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

Removes an include by an ast_context structure.

Return values
0on success.
-1on failure.

Definition at line 4859 of file pbx.c.

References ast_unlock_context(), AST_VECTOR_GET, AST_VECTOR_REMOVE_ORDERED, ast_wrlock_context(), include_free(), and ast_context::includes.

Referenced by ast_context_remove_include().

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

Remove a switch.

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

Definition at line 4894 of file pbx.c.

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

4895 {
4896  int ret = -1; /* default error return */
4897  struct ast_context *c;
4898 
4899  c = find_context_locked(context);
4900  if (c) {
4901  /* remove switch from this context ... */
4902  ret = ast_context_remove_switch2(c, sw, data, registrar);
4904  }
4905  return ret;
4906 }
int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
This function locks given context, removes switch, unlock context and return.
Definition: pbx.c:4916
const char * registrar
Definition: pbx.c:286
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4814
ast_context: An extension context
Definition: pbx.c:284
char data[]
Definition: pbx.c:304
int ast_context_remove_switch2 ( struct ast_context con,
const char *  sw,
const char *  data,
const char *  registrar 
)

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

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

Definition at line 4916 of file pbx.c.

References ast_context::alts, ast_unlock_context(), AST_VECTOR_GET, AST_VECTOR_REMOVE_ORDERED, and ast_wrlock_context().

Referenced by ast_context_remove_switch().

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

Enable or disable autohints support on a context.

Parameters
conpointer to the context
enabledwhether autohints are enabled

Definition at line 6230 of file pbx.c.

References ast_context::autohints, and enabled.

6231 {
6232  con->autohints = enabled;
6233 }
int autohints
Definition: pbx.c:297
static int enabled
Whether or not we are storing history.
int ast_context_verify_includes ( struct ast_context con)

Verifies includes in an ast_contect structure.

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

Definition at line 8732 of file pbx.c.

References ast_context_find().

8733 {
8734  int idx;
8735  int res = 0;
8736  int includecount = ast_context_includes_count(con);
8737 
8738  if (includecount >= AST_PBX_MAX_STACK) {
8739  ast_log(LOG_WARNING, "Context %s contains too many includes (%d). Maximum is %d.\n",
8740  ast_get_context_name(con), includecount, AST_PBX_MAX_STACK);
8741  }
8742 
8743  for (idx = 0; idx < includecount; idx++) {
8744  const struct ast_include *inc = ast_context_includes_get(con, idx);
8745 
8746  if (ast_context_find(include_rname(inc))) {
8747  continue;
8748  }
8749 
8750  res = -1;
8751  ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
8752  ast_get_context_name(con), include_rname(inc));
8753  break;
8754  }
8755 
8756  return res;
8757 }
ast_include: include= support in extensions.conf
Definition: pbx_include.c:37
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: pbx.c:2439
enum ast_extension_states ast_devstate_to_extenstate ( enum ast_device_state  devstate)

Map devstate to an extension state.

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

Definition at line 3006 of file pbx.c.

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

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

Determine whether an extension exists.

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

Definition at line 4175 of file pbx.c.

References pbx_extension_helper().

Referenced by __ast_pbx_run(), ast_app_dtget(), ast_bridge_setup_after_goto(), ast_pbx_outgoing_exten_predial(), chan_pjsip_cng_tone_detected(), comeback_goto(), dial_exec_full(), fax_detect_framehook(), grab_transfer(), jingle_new(), join_conference_bridge(), leave_voicemail(), local_call(), local_devicestate(), and waitstream_core().

4176 {
4177  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
4178 }
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
int ast_explicit_goto ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority 
)
Note
This function will handle locking the channel as needed.

Definition at line 6945 of file pbx.c.

References AST_FLAG_IN_AUTOLOOP.

Referenced by ast_async_goto(), and ast_bridge_setup_after_goto().

6946 {
6947  if (!chan)
6948  return -1;
6949 
6950  ast_channel_lock(chan);
6951 
6952  if (!ast_strlen_zero(context))
6953  ast_channel_context_set(chan, context);
6954  if (!ast_strlen_zero(exten))
6955  ast_channel_exten_set(chan, exten);
6956  if (priority > -1) {
6957  /* see flag description in channel.h for explanation */
6958  if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP)) {
6959  --priority;
6960  }
6961  ast_channel_priority_set(chan, priority);
6962  }
6963 
6964  ast_channel_unlock(chan);
6965 
6966  return 0;
6967 }
int ast_extension_cmp ( const char *  a,
const char *  b 
)

Determine if one extension should match before another.

Parameters
aextension to compare with b
bextension to compare with a

Checks whether or extension a should match before extension b

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

Definition at line 2197 of file pbx.c.

References ext_cmp().

Referenced by lua_extension_cmp().

2198 {
2199  int cmp;
2200 
2201  cmp = ext_cmp(a, b);
2202  if (cmp < 0) {
2203  return -1;
2204  }
2205  if (cmp > 0) {
2206  return 1;
2207  }
2208  return 0;
2209 }
static int ext_cmp(const char *a, const char *b)
the full routine to compare extensions in rules.
Definition: extconf.c:3944
int ast_extension_match ( const char *  pattern,
const char *  extension 
)

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

Parameters
patternpattern to match
extensionextension to check against the pattern.

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

Return values
1on match
0on failure

Definition at line 2427 of file pbx.c.

References ast_extension_match().

Referenced by ast_extension_match(), ast_ignore_pattern(), do_say(), lua_find_extension(), manager_show_dialplan_helper(), and reload().

2428 {
2429  return extension_match_core(pattern, extension, E_MATCH);
2430 }
structure to hold extensions
int ast_extension_state ( struct ast_channel c,
const char *  context,
const char *  exten 
)

Check extension state for an extension by using hint.

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

Definition at line 3170 of file pbx.c.

Referenced by get_queue_member_status().

3171 {
3172  return internal_extension_state_extended(c, context, exten, NULL);
3173 }
const char* ast_extension_state2str ( int  extension_state)

Return extension_state as string.

Return string representation of the state of an extension.

Definition at line 3126 of file pbx.c.

Referenced by handle_show_hint(), and handle_show_hints().

3127 {
3128  int i;
3129 
3130  for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
3131  if (extension_states[i].extension_state == extension_state)
3132  return extension_states[i].text;
3133  }
3134  return "Unknown";
3135 }
int ast_extension_state_add ( const char *  context,
const char *  exten,
ast_state_cb_type  change_cb,
void *  data 
)

Add watcher for extension states.

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

Definition at line 3823 of file pbx.c.

Referenced by create_queue_member().

3825 {
3826  return extension_state_add_destroy(context, exten, change_cb, NULL, data, 0);
3827 }
int ast_extension_state_add_destroy ( const char *  context,
const char *  exten,
ast_state_cb_type  change_cb,
ast_state_cb_destroy_type  destroy_cb,
void *  data 
)

Add watcher for extension states with destructor.

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

Definition at line 3817 of file pbx.c.

3819 {
3820  return extension_state_add_destroy(context, exten, change_cb, destroy_cb, data, 0);
3821 }
int ast_extension_state_add_destroy_extended ( const char *  context,
const char *  exten,
ast_state_cb_type  change_cb,
ast_state_cb_destroy_type  destroy_cb,
void *  data 
)

Add watcher for extended extension states with destructor.

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

Definition at line 3829 of file pbx.c.

3831 {
3832  return extension_state_add_destroy(context, exten, change_cb, destroy_cb, data, 1);
3833 }
int ast_extension_state_add_extended ( const char *  context,
const char *  exten,
ast_state_cb_type  change_cb,
void *  data 
)

Add watcher for extended extension states.

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

Definition at line 3835 of file pbx.c.

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

Deletes a state change watcher by ID.

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

Definition at line 3856 of file pbx.c.

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

3857 {
3858  struct ast_state_cb *p_cur;
3859  int ret = -1;
3860 
3861  if (!id) { /* id == 0 is a callback without extension */
3862  if (!change_cb) {
3863  return ret;
3864  }
3865  p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK);
3866  if (p_cur) {
3867  ret = 0;
3868  ao2_ref(p_cur, -1);
3869  }
3870  } else { /* callback with extension, find the callback based on ID */
3871  struct ast_hint *hint;
3872 
3873  ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
3874  hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
3875  if (hint) {
3876  p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
3877  if (p_cur) {
3878  ret = 0;
3879  ao2_ref(p_cur, -1);
3880  }
3881  ao2_ref(hint, -1);
3882  }
3883  ao2_unlock(hints);
3884  }
3885 
3886  return ret;
3887 }
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:1693
ast_state_cb: An extension state notify register item
Definition: pbx.c:308
ast_state_cb_type change_cb
Definition: pbx.c:316
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
Structure for dial plan hints.
Definition: pbx.c:331
static int find_hint_by_cb_id(void *obj, void *arg, int flags)
Find Hint by callback id.
Definition: pbx.c:3842
struct ao2_container * callbacks
Definition: pbx.c:339
int ast_extension_state_extended ( struct ast_channel c,
const char *  context,
const char *  exten,
struct ao2_container **  device_state_info 
)

Check extended extension state for an extension by using hint.

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

Definition at line 3176 of file pbx.c.

References ao2_ref, and container.

3178 {
3179  struct ao2_container *container = NULL;
3180  int ret;
3181 
3182  if (device_state_info) {
3183  container = alloc_device_state_info();
3184  }
3185 
3186  ret = internal_extension_state_extended(c, context, exten, container);
3187  if (ret < 0 && container) {
3188  ao2_ref(container, -1);
3189  container = NULL;
3190  }
3191 
3192  if (device_state_info) {
3193  get_device_state_causing_channels(container);
3194  *device_state_info = container;
3195  }
3196 
3197  return ret;
3198 }
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
struct ao2_container * container
Definition: res_fax.c:501
Generic container type.
int ast_findlabel_extension ( struct ast_channel c,
const char *  context,
const char *  exten,
const char *  label,
const char *  callerid 
)

Find the priority of an extension that has the specified label.

Parameters
cthis is not important
contextwhich context to look in
extenwhich extension to search for
labellabel of the action within the extension to match to priority
calleridcallerid to search for
Note
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
Return values
thepriority which matches the given label in the extension
-1if not found.

Definition at line 4180 of file pbx.c.

References pbx_extension_helper().

Referenced by action_redirect(), ast_ari_channels_continue_in_dialplan(), and pbx_parse_location().

4181 {
4182  return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
4183 }
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
int ast_findlabel_extension2 ( struct ast_channel c,
struct ast_context con,
const char *  exten,
const char *  label,
const char *  callerid 
)

Find the priority of an extension that has the specified label.

Note
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
This function is the same as ast_findlabel_extension, except that it accepts a pointer to an ast_context structure to specify the context instead of the name of the context. Otherwise, the functions behave the same.

Definition at line 4185 of file pbx.c.

References ast_findlabel_extension2(), and pbx_extension_helper().

Referenced by ast_findlabel_extension2().

4186 {
4187  return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
4188 }
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
int ast_get_extension_data ( char *  buf,
int  bufsize,
struct ast_channel c,
const char *  context,
const char *  exten,
int  priority 
)

Fill a string buffer with the data at a dialplan extension.

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

Definition at line 8567 of file pbx.c.

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

8569 {
8570  struct ast_exten *e;
8571  struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
8573  e = pbx_find_extension(c, NULL, &q, context, exten, priority, NULL, "", E_MATCH);
8574  if (e) {
8575  if (buf) {
8576  const char *tmp = ast_get_extension_app_data(e);
8577  if (tmp) {
8578  ast_copy_string(buf, tmp, bufsize);
8579  }
8580  }
8582  return 0;
8583  }
8585  return -1;
8586 }
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition: pbx.c:237
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8468
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
const char* ast_get_extension_registrar_file ( struct ast_exten e)

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

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

Definition at line 8537 of file pbx.c.

References ast_exten::registrar_file.

Referenced by show_dialplan_helper_extension_output().

8538 {
8539  return e ? e->registrar_file : NULL;
8540 }
const char * registrar_file
Definition: pbx.c:254
int ast_get_extension_registrar_line ( struct ast_exten e)

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

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

Definition at line 8542 of file pbx.c.

References ast_exten::registrar_line.

Referenced by show_dialplan_helper_extension_output().

8543 {
8544  return e ? e->registrar_line : 0;
8545 }
int registrar_line
Definition: pbx.c:255
int ast_get_hint ( char *  hint,
int  hintsize,
char *  name,
int  namesize,
struct ast_channel c,
const char *  context,
const char *  exten 
)

Get hint for channel.

If an extension hint exists, return non-zero.

Definition at line 4137 of file pbx.c.

References ast_copy_string().

4138 {
4139  struct ast_exten *e = ast_hint_extension(c, context, exten);
4140 
4141  if (e) {
4142  if (hint)
4143  ast_copy_string(hint, ast_get_extension_app(e), hintsize);
4144  if (name) {
4145  const char *tmp = ast_get_extension_app_data(e);
4146  if (tmp)
4147  ast_copy_string(name, tmp, namesize);
4148  }
4149  return -1;
4150  }
4151  return 0;
4152 }
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition: pbx.c:237
char * name
Definition: pbx.c:239
char * exten
Definition: pbx.c:238
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
int ast_goto_if_exists ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority 
)
Note
This function will handle locking the channel as needed.

Definition at line 8781 of file pbx.c.

Referenced by ast_bridge_setup_after_goto(), and valid_exit().

8782 {
8783  return __ast_goto_if_exists(chan, context, exten, priority, 0);
8784 }
int priority
Definition: pbx.c:243
char * exten
Definition: pbx.c:238
int ast_hint_presence_state ( struct ast_channel c,
const char *  context,
const char *  exten,
char **  subtype,
char **  message 
)

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

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

Definition at line 3226 of file pbx.c.

References ast_exten::app, ast_add_extension(), ast_free_ptr(), ast_strdup, ast_exten::cidmatch, ast_exten::data, ast_exten::exten, ast_exten::label, ast_exten::matchcid, ast_context::name, ast_exten::parent, ast_exten::priority, and ast_exten::registrar.

3227 {
3228  struct ast_exten *e;
3229 
3230  if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */
3231  return -1; /* No hint, return -1 */
3232  }
3233 
3234  if (e->exten[0] == '_') {
3235  /* Create this hint on-the-fly */
3236  ao2_lock(hints);
3237  ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
3238  e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
3239  e->registrar);
3240  ao2_unlock(hints);
3241  if (!(e = ast_hint_extension(c, context, exten))) {
3242  /* Improbable, but not impossible */
3243  return -1;
3244  }
3245  }
3246 
3247  return extension_presence_state_helper(e, subtype, message);
3248 }
const char * label
Definition: pbx.c:244
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition: pbx.c:237
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
void ast_free_ptr(void *ptr)
free() wrapper
Definition: main/astmm.c:1739
const char * registrar
Definition: pbx.c:253
int matchcid
Definition: pbx.c:240
int priority
Definition: pbx.c:243
char * exten
Definition: pbx.c:238
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition: pbx.c:6928
const char * cidmatch
Definition: pbx.c:241
const char * name
Definition: pbx.c:285
const char * app
Definition: pbx.c:246
struct ast_context * parent
Definition: pbx.c:245
void * data
Definition: pbx.c:248
int ast_ignore_pattern ( const char *  context,
const char *  pattern 
)

Checks to see if a number should be ignored.

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

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

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

Definition at line 6879 of file pbx.c.

References ast_context_find(), ast_extension_match(), ast_rdlock_contexts(), and ast_unlock_contexts().

Referenced by ast_app_dtget().

6880 {
6881  int ret = 0;
6882  struct ast_context *con;
6883 
6885  con = ast_context_find(context);
6886  if (con) {
6887  int idx;
6888 
6889  for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6890  const struct ast_ignorepat *pat = ast_context_ignorepats_get(con, idx);
6891 
6892  if (ast_extension_match(ast_get_ignorepat_name(pat), pattern)) {
6893  ret = 1;
6894  break;
6895  }
6896  }
6897  }
6899 
6900  return ret;
6901 }
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: pbx.c:2439
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8468
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
ast_ignorepat: Ignore patterns in dial plan
Definition: pbx_ignorepat.c:37
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
Definition: pbx.c:2427
ast_context: An extension context
Definition: pbx.c:284
int ast_matchmore_extension ( struct ast_channel c,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid 
)

Looks to see if adding anything to this extension might match something. (exists ^ canmatch)

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

Definition at line 4195 of file pbx.c.

References pbx_extension_helper().

Referenced by __ast_pbx_run(), ast_app_dtget(), and collect_digits().

4196 {
4197  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
4198 }
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
void ast_merge_contexts_and_delete ( struct ast_context **  extcontexts,
struct ast_hashtab exttable,
const char *  registrar 
)

Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.

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

Definition at line 6426 of file pbx.c.

References ao2_callback, ao2_container_count(), ao2_iterator_destroy(), AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_link, ao2_ref, ast_exten::app, ast_calloc, ast_copy_string(), ast_free_ptr(), ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hint_extension_nolock(), AST_HINT_UPDATE_DEVICE, AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_wrlock_contexts(), ast_hint::callbacks, ast_state_cb::change_cb, context_merge_lock, context_table_create_autohints(), ast_exten::data, ast_state_cb::data, ast_exten::exten, ast_hint::exten, ast_hint::last_presence_message, ast_hint::last_presence_state, ast_hint::last_presence_subtype, ast_hint::laststate, ast_context::name, ast_context::next, OBJ_UNLINK, ast_exten::parent, PRIORITY_HINT, and ast_exten::registrar.

Referenced by localized_merge_contexts_and_delete(), and lua_reload_extensions().

6427 {
6428  double ft;
6429  struct ast_context *tmp;
6430  struct ast_context *oldcontextslist;
6431  struct ast_hashtab *oldtable;
6432  struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
6433  struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
6434  struct store_hint *saved_hint;
6435  struct ast_hint *hint;
6436  struct ast_exten *exten;
6437  int length;
6438  struct ast_state_cb *thiscb;
6439  struct ast_hashtab_iter *iter;
6440  struct ao2_iterator i;
6441  int ctx_count = 0;
6442  struct timeval begintime;
6443  struct timeval writelocktime;
6444  struct timeval endlocktime;
6445  struct timeval enddeltime;
6446 
6447  /*
6448  * It is very important that this function hold the hints
6449  * container lock _and_ the conlock during its operation; not
6450  * only do we need to ensure that the list of contexts and
6451  * extensions does not change, but also that no hint callbacks
6452  * (watchers) are added or removed during the merge/delete
6453  * process
6454  *
6455  * In addition, the locks _must_ be taken in this order, because
6456  * there are already other code paths that use this order
6457  */
6458 
6459  begintime = ast_tvnow();
6460  ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
6462 
6463  if (!contexts_table) {
6464  /* Create any autohint contexts */
6466 
6467  /* Well, that's odd. There are no contexts. */
6468  contexts_table = exttable;
6469  contexts = *extcontexts;
6471  ast_mutex_unlock(&context_merge_lock);
6472  return;
6473  }
6474 
6475  iter = ast_hashtab_start_traversal(contexts_table);
6476  while ((tmp = ast_hashtab_next(iter))) {
6477  ++ctx_count;
6478  context_merge(extcontexts, exttable, tmp, registrar);
6479  }
6481 
6482  ao2_lock(hints);
6483  writelocktime = ast_tvnow();
6484 
6485  /* preserve all watchers for hints */
6487  for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
6488  if (ao2_container_count(hint->callbacks)) {
6489  size_t exten_len;
6490 
6491  ao2_lock(hint);
6492  if (!hint->exten) {
6493  /* The extension has already been destroyed. (Should never happen here) */
6494  ao2_unlock(hint);
6495  continue;
6496  }
6497 
6498  exten_len = strlen(hint->exten->exten) + 1;
6499  length = exten_len + strlen(hint->exten->parent->name) + 1
6500  + sizeof(*saved_hint);
6501  if (!(saved_hint = ast_calloc(1, length))) {
6502  ao2_unlock(hint);
6503  continue;
6504  }
6505 
6506  /* This removes all the callbacks from the hint into saved_hint. */
6507  while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
6508  AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
6509  /*
6510  * We intentionally do not unref thiscb to account for the
6511  * non-ao2 reference in saved_hint->callbacks
6512  */
6513  }
6514 
6515  saved_hint->laststate = hint->laststate;
6516  saved_hint->context = saved_hint->data;
6517  strcpy(saved_hint->data, hint->exten->parent->name);
6518  saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
6519  ast_copy_string(saved_hint->exten, hint->exten->exten, exten_len);
6520  if (hint->last_presence_subtype) {
6521  saved_hint->last_presence_subtype = ast_strdup(hint->last_presence_subtype);
6522  }
6523  if (hint->last_presence_message) {
6524  saved_hint->last_presence_message = ast_strdup(hint->last_presence_message);
6525  }
6526  saved_hint->last_presence_state = hint->last_presence_state;
6527  ao2_unlock(hint);
6528  AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
6529  }
6530  }
6532 
6533  /* save the old table and list */
6534  oldtable = contexts_table;
6535  oldcontextslist = contexts;
6536 
6537  /* move in the new table and list */
6538  contexts_table = exttable;
6539  contexts = *extcontexts;
6540 
6541  /*
6542  * Restore the watchers for hints that can be found; notify
6543  * those that cannot be restored.
6544  */
6545  while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
6546  struct pbx_find_info q = { .stacklen = 0 };
6547 
6548  exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
6549  PRIORITY_HINT, NULL, "", E_MATCH);
6550  /*
6551  * If this is a pattern, dynamically create a new extension for this
6552  * particular match. Note that this will only happen once for each
6553  * individual extension, because the pattern will no longer match first.
6554  */
6555  if (exten && exten->exten[0] == '_') {
6556  ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
6557  PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
6558  exten->registrar);
6559  /* rwlocks are not recursive locks */
6560  exten = ast_hint_extension_nolock(NULL, saved_hint->context,
6561  saved_hint->exten);
6562  }
6563 
6564  /* Find the hint in the hints container */
6565  hint = exten ? ao2_find(hints, exten, 0) : NULL;
6566  if (!hint) {
6567  /*
6568  * Notify watchers of this removed hint later when we aren't
6569  * encumbered by so many locks.
6570  */
6571  AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
6572  } else {
6573  ao2_lock(hint);
6574  while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
6575  ao2_link(hint->callbacks, thiscb);
6576  /* Ref that we added when putting into saved_hint->callbacks */
6577  ao2_ref(thiscb, -1);
6578  }
6579  hint->laststate = saved_hint->laststate;
6580  hint->last_presence_state = saved_hint->last_presence_state;
6581  hint->last_presence_subtype = saved_hint->last_presence_subtype;
6582  hint->last_presence_message = saved_hint->last_presence_message;
6583  ao2_unlock(hint);
6584  ao2_ref(hint, -1);
6585  /*
6586  * The free of saved_hint->last_presence_subtype and
6587  * saved_hint->last_presence_message is not necessary here.
6588  */
6589  ast_free(saved_hint);
6590  }
6591  }
6592 
6593  /* Create all applicable autohint contexts */
6594  context_table_create_autohints(contexts_table);
6595 
6596  ao2_unlock(hints);
6598 
6599  /*
6600  * Notify watchers of all removed hints with the same lock
6601  * environment as device_state_cb().
6602  */
6603  while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
6604  /* this hint has been removed, notify the watchers */
6605  while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
6606  execute_state_callback(thiscb->change_cb,
6607  saved_hint->context,
6608  saved_hint->exten,
6609  thiscb->data,
6611  NULL,
6612  NULL);
6613  /* Ref that we added when putting into saved_hint->callbacks */
6614  ao2_ref(thiscb, -1);
6615  }
6616  ast_free(saved_hint->last_presence_subtype);
6617  ast_free(saved_hint->last_presence_message);
6618  ast_free(saved_hint);
6619  }
6620 
6621  ast_mutex_unlock(&context_merge_lock);
6622  endlocktime = ast_tvnow();
6623 
6624  /*
6625  * The old list and hashtab no longer are relevant, delete them
6626  * while the rest of asterisk is now freely using the new stuff
6627  * instead.
6628  */
6629 
6630  ast_hashtab_destroy(oldtable, NULL);
6631 
6632  for (tmp = oldcontextslist; tmp; ) {
6633  struct ast_context *next; /* next starting point */
6634 
6635  next = tmp->next;
6636  __ast_internal_context_destroy(tmp);
6637  tmp = next;
6638  }
6639  enddeltime = ast_tvnow();
6640 
6641  ft = ast_tvdiff_us(writelocktime, begintime);
6642  ft /= 1000000.0;
6643  ast_verb(5,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
6644 
6645  ft = ast_tvdiff_us(endlocktime, writelocktime);
6646  ft /= 1000000.0;
6647  ast_verb(5,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
6648 
6649  ft = ast_tvdiff_us(enddeltime, endlocktime);
6650  ft /= 1000000.0;
6651  ast_verb(5,"Time to delete the old dialplan: %8.6f sec\n", ft);
6652 
6653  ft = ast_tvdiff_us(enddeltime, begintime);
6654  ft /= 1000000.0;
6655  ast_verb(5,"Total time merge_contexts_delete: %8.6f sec\n", ft);
6656  ast_verb(5, "%s successfully loaded %d contexts (enable debug for details).\n", registrar, ctx_count);
6657 }
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition: pbx.c:237
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
void * data
Definition: pbx.c:312
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:1693
ast_state_cb: An extension state notify register item
Definition: pbx.c:308
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: main/hashtab.c:683
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
static ast_mutex_t context_merge_lock
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
Definition: pbx.c:795
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
void ast_free_ptr(void *ptr)
free() wrapper
Definition: main/astmm.c:1739
const char * registrar
Definition: pbx.c:253
ast_state_cb_type change_cb
Definition: pbx.c:316
int last_presence_state
Definition: pbx.c:345
struct ast_context * next
Definition: pbx.c:292
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8463
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
const char * registrar
Definition: pbx.c:286
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define PRIORITY_HINT
Definition: pbx.h:54
void ast_hashtab_end_traversal(struct ast_hashtab_iter *it)
end the traversal, free the iterator, unlock if necc.
Definition: main/hashtab.c:674
struct ast_exten * exten
Hint extension.
Definition: pbx.c:338
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
char * exten
Definition: pbx.c:238
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
int laststate
Definition: pbx.c:342
Structure for dial plan hints.
Definition: pbx.c:331
an iterator for traversing the buckets
Definition: hashtab.h:105
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
Definition: linkedlists.h:252
static void context_table_create_autohints(struct ast_hashtab *table)
Definition: pbx.c:6290
Assume that the ao2_container is already locked.
Definition: astobj2.h:1852
const char * name
Definition: pbx.c:285
static struct ast_exten * ast_hint_extension_nolock(struct ast_channel *c, const char *context, const char *exten)
Find hint for given extension in context.
Definition: pbx.c:2991
const char * app
Definition: pbx.c:246
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
Definition: search.h:40
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:87
struct ast_context * parent
Definition: pbx.c:245
char * last_presence_message
Definition: pbx.c:347
void * data
Definition: pbx.c:248
char * last_presence_subtype
Definition: pbx.c:346
ast_context: An extension context
Definition: pbx.c:284
struct ao2_container * callbacks
Definition: pbx.c:339
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ast_hashtab_destroy(struct ast_hashtab *tab, void(*objdestroyfunc)(void *obj))
This func will free the hash table and all its memory.
Definition: main/hashtab.c:363
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
int ast_parseable_goto ( struct ast_channel chan,
const char *  goto_string 
)
Note
This function will handle locking the channel as needed.

Definition at line 8866 of file pbx.c.

Referenced by ast_bridge_setup_after_goto(), dial_exec_full(), and pbx_builtin_goto().

8867 {
8868  return pbx_parseable_goto(chan, goto_string, 0);
8869 }
void ast_pbx_h_exten_run ( struct ast_channel chan,
const char *  context 
)

Run the h exten from the given context.

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

Definition at line 4205 of file pbx.c.

References ast_debug, AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, AST_SOFTHANGUP_HANGUP_EXEC, ast_softhangup_nolock(), ast_spawn_extension(), and S_COR.

Referenced by __ast_pbx_run(), and ast_bridge_setup_after_goto().

4206 {
4207  int autoloopflag;
4208  int found;
4209  int spawn_error;
4210 
4211  ast_channel_lock(chan);
4212 
4213  /*
4214  * Make sure that the channel is marked as hungup since we are
4215  * going to run the h exten on it.
4216  */
4218 
4219  /* Set h exten location */
4220  if (context != ast_channel_context(chan)) {
4221  ast_channel_context_set(chan, context);
4222  }
4223  ast_channel_exten_set(chan, "h");
4224  ast_channel_priority_set(chan, 1);
4225 
4226  /* Save autoloop flag */
4227  autoloopflag = ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
4228  ast_set_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
4229  ast_channel_unlock(chan);
4230 
4231  for (;;) {
4232  spawn_error = ast_spawn_extension(chan, ast_channel_context(chan),
4233  ast_channel_exten(chan), ast_channel_priority(chan),
4234  S_COR(ast_channel_caller(chan)->id.number.valid,
4235  ast_channel_caller(chan)->id.number.str, NULL), &found, 1);
4236 
4237  ast_channel_lock(chan);
4238  if (spawn_error) {
4239  /* The code after the loop needs the channel locked. */
4240  break;
4241  }
4242  ast_channel_priority_set(chan, ast_channel_priority(chan) + 1);
4243  ast_channel_unlock(chan);
4244  }
4245  if (found && spawn_error) {
4246  /* Something bad happened, or a hangup has been requested. */
4247  ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n",
4248  ast_channel_context(chan), ast_channel_exten(chan),
4249  ast_channel_priority(chan), ast_channel_name(chan));
4250  ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n",
4251  ast_channel_context(chan), ast_channel_exten(chan),
4252  ast_channel_priority(chan), ast_channel_name(chan));
4253  }
4254 
4255  /* An "h" exten has been run, so indicate that one has been run. */
4256  ast_set_flag(ast_channel_flags(chan), AST_FLAG_BRIDGE_HANGUP_RUN);
4257 
4258  /* Restore autoloop flag */
4259  ast_set2_flag(ast_channel_flags(chan), autoloopflag, AST_FLAG_IN_AUTOLOOP);
4260  ast_channel_unlock(chan);
4261 }
int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
Launch a new extension (i.e. new stack)
Definition: pbx.c:4200
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:87
#define ast_debug(level,...)
Log a DEBUG message.
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2458
int ast_pbx_init ( void  )

Provided by pbx.c

Definition at line 8989 of file pbx.c.

References AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_container_alloc_hash, ao2_container_alloc_list, ao2_container_register(), ast_register_cleanup(), autohint_hash_cb(), hintdevice_cmp_multiple(), hintdevice_hash_cb(), and STASIS_MESSAGE_TYPE_INIT.

8990 {
8992  HASH_EXTENHINT_SIZE, hint_hash, NULL, hint_cmp);
8993  if (hints) {
8994  ao2_container_register("hints", hints, print_hints_key);
8995  }
8997  HASH_EXTENHINT_SIZE, hintdevice_hash_cb, NULL, hintdevice_cmp_multiple);
8998  if (hintdevices) {
8999  ao2_container_register("hintdevices", hintdevices, print_hintdevices_key);
9000  }
9001  /* This is protected by the context_and_merge lock */
9003  autohint_hash_cb, NULL, autohint_cmp);
9004  if (autohints) {
9005  ao2_container_register("autohints", autohints, print_autohint_key);
9006  }
9007  statecbs = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, statecbs_cmp);
9008  if (statecbs) {
9009  ao2_container_register("statecbs", statecbs, print_statecbs_key);
9010  }
9011 
9012  ast_register_cleanup(pbx_shutdown);
9013 
9014  if (STASIS_MESSAGE_TYPE_INIT(hint_change_message_type) != 0) {
9015  return -1;
9016  }
9017  if (STASIS_MESSAGE_TYPE_INIT(hint_remove_message_type) != 0) {
9018  return -1;
9019  }
9020 
9021  return (hints && hintdevices && autohints && statecbs) ? 0 : -1;
9022 }
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1493
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
static struct ao2_container * hintdevices
Container for hint devices.
Definition: pbx.c:370
static int hintdevice_cmp_multiple(void *obj, void *arg, int flags)
Definition: pbx.c:428
int ao2_container_register(const char *name, struct ao2_container *self, ao2_prnt_obj_fn *prnt_obj)
Register a container for CLI stats and integrity check.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
static int autohint_hash_cb(const void *obj, const int flags)
Definition: pbx.c:460
static int hintdevice_hash_cb(const void *obj, const int flags)
Definition: pbx.c:402
static struct ao2_container * autohints
Container for autohint contexts.
Definition: pbx.c:387
int ast_pbx_outgoing_app ( const char *  type,
struct ast_format_cap cap,
const char *  addr,
int  timeout,
const char *  app,
const char *  appdata,
int *  reason,
int  synchronous,
const char *  cid_num,
const char *  cid_name,
struct ast_variable vars,
const char *  account,
struct ast_channel **  locked_channel,
const struct ast_assigned_ids assignedids 
)

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

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

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

Definition at line 7980 of file pbx.c.

Referenced by orig_app().

7985 {
7986  return ast_pbx_outgoing_app_predial(type, cap, addr, timeout, app, appdata, reason, synchronous,
7987  cid_num, cid_name, vars, account, locked_channel, assignedids, NULL);
7988 }
int ast_pbx_outgoing_exten ( const char *  type,
struct ast_format_cap cap,
const char *  addr,
int  timeout,
const char *  context,
const char *  exten,
int  priority,
int *  reason,
int  synchronous,
const char *  cid_num,
const char *  cid_name,
struct ast_variable vars,
const char *  account,
struct ast_channel **  locked_channel,
int  early_media,
const struct ast_assigned_ids assignedids 
)

Synchronously or asynchronously make an outbound call and send it to a particular extension.

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

Definition at line 7916 of file pbx.c.

References ast_pbx_outgoing_exten_predial().

Referenced by orig_exten().

7921 {
7922  return ast_pbx_outgoing_exten_predial(type, cap, addr, timeout, context, exten, priority, reason,
7923  synchronous, cid_num, cid_name, vars, account, locked_channel, early_media, assignedids, NULL);
7924 }
int ast_pbx_outgoing_exten_predial(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids, const char *predial_callee)
Definition: pbx.c:7926
int ast_pbx_outgoing_exten_predial ( const char *  type,
struct ast_format_cap cap,
const char *  addr,
int  timeout,
const char *  context,
const char *  exten,
int  priority,
int *  reason,
int  synchronous,
const char *  cid_num,
const char *  cid_name,
struct ast_variable vars,
const char *  account,
struct ast_channel **  locked_channel,
int  early_media,
const struct ast_assigned_ids assignedids,
const char *  predial_callee 
)
Todo:
XXX Not good. The channel name is not unique if more than one originate fails at a time.

Definition at line 7926 of file pbx.c.

References ast_channel_alloc, ast_exists_extension(), ast_hangup(), ast_pbx_run(), ast_set_variables(), AST_STATE_DOWN, and pbx_builtin_setvar_helper().

Referenced by ast_pbx_outgoing_exten().

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

Execute the PBX in the current thread.

Parameters
cchannel to run the pbx on

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

Return values
Zeroon success
non-zeroon failure

Definition at line 4755 of file pbx.c.

References ast_pbx_run_args().

Referenced by ari_originate_dial(), ast_bridge_run_after_goto(), ast_pbx_outgoing_exten_predial(), and pbx_outgoing_exec().

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

Execute the PBX in the current thread.

Parameters
cchannel to run the pbx on
argsoptions for the pbx

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

Return values
Zeroon success
non-zeroon failure

Definition at line 4735 of file pbx.c.

References __ast_pbx_run(), AST_OPT_FLAG_FULLY_BOOTED, and increase_call_count().

Referenced by ast_pbx_run(), and stasis_app_exec().

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

Create a new thread and start the PBX.

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

Definition at line 4708 of file pbx.c.

References AST_OPT_FLAG_FULLY_BOOTED, and increase_call_count().

Referenced by ast_async_goto(), ast_iax2_new(), console_new(), dial_exec_full(), handle_response_clip(), handle_response_cmgr(), jingle_action_session_initiate(), local_call(), and unistim_new().

4709 {
4710  pthread_t t;
4711 
4712  if (!c) {
4713  ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
4714  return AST_PBX_FAILED;
4715  }
4716 
4717  if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
4718  ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
4719  return AST_PBX_FAILED;
4720  }
4721 
4722  if (increase_call_count(c))
4723  return AST_PBX_CALL_LIMIT;
4724 
4725  /* Start a new thread, and get something handling this channel. */
4726  if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
4727  ast_log(LOG_WARNING, "Failed to create new channel thread\n");
4728  decrease_call_count();
4729  return AST_PBX_FAILED;
4730  }
4731 
4732  return AST_PBX_SUCCESS;
4733 }
static int increase_call_count(const struct ast_channel *c)
Increase call count for channel.
Definition: pbx.c:4617
int ast_rdlock_context ( struct ast_context con)

Read locks a given context.

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

Definition at line 8486 of file pbx.c.

References ast_context::lock.

Referenced by handle_cli_dialplan_save(), lookup_c_ip(), lookup_ci(), and manager_show_dialplan_helper().

8487 {
8488  return ast_rwlock_rdlock(&con->lock);
8489 }
ast_rwlock_t lock
Definition: pbx.c:288
int ast_rdlock_contexts ( void  )

Read locks the context list.

Return values
0on success
-1on error

Definition at line 8468 of file pbx.c.

References conlock.

Referenced by ast_context_find(), ast_context_find_or_create(), ast_get_extension_data(), ast_ignore_pattern(), ast_unregister_application(), complete_dialplan_add_extension(), find_context_locked(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), and unreference_cached_app().

8469 {
8470  return ast_mutex_lock(&conlock);
8471 }
static ast_mutex_t conlock
Lock for the ast_context list.
Definition: pbx.c:790
int ast_spawn_extension ( struct ast_channel c,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid,
int *  found,
int  combined_find_spawn 
)

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

Parameters
cnot important
contextwhich context to generate the extension within
extennew extension to add
prioritypriority of new extension
calleridcallerid of extension
found
combined_find_spawnThis adds a new extension to the asterisk extension list.
Note
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
Return values
0on success
-1on failure.

Definition at line 4200 of file pbx.c.

References pbx_extension_helper().

Referenced by __ast_pbx_run(), and ast_pbx_h_exten_run().

4201 {
4202  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
4203 }
char context[AST_MAX_CONTEXT]
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
char exten[AST_MAX_EXTENSION]
int ast_str_get_hint ( struct ast_str **  hint,
ssize_t  hintsize,
struct ast_str **  name,
ssize_t  namesize,
struct ast_channel c,
const char *  context,
const char *  exten 
)

Get hint for channel.

If an extension hint exists, return non-zero.

Definition at line 4155 of file pbx.c.

References ast_str_set().

Referenced by ast_str_retrieve_variable().

4156 {
4157  struct ast_exten *e = ast_hint_extension(c, context, exten);
4158 
4159  if (!e) {
4160  return 0;
4161  }
4162 
4163  if (hint) {
4164  ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
4165  }
4166  if (name) {
4167  const char *tmp = ast_get_extension_app_data(e);
4168  if (tmp) {
4169  ast_str_set(name, namesize, "%s", tmp);
4170  }
4171  }
4172  return -1;
4173 }
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition: pbx.c:237
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
char * exten
Definition: pbx.c:238
int ast_unlock_context ( struct ast_context con)
Return values
Unlocksthe given context
Parameters
concontext to unlock
Return values
0on success
-1on failure

Definition at line 8491 of file pbx.c.

References ast_context::lock.

Referenced by ast_add_extension2_lockopt(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_include2(), ast_context_remove_switch2(), handle_cli_dialplan_save(), lookup_c_ip(), lookup_ci(), manager_show_dialplan_helper(), and parking_lot_cfg_create_extensions().

8492 {
8493  return ast_rwlock_unlock(&con->lock);
8494 }
ast_rwlock_t lock
Definition: pbx.c:288
int ast_unlock_contexts ( void  )
int ast_wrlock_context ( struct ast_context con)

Write locks a given context.

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

Definition at line 8481 of file pbx.c.

References ast_context::lock.

Referenced by ast_add_extension2_lockopt(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_include2(), ast_context_remove_switch2(), and parking_lot_cfg_create_extensions().

8482 {
8483  return ast_rwlock_wrlock(&con->lock);
8484 }
ast_rwlock_t lock
Definition: pbx.c:288
int ast_wrlock_contexts ( void  )

Write locks the context list.

Return values
0on success
-1on error

Definition at line 8463 of file pbx.c.

References conlock.

Referenced by ast_context_destroy(), ast_context_destroy_by_name(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and parking_lot_cfg_create_extensions().

8464 {
8465  return ast_mutex_lock(&conlock);
8466 }
static ast_mutex_t conlock
Lock for the ast_context list.
Definition: pbx.c:790
static int autohint_hash_cb ( const void *  obj,
const int  flags 
)
static
Note
Using the context name for hash

Definition at line 460 of file pbx.c.

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

Referenced by ast_pbx_init().

461 {
462  const struct ast_autohint *autohint;
463  const char *key;
464 
465  switch (flags & OBJ_SEARCH_MASK) {
466  case OBJ_SEARCH_KEY:
467  key = obj;
468  break;
469  case OBJ_SEARCH_OBJECT:
470  autohint = obj;
471  key = autohint->context;
472  break;
473  default:
474  ast_assert(0);
475  return 0;
476  }
477 
478  return ast_str_case_hash(key);
479 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
char context[1]
Name of the context.
Definition: pbx.c:396
Structure for dial plan autohints.
Definition: pbx.c:392
The arg parameter is an object of the same type.
Definition: astobj2.h:1087
Search option field mask.
Definition: astobj2.h:1072
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:1303
static int collect_digits ( struct ast_channel c,
int  waittime,
char *  buf,
int  buflen,
int  pos 
)
static

collect digits from the channel into the buffer.

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

Definition at line 4279 of file pbx.c.

References ast_channel_clear_softhangup(), ast_matchmore_extension(), AST_SOFTHANGUP_ASYNCGOTO, ast_waitfordigit(), ast_pbx::dtimeoutms, and S_COR.

Referenced by __ast_pbx_run().

4280 {
4281  int digit;
4282 
4283  buf[pos] = '\0'; /* make sure it is properly terminated */
4284  while (ast_matchmore_extension(c, ast_channel_context(c), buf, 1,
4285  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4286  /* As long as we're willing to wait, and as long as it's not defined,
4287  keep reading digits until we can't possibly get a right answer anymore. */
4288  digit = ast_waitfordigit(c, waittime);
4289  if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_ASYNCGOTO) {
4290  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
4291  } else {
4292  if (!digit) /* No entry */
4293  break;
4294  if (digit < 0) /* Error, maybe a hangup */
4295  return -1;
4296  if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
4297  buf[pos++] = digit;
4298  buf[pos] = '\0';
4299  }
4300  waittime = ast_channel_pbx(c)->dtimeoutms;
4301  }
4302  }
4303  return 0;
4304 }
Number structure.
Definition: app_followme.c:154
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition: channel.c:2432
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch) ...
Definition: pbx.c:4195
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3175
int dtimeoutms
Definition: pbx.h:215
static void context_table_create_autohints ( struct ast_hashtab table)
static

Set up an autohint placeholder in the hints container

Definition at line 6290 of file pbx.c.

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

Referenced by ast_merge_contexts_and_delete().

6291 {
6292  struct ast_context *con;
6293  struct ast_hashtab_iter *iter;
6294 
6295  /* Remove all autohints as the below iteration will recreate them */
6297 
6298  iter = ast_hashtab_start_traversal(table);
6299  while ((con = ast_hashtab_next(iter))) {
6300  size_t name_len = strlen(con->name) + 1;
6301  size_t registrar_len = strlen(con->registrar) + 1;
6302  struct ast_autohint *autohint;
6303 
6304  if (!con->autohints) {
6305  continue;
6306  }
6307 
6308  autohint = ao2_alloc_options(sizeof(*autohint) + name_len + registrar_len, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
6309  if (!autohint) {
6310  continue;
6311  }
6312 
6313  ast_copy_string(autohint->context, con->name, name_len);
6314  autohint->registrar = autohint->context + name_len;
6315  ast_copy_string(autohint->registrar, con->registrar, registrar_len);
6316 
6317  ao2_link(autohints, autohint);
6318  ao2_ref(autohint, -1);
6319 
6320  ast_verb(3, "Enabled autohints support on context '%s'\n", con->name);
6321  }
6323 }
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:1693
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: main/hashtab.c:683
char context[1]
Name of the context.
Definition: pbx.c:396
int autohints
Definition: pbx.c:297
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
const char * registrar
Definition: pbx.c:286
char * registrar
Name of the registrar.
Definition: pbx.c:394
void ast_hashtab_end_traversal(struct ast_hashtab_iter *it)
end the traversal, free the iterator, unlock if necc.
Definition: main/hashtab.c:674
Structure for dial plan autohints.
Definition: pbx.c:392
an iterator for traversing the buckets
Definition: hashtab.h:105
const char * name
Definition: pbx.c:285
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
ast_context: An extension context
Definition: pbx.c:284
static struct ao2_container * autohints
Container for autohint contexts.
Definition: pbx.c:387
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
static int ext_cmp_pattern_pos ( const char **  p,
unsigned char *  bitwise 
)
static

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

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

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

Definition at line 1977 of file pbx.c.

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

lookup for a context with a given name,

Return values
foundcontext or NULL if not found.

Definition at line 4800 of file pbx.c.

References ast_hashtab_lookup(), and ast_context::name.

4801 {
4802  struct ast_context item = {
4803  .name = context,
4804  };
4805 
4806  return ast_hashtab_lookup(contexts_table, &item);
4807 }
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition: main/hashtab.c:486
const char * name
Definition: pbx.c:285
ast_context: An extension context
Definition: pbx.c:284
static struct ast_context * find_context_locked ( const char *  context)
static

lookup for a context with a given name,

Return values
withconlock held if found.
NULLif not found.

Definition at line 4814 of file pbx.c.

References ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), and ast_context::name.

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

4815 {
4816  struct ast_context *c;
4817  struct ast_context item = {
4818  .name = context,
4819  };
4820 
4822  c = ast_hashtab_lookup(contexts_table, &item);
4823  if (!c) {
4825  }
4826 
4827  return c;
4828 }
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition: main/hashtab.c:486
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8468
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
const char * name
Definition: pbx.c:285
ast_context: An extension context
Definition: pbx.c:284
static int hintdevice_cmp_multiple ( void *  obj,
void *  arg,
int  flags 
)
static
Note
Devices on hints are not unique so no CMP_STOP is returned Dont use ao2_find against hintdevices container cause there always could be more than one result.

Definition at line 428 of file pbx.c.

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

Referenced by ast_pbx_init().

429 {
430  struct ast_hintdevice *left = obj;
431  struct ast_hintdevice *right = arg;
432  const char *right_key = arg;
433  int cmp;
434 
435  switch (flags & OBJ_SEARCH_MASK) {
436  case OBJ_SEARCH_OBJECT:
437  right_key = right->hintdevice;
438  /* Fall through */
439  case OBJ_SEARCH_KEY:
440  cmp = strcasecmp(left->hintdevice, right_key);
441  break;
443  /*
444  * We could also use a partial key struct containing a length
445  * so strlen() does not get called for every comparison instead.
446  */
447  cmp = strncmp(left->hintdevice, right_key, strlen(right_key));
448  break;
449  default:
450  ast_assert(0);
451  cmp = 0;
452  break;
453  }
454  return cmp ? 0 : CMP_MATCH;
455 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
char hintdevice[1]
Definition: pbx.c:383
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1116
The arg parameter is an object of the same type.
Definition: astobj2.h:1087
Structure for dial plan hint devices.
Definition: pbx.c:376
Search option field mask.
Definition: astobj2.h:1072
static int hintdevice_hash_cb ( const void *  obj,
const int  flags 
)
static
Note
Using the device for hash

Definition at line 402 of file pbx.c.

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

Referenced by ast_pbx_init().

403 {
404  const struct ast_hintdevice *ext;
405  const char *key;
406 
407  switch (flags & OBJ_SEARCH_MASK) {
408  case OBJ_SEARCH_KEY:
409  key = obj;
410  break;
411  case OBJ_SEARCH_OBJECT:
412  ext = obj;
413  key = ext->hintdevice;
414  break;
415  default:
416  ast_assert(0);
417  return 0;
418  }
419 
420  return ast_str_case_hash(key);
421 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
char hintdevice[1]
Definition: pbx.c:383
The arg parameter is an object of the same type.
Definition: astobj2.h:1087
Structure for dial plan hint devices.
Definition: pbx.c:376
Search option field mask.
Definition: astobj2.h:1072
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:1303
static int increase_call_count ( const struct ast_channel c)
static

Increase call count for channel.

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

Definition at line 4617 of file pbx.c.

References ast_option_maxcalls, ast_option_maxload, and option_minmemfree.

Referenced by ast_pbx_run_args(), and ast_pbx_start().

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

Provided by pbx.c

Definition at line 8421 of file pbx.c.

References __ast_custom_function_register(), ast_cli_register_multiple, ast_device_state_message_type(), ast_device_state_topic_all(), ast_manager_register_xml_core, ast_presence_state_message_type(), ast_presence_state_topic_all(), ast_register_cleanup(), manager_show_dialplan(), stasis_subscription_accept_message_type(), STASIS_SUBSCRIPTION_FILTER_SELECTIVE, and stasis_subscription_set_filter().

8422 {
8423  int res = 0;
8424 
8425  ast_register_cleanup(unload_pbx);
8426 
8427  /* Initialize the PBX */
8428  ast_verb(1, "Asterisk PBX Core Initializing\n");
8429 
8430  ast_verb(5, "Registering builtin functions:\n");
8431  ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
8432  __ast_custom_function_register(&exception_function, NULL);
8433  __ast_custom_function_register(&testtime_function, NULL);
8434 
8435  /* Register manager application */
8436  res |= ast_manager_register_xml_core("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan);
8437  res |= ast_manager_register_xml_core("ExtensionStateList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_extensionstatelist);
8438 
8439  if (res) {
8440  return -1;
8441  }
8442 
8443  if (!(device_state_sub = stasis_subscribe(ast_device_state_topic_all(), device_state_cb, NULL))) {
8444  return -1;
8445  }
8447  stasis_subscription_accept_message_type(device_state_sub, hint_change_message_type());
8448  stasis_subscription_accept_message_type(device_state_sub, hint_remove_message_type());
8450 
8451  if (!(presence_state_sub = stasis_subscribe(ast_presence_state_topic_all(), presence_state_cb, NULL))) {
8452  return -1;
8453  }
8456 
8457  return 0;
8458 }
static struct stasis_subscription * presence_state_sub
Subscription for presence state change events.
Definition: pbx.c:775
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition: stasis.c:1077
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:202
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
static int manager_show_dialplan(struct mansession *s, const struct message *m)
Manager listing of dial plan.
Definition: pbx.c:5970
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
Definition: devicestate.c:668
struct stasis_message_type * ast_presence_state_message_type(void)
Get presence state message type.
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition: stasis.c:1023
int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
Register a custom function.
struct stasis_topic * ast_presence_state_topic_all(void)
Get presence state topic.
static struct stasis_subscription * device_state_sub
Subscription for device state change events.
Definition: pbx.c:773
int pbx_checkcondition ( const char *  condition)

Evaluate a condition.

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

Definition at line 8282 of file pbx.c.

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

Attempt to convert disconnect cause to old originate reason.

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

Definition at line 7681 of file pbx.c.

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, AST_DIAL_RESULT_ANSWERED, and AST_DIAL_RESULT_HANGUP.

7682 {
7683  enum ast_control_frame_type pbx_reason;
7684 
7685  if (dial_result == AST_DIAL_RESULT_ANSWERED) {
7686  /* Remote end answered. */
7687  pbx_reason = AST_CONTROL_ANSWER;
7688  } else if (dial_result == AST_DIAL_RESULT_HANGUP) {
7689  /* Caller hungup */
7690  pbx_reason = AST_CONTROL_HANGUP;
7691  } else {
7692  switch (cause) {
7693  case AST_CAUSE_USER_BUSY:
7694  pbx_reason = AST_CONTROL_BUSY;
7695  break;
7696  case AST_CAUSE_CALL_REJECTED:
7697  case AST_CAUSE_NETWORK_OUT_OF_ORDER:
7698  case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
7699  case AST_CAUSE_NORMAL_TEMPORARY_FAILURE:
7700  case AST_CAUSE_SWITCH_CONGESTION:
7701  case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
7702  pbx_reason = AST_CONTROL_CONGESTION;
7703  break;
7704  case AST_CAUSE_ANSWERED_ELSEWHERE:
7705  case AST_CAUSE_NO_ANSWER:
7706  /* Remote end was ringing (but isn't anymore) */
7707  pbx_reason = AST_CONTROL_RINGING;
7708  break;
7709  case AST_CAUSE_UNALLOCATED:
7710  default:
7711  /* Call Failure (not BUSY, and not NO_ANSWER, maybe Circuit busy or down?) */
7712  pbx_reason = 0;
7713  break;
7714  }
7715  }
7716 
7717  return pbx_reason;
7718 }
ast_control_frame_type
Internal control frame subtype field values.
static int pbx_extension_helper ( struct ast_channel c,
struct ast_context con,
const char *  context,
const char *  exten,
int  priority,
const char *  label,
const char *  callerid,
enum ext_match_t  action,
int *  found,
int  combined_find_spawn 
)
static

The return value depends on the action:

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

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

Definition at line 2875 of file pbx.c.

References ast_exten::app, app_name(), ast_copy_string(), ast_debug, ast_rdlock_contexts(), ast_strdupa, ast_unlock_contexts(), ast_exten::cached_app, COLORIZE_FMT, ast_exten::data, EXT_DATA_SIZE, ast_switch::name, ast_context::name, pbx_exec(), pbx_findapp(), ast_exten::priority, and S_OR.

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

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

Parses a dialplan location into context, extension, priority.

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

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

Return values
0success
non-zerofailure

Definition at line 8791 of file pbx.c.

References ast_findlabel_extension(), ast_channel::context, ast_channel::exten, and S_COR.

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

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

Definition at line 4770 of file pbx.c.

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

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

Definition at line 4777 of file pbx.c.

4778 {
4779  int oldval = extenpatternmatchnew;
4780  extenpatternmatchnew = newval;
4781  return oldval;
4782 }
void pbx_set_overrideswitch ( const char *  newval)

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

Since
1.6.1

Definition at line 4784 of file pbx.c.

References ast_strdup.

4785 {
4786  if (overrideswitch) {
4787  ast_free(overrideswitch);
4788  }
4789  if (!ast_strlen_zero(newval)) {
4790  overrideswitch = ast_strdup(newval);
4791  } else {
4792  overrideswitch = NULL;
4793  }
4794 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
int raise_exception ( struct ast_channel chan,
const char *  reason,
int  priority 
)

pbx.c functions needed by pbx_builtins.c

Definition at line 2806 of file pbx.c.

References ast_calloc_with_stringfields, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_free(), ast_string_field_set, ast_datastore::data, pbx_exception::priority, and set_ext_pri().

Referenced by __ast_pbx_run().

2807 {
2808  struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
2809  struct pbx_exception *exception = NULL;
2810 
2811  if (!ds) {
2812  ds = ast_datastore_alloc(&exception_store_info, NULL);
2813  if (!ds)
2814  return -1;
2815  if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
2816  ast_datastore_free(ds);
2817  return -1;
2818  }
2819  ds->data = exception;
2820  ast_channel_datastore_add(chan, ds);
2821  } else
2822  exception = ds->data;
2823 
2824  ast_string_field_set(exception, reason, reason);
2825  ast_string_field_set(exception, context, ast_channel_context(chan));
2826  ast_string_field_set(exception, exten, ast_channel_exten(chan));
2827  exception->priority = ast_channel_priority(chan);
2828  set_ext_pri(chan, "e", priority);
2829  return 0;
2830 }
const ast_string_field exten
Definition: pbx.c:630
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:432
Structure for a data store object.
Definition: datastore.h:64
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
const ast_string_field reason
Definition: pbx.c:630
int priority
Definition: pbx.c:632
void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
Definition: pbx.c:4264
void * data
Definition: datastore.h:66
const ast_string_field context
Definition: pbx.c:630
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2385
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
void set_ext_pri ( struct ast_channel c,
const char *  exten,
int  pri 
)

helper function to set extension and priority

Definition at line 4264 of file pbx.c.

Referenced by __ast_pbx_run(), and raise_exception().

4265 {
4266  ast_channel_lock(c);
4267  ast_channel_exten_set(c, exten);
4268  ast_channel_priority_set(c, pri);
4269  ast_channel_unlock(c);
4270 }
const ast_string_field exten
Definition: pbx.c:630
void unreference_cached_app ( struct ast_app app)

pbx.c function needed by pbx_app.c

Definition at line 6130 of file pbx.c.

References ast_rdlock_contexts(), and ast_unlock_contexts().

Referenced by ast_unregister_application().

6131 {
6132  struct ast_context *context = NULL;
6133  struct ast_exten *eroot = NULL, *e = NULL;
6134 
6136  while ((context = ast_walk_contexts(context))) {
6137  while ((eroot = ast_walk_context_extensions(context, eroot))) {
6138  while ((e = ast_walk_extension_priorities(eroot, e))) {
6139  if (e->cached_app == app)
6140  e->cached_app = NULL;
6141  }
6142  }
6143  }
6145 
6146  return;
6147 }
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition: pbx.c:237
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8468
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
ast_context: An extension context
Definition: pbx.c:284

Variable Documentation

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

Lock for the ast_context list.

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

Definition at line 790 of file pbx.c.

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

struct ast_custom_function exception_function
static
Initial value:
= {
.name = "EXCEPTION",
.read = acf_exception_read,
}

Definition at line 2852 of file pbx.c.

const struct ast_datastore_info exception_store_info
static
Initial value:
= {
.type = "EXCEPTION",
.destroy = exception_store_free,
}

Definition at line 2790 of file pbx.c.

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

Definition at line 806 of file pbx.c.

Referenced by lua_register_hints().

struct ast_custom_function testtime_function
static
Initial value:
= {
.name = "TESTTIME",
.write = testtime_write,
}

Definition at line 8277 of file pbx.c.