Asterisk - The Open Source Telephony Project GIT-master-6144b6b
Loading...
Searching...
No Matches
Data Structures | Macros | Enumerations | 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/say.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/hashtab.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/xmldoc.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/dial.h"
#include "asterisk/vector.h"
#include "asterisk/extension_state.h"
#include "pbx_private.h"
Include dependency graph for pbx.c:

Go to the source code of this file.

Data Structures

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

Macros

#define ADVANCE(s)   candidate_exten_advance(s)
 
#define BITS_PER   8 /* Number of bits per unit (byte). */
 
#define EXT_DATA_SIZE   8192
 
#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
 

Enumerations

enum  ast_context_scope { AST_CONTEXT_SCOPE_LOCAL = 0 , AST_CONTEXT_SCOPE_GLOBAL }
 

Functions

void __ast_context_destroy (struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
 
static int __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
 
static void __ast_internal_context_destroy (struct ast_context *con)
 
static enum ast_pbx_result __ast_pbx_run (struct ast_channel *c, struct ast_pbx_args *args)
 
static int _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
 
static int acf_exception_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
 
static struct match_charadd_exten_to_pattern_tree (struct ast_context *con, struct ast_exten *e1, int findonly)
 
static struct match_charadd_pattern_node (struct ast_context *con, struct match_char *current, const struct pattern_node *pattern, int is_pattern, int already, struct match_char **nextcharptr)
 
static int add_priority (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace)
 add the extension in the priority chain.
 
static struct match_charalready_in_tree (struct match_char *current, char *pat, int is_pattern)
 
int ast_active_calls (void)
 Retrieve the number of active calls.
 
int ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add and extension to an extension context.
 
int ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, const char *registrar_file, int registrar_line)
 Main interface to add extensions to the list for out context.
 
static int ast_add_extension2_lockopt (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, const char *registrar_file, int registrar_line, int lock_context)
 Same as ast_add_extension2() but controls the context locking.
 
int ast_add_extension2_nolock (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, const char *registrar_file, int registrar_line)
 Same as ast_add_extension2, but assumes you have already locked context.
 
static int ast_add_hint (struct ast_exten *e)
 
int ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location.
 
int ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location.
 
int ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
 
int ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string)
 
int ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks for a valid matching extension.
 
static int ast_change_hint (struct ast_exten *oe, struct ast_exten *ne)
 Change hint for an extension.
 
int ast_context_add_ignorepat (const char *context, const char *value, const char *registrar)
 Add an ignorepat.
 
int ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar)
 
int ast_context_add_include (const char *context, const char *include, const char *registrar)
 Add a context include.
 
int ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar)
 Add a context include.
 
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
 Add a switch.
 
int ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
 Adds a switch (first param is a ast_context)
 
void ast_context_destroy (struct ast_context *con, const char *registrar)
 Destroy a context (matches the specified context or ANY context if NULL)
 
int ast_context_destroy_by_name (const char *context, const char *registrar)
 Destroy a context by name.
 
struct ast_contextast_context_find (const char *name)
 Find a context.
 
struct ast_contextast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
 Register a new context or find an existing one.
 
int ast_context_ignorepats_count (const struct ast_context *con)
 
const struct ast_ignorepatast_context_ignorepats_get (const struct ast_context *con, int idx)
 
int ast_context_includes_count (const struct ast_context *con)
 
const struct ast_includeast_context_includes_get (const struct ast_context *con, int idx)
 
int ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar)
 Simply remove extension from context.
 
int ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
 This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
 
int ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar)
 
int ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked)
 
int ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar)
 Remove an ignorepat.
 
int ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
 
int ast_context_remove_include (const char *context, const char *include, const char *registrar)
 Remove included contexts. This function locks contexts list by &conlist, search for the right context structure, leave context list locked and call ast_context_remove_include2 which removes include, unlock contexts list and return ...
 
int ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar)
 Locks context, remove included contexts, unlocks context. When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault.
 
int ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar)
 Remove a switch.
 
int ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar)
 This function locks given context, removes switch, unlock context and return.
 
void ast_context_set_autohints (struct ast_context *con, int enabled)
 Enable or disable autohints support on a context.
 
int ast_context_switches_count (const struct ast_context *con)
 
const struct ast_swast_context_switches_get (const struct ast_context *con, int idx)
 
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure.
 
int ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Determine whether an extension exists.
 
int ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
 
int ast_extension_close (const char *pattern, const char *data, int needmore)
 
int ast_extension_cmp (const char *a, const char *b)
 Determine if one extension should match before another.
 
int ast_extension_match (const char *pattern, const char *extension)
 Determine if a given extension matches a given pattern (in NXX format)
 
int ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
 
int ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label.
 
const char * ast_get_context_name (struct ast_context *con)
 
const char * ast_get_context_registrar (struct ast_context *c)
 
const char * ast_get_extension_app (struct ast_exten *e)
 
void * ast_get_extension_app_data (struct ast_exten *e)
 
const char * ast_get_extension_cidmatch (struct ast_exten *e)
 
struct ast_contextast_get_extension_context (struct ast_exten *exten)
 
int ast_get_extension_data (char *buf, int bufsize, struct ast_channel *c, const char *context, const char *exten, int priority)
 Fill a string buffer with the data at a dialplan extension.
 
const char * ast_get_extension_label (struct ast_exten *exten)
 
int ast_get_extension_matchcid (struct ast_exten *e)
 
const char * ast_get_extension_name (struct ast_exten *exten)
 
int ast_get_extension_priority (struct ast_exten *exten)
 
const char * ast_get_extension_registrar (struct ast_exten *e)
 
const char * ast_get_extension_registrar_file (struct ast_exten *e)
 Get name of configuration file used by registrar to register this extension.
 
int ast_get_extension_registrar_line (struct ast_exten *e)
 Get line number of configuration file used by registrar to register this extension.
 
int ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
 Get hint for channel.
 
int ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
 
int ast_hashtab_compare_contexts (const void *ah_a, const void *ah_b)
 hashtable functions for contexts
 
unsigned int ast_hashtab_hash_contexts (const void *obj)
 
static struct ast_extenast_hint_extension (struct ast_channel *c, const char *context, const char *exten)
 
static struct ast_extenast_hint_extension_nolock (struct ast_channel *c, const char *context, const char *exten)
 Find hint for given extension in context.
 
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored.
 
int ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch)
 
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
 
int ast_parseable_goto (struct ast_channel *chan, const char *goto_string)
 
void ast_pbx_h_exten_run (struct ast_channel *chan, const char *context)
 Run the h exten from the given context.
 
int ast_pbx_init (void)
 
int ast_pbx_outgoing_app (const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, const struct ast_assigned_ids *assignedids)
 Synchronously or asynchronously make an outbound call and execute an application on the channel.
 
int ast_pbx_outgoing_app_predial (const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, const struct ast_assigned_ids *assignedids, const char *predial_callee)
 
int ast_pbx_outgoing_exten (const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids)
 Synchronously or asynchronously make an outbound call and send it to a particular extension.
 
int ast_pbx_outgoing_exten_predial (const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids, const char *predial_callee)
 
enum ast_pbx_result ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.
 
enum ast_pbx_result ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args)
 Execute the PBX in the current thread.
 
enum ast_pbx_result ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX.
 
int ast_processed_calls (void)
 Retrieve the total number of calls processed through the PBX since last restart.
 
int ast_rdlock_context (struct ast_context *con)
 Read locks a given context.
 
int ast_rdlock_contexts (void)
 Read locks the context list.
 
static int ast_remove_hint (struct ast_exten *e)
 
int ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
 Launch a new extension (i.e. new stack)
 
int ast_str_get_hint (struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten)
 Get hint for channel.
 
 AST_THREADSTORAGE_CUSTOM_SCOPE (switch_data, NULL, ast_free_ptr, static)
 
int ast_unlock_context (struct ast_context *con)
 
int ast_unlock_contexts (void)
 Unlocks contexts.
 
struct ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
 
const struct ast_ignorepatast_walk_context_ignorepats (const struct ast_context *con, const struct ast_ignorepat *ip)
 
const struct ast_includeast_walk_context_includes (const struct ast_context *con, const struct ast_include *inc)
 
const struct ast_swast_walk_context_switches (const struct ast_context *con, const struct ast_sw *sw)
 
struct ast_contextast_walk_contexts (struct ast_context *con)
 
struct ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
 
int ast_wrlock_context (struct ast_context *con)
 Write locks a given context.
 
int ast_wrlock_contexts (void)
 Write locks the context list.
 
static const char * candidate_exten_advance (const char *str)
 
static void cli_match_char_tree (struct match_char *node, char *prefix, int fd)
 
static int collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
 collect digits from the channel into the buffer.
 
static int compare_char (const void *a, const void *b)
 
static char * complete_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 int context_promote (struct ast_context *context)
 
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_pattern_tree (struct match_char *pattern_tree)
 
static void exception_store_free (void *data)
 
static int ext_cmp (const char *left, const char *right)
 
static int ext_cmp_exten (const char *left, const char *right)
 
static int ext_cmp_exten_partial (const char *left, const char *right)
 
static int ext_cmp_exten_strlen (const char *str)
 
static int ext_cmp_pattern (const char *left, const char *right)
 
static int ext_cmp_pattern_pos (const char **p, unsigned char *bitwise)
 helper functions to sort extension patterns in the desired way, so that more specific patterns appear first.
 
static int ext_fluff_count (const char *exten)
 
static unsigned int ext_strncpy (char *dst, const char *src, size_t dst_size, int nofluff)
 
static int extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
 
static struct ast_contextfind_context (const char *context)
 lookup for a context with a given name,
 
static struct ast_contextfind_context_locked (const char *context)
 lookup for a context with a given name,
 
static struct ast_extenget_canmatch_exten (struct match_char *node)
 
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 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_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 increase_call_count (const struct ast_channel *c)
 Increase call count for channel.
 
static void insert_in_next_chars_alt_char_list (struct match_char **parent_ptr, struct match_char *node)
 
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)
 
int pbx_checkcondition (const char *condition)
 Evaluate a condition.
 
static void pbx_destroy (struct ast_pbx *p)
 
static enum ast_control_frame_type pbx_dial_reason (enum ast_dial_result dial_result, int cause)
 Attempt to convert disconnect cause to old originate reason.
 
static int pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
 The return value depends on the action:
 
struct ast_extenpbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
 
static int pbx_outgoing_attempt (const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids, const char *predial_callee)
 
static void pbx_outgoing_destroy (void *obj)
 Destructor for outgoing structure.
 
static void * pbx_outgoing_exec (void *data)
 Internal function which dials an outgoing leg and sends it to a provided extension or application.
 
static void pbx_outgoing_state_callback (struct ast_dial *dial)
 Internal dialing state callback which causes early media to trigger an answer.
 
int pbx_parse_location (struct ast_channel *chan, char **contextp, char **extenp, char **prip, int *ipri, int *mode, char *rest)
 Parses a dialplan location into context, extension, priority.
 
static int pbx_parseable_goto (struct ast_channel *chan, const char *goto_string, int async)
 
int pbx_set_autofallthrough (int newval)
 
int pbx_set_extenpatternmatchnew (int newval)
 
void pbx_set_overrideswitch (const char *newval)
 
static void pbx_shutdown (void)
 
static void * pbx_thread (void *data)
 
static void print_ext (struct ast_exten *e, char *buf, int buflen)
 helper function to print an extension
 
int raise_exception (struct ast_channel *chan, const char *reason, int priority)
 
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.
 
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 ast_mutex_t conlock = AST_MUTEX_INIT_VALUE
 Lock for the ast_context list.
 
static struct ast_contextcontexts
 
static struct ast_hashtabcontexts_table = NULL
 
static int countcalls
 
static struct ast_custom_function exception_function
 
static const struct ast_datastore_info exception_store_info
 
static int extenpatternmatchnew = 0
 
static ast_mutex_t maxcalllock = AST_MUTEX_INIT_VALUE
 
static char * overrideswitch = NULL
 
static struct ast_cli_entry pbx_cli []
 
static struct ast_custom_function testtime_function
 
static int totalcalls
 

Detailed Description

Core PBX routines.

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

Definition in file pbx.c.

Macro Definition Documentation

◆ ADVANCE

#define ADVANCE (   s)    candidate_exten_advance(s)

Definition at line 860 of file pbx.c.

◆ BITS_PER

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

◆ EXT_DATA_SIZE

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

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

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

Definition at line 182 of file pbx.c.

◆ INC_DST_OVERFLOW_CHECK

#define INC_DST_OVERFLOW_CHECK

◆ MAX_EXTENBUF_SIZE

#define MAX_EXTENBUF_SIZE   512

Definition at line 1288 of file pbx.c.

◆ MORE

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

Definition at line 859 of file pbx.c.

◆ NEW_MATCHER_CHK_MATCH

#define NEW_MATCHER_CHK_MATCH

◆ NEW_MATCHER_RECURSE

#define NEW_MATCHER_RECURSE

◆ SAY_STUBS

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

Definition at line 56 of file pbx.c.

◆ STATUS_NO_CONTEXT

#define STATUS_NO_CONTEXT   1

Definition at line 2090 of file pbx.c.

◆ STATUS_NO_EXTENSION

#define STATUS_NO_EXTENSION   2

Definition at line 2091 of file pbx.c.

◆ STATUS_NO_LABEL

#define STATUS_NO_LABEL   4

Definition at line 2093 of file pbx.c.

◆ STATUS_NO_PRIORITY

#define STATUS_NO_PRIORITY   3

Definition at line 2092 of file pbx.c.

◆ STATUS_SUCCESS

#define STATUS_SUCCESS   5

Definition at line 2094 of file pbx.c.

◆ SWITCH_DATA_LENGTH

#define SWITCH_DATA_LENGTH   256

Definition at line 185 of file pbx.c.

◆ VAR_HARDTRAN

#define VAR_HARDTRAN   3

Definition at line 189 of file pbx.c.

◆ VAR_NORMAL

#define VAR_NORMAL   1

Definition at line 187 of file pbx.c.

◆ VAR_SOFTTRAN

#define VAR_SOFTTRAN   2

Definition at line 188 of file pbx.c.

Enumeration Type Documentation

◆ ast_context_scope

Enumerator
AST_CONTEXT_SCOPE_LOCAL 

Context is only locally accessible

AST_CONTEXT_SCOPE_GLOBAL 

Context is globally accessible

Definition at line 196 of file pbx.c.

196 {
197 AST_CONTEXT_SCOPE_LOCAL = 0, /*!< Context is only locally accessible */
198 AST_CONTEXT_SCOPE_GLOBAL, /*!< Context is globally accessible */
199};
@ AST_CONTEXT_SCOPE_GLOBAL
Definition pbx.c:198
@ AST_CONTEXT_SCOPE_LOCAL
Definition pbx.c:197

Function Documentation

◆ __ast_context_destroy()

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

Definition at line 6342 of file pbx.c.

6343{
6344 struct ast_context *tmp, *tmpl=NULL;
6345 struct ast_exten *exten_item, *prio_item;
6346
6347 for (tmp = list; tmp; ) {
6348 struct ast_context *next = NULL; /* next starting point */
6349 /* The following code used to skip forward to the next
6350 context with matching registrar, but this didn't
6351 make sense; individual priorities registrar'd to
6352 the matching registrar could occur in any context! */
6353 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
6354 if (con) {
6355 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
6356 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
6357 if ( !strcasecmp(tmp->name, con->name) ) {
6358 break; /* found it */
6359 }
6360 }
6361 }
6362
6363 if (!tmp) /* not found, we are done */
6364 break;
6365 ast_wrlock_context(tmp);
6366
6367 if (registrar) {
6368 /* then search thru and remove any extens that match registrar. */
6369 struct ast_hashtab_iter *exten_iter;
6370 struct ast_hashtab_iter *prio_iter;
6371 int idx;
6372
6373 /* remove any ignorepats whose registrar matches */
6374 for (idx = ast_context_ignorepats_count(tmp) - 1; idx >= 0; idx--) {
6375 struct ast_ignorepat *ip = AST_VECTOR_GET(&tmp->ignorepats, idx);
6376
6377 if (!strcmp(ast_get_ignorepat_registrar(ip), registrar)) {
6378 AST_VECTOR_REMOVE_ORDERED(&tmp->ignorepats, idx);
6379 ignorepat_free(ip);
6380 }
6381 }
6382 /* remove any includes whose registrar matches */
6383 for (idx = ast_context_includes_count(tmp) - 1; idx >= 0; idx--) {
6384 struct ast_include *i = AST_VECTOR_GET(&tmp->includes, idx);
6385
6386 if (!strcmp(ast_get_include_registrar(i), registrar)) {
6387 AST_VECTOR_REMOVE_ORDERED(&tmp->includes, idx);
6388 include_free(i);
6389 }
6390 }
6391 /* remove any switches whose registrar matches */
6392 for (idx = ast_context_switches_count(tmp) - 1; idx >= 0; idx--) {
6393 struct ast_sw *sw = AST_VECTOR_GET(&tmp->alts, idx);
6394
6395 if (!strcmp(ast_get_switch_registrar(sw), registrar)) {
6396 AST_VECTOR_REMOVE_ORDERED(&tmp->alts, idx);
6397 sw_free(sw);
6398 }
6399 }
6400
6401 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
6402 exten_iter = ast_hashtab_start_traversal(tmp->root_table);
6403 while ((exten_item=ast_hashtab_next(exten_iter))) {
6404 int end_traversal = 1;
6405
6406 /*
6407 * If the extension could not be removed from the root_table due to
6408 * a loaded PBX app, it can exist here but have its peer_table be
6409 * destroyed due to a previous pass through this function.
6410 */
6411 if (!exten_item->peer_table) {
6412 continue;
6413 }
6414
6415 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
6416 while ((prio_item=ast_hashtab_next(prio_iter))) {
6418 char cidmatch[AST_MAX_EXTENSION];
6419 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
6420 continue;
6421 }
6422 ast_verb(5, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
6423 tmp->name, prio_item->name, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
6424 ast_copy_string(extension, prio_item->exten, sizeof(extension));
6425 if (prio_item->cidmatch) {
6426 ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch));
6427 }
6428 end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, cidmatch, prio_item->matchcid, NULL, 1);
6429 }
6430 /* Explanation:
6431 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This
6432 * destruction includes destroying the exten's peer_table, which we are currently traversing. If
6433 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed
6434 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result
6435 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply
6436 * free the iterator
6437 */
6438 if (end_traversal) {
6439 ast_hashtab_end_traversal(prio_iter);
6440 } else {
6441 ast_free(prio_iter);
6442 }
6443 }
6444 ast_hashtab_end_traversal(exten_iter);
6445 }
6446
6447 /* delete the context if it's registrar matches, is empty, has refcount of 1, */
6448 /* it's not empty, if it has includes, ignorepats, or switches that are registered from
6449 another registrar. It's not empty if there are any extensions */
6450 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !ast_context_ignorepats_count(tmp) && !ast_context_includes_count(tmp) && !ast_context_switches_count(tmp)) {
6451 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
6452 ast_hashtab_remove_this_object(contexttab, tmp);
6453
6454 next = tmp->next;
6455 if (tmpl)
6456 tmpl->next = next;
6457 else
6458 contexts = next;
6459 /* Okay, now we're safe to let it go -- in a sense, we were
6460 ready to let it go as soon as we locked it. */
6461 ast_unlock_context(tmp);
6463 } else {
6464 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
6465 tmp->refcount, tmp->root);
6466 ast_unlock_context(tmp);
6467 next = tmp->next;
6468 tmpl = tmp;
6469 }
6470 } else if (con) {
6471 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
6472 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
6473 ast_hashtab_remove_this_object(contexttab, tmp);
6474
6475 next = tmp->next;
6476 if (tmpl)
6477 tmpl->next = next;
6478 else
6479 contexts = next;
6480 /* Okay, now we're safe to let it go -- in a sense, we were
6481 ready to let it go as soon as we locked it. */
6482 ast_unlock_context(tmp);
6484 }
6485
6486 /* if we have a specific match, we are done, otherwise continue */
6487 tmp = con ? NULL : next;
6488 }
6489}
#define ast_free(a)
Definition astmm.h:180
#define AST_MAX_EXTENSION
Definition channel.h:134
static const char registrar[]
The static registrar for the added dialplan hints.
#define ast_hashtab_start_traversal(tab)
Definition hashtab.h:356
void * ast_hashtab_remove_this_object(struct ast_hashtab *tab, void *obj)
Hash the object and then compare ptrs in bucket list instead of calling the compare routine,...
Definition hashtab.c:789
void ast_hashtab_end_traversal(struct ast_hashtab_iter *it)
end the traversal, free the iterator, unlock if necc.
Definition hashtab.c:674
void * ast_hashtab_next(struct ast_hashtab_iter *it)
Gets the next object in the list, advances iter one step returns null on end of traversal.
Definition hashtab.c:683
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition pbx.c:6639
int ast_unlock_context(struct ast_context *con)
Definition pbx.c:6649
int ast_context_remove_extension_callerid2(struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked)
Definition pbx.c:3543
int ast_context_ignorepats_count(const struct ast_context *con)
Definition pbx.c:6880
static struct ast_context * contexts
Definition pbx.c:425
int ast_context_switches_count(const struct ast_context *con)
Definition pbx.c:6792
int ast_context_includes_count(const struct ast_context *con)
Definition pbx.c:6837
static void __ast_internal_context_destroy(struct ast_context *con)
Definition pbx.c:6297
const char * ast_get_ignorepat_registrar(const struct ast_ignorepat *ip)
const char * ast_get_include_registrar(const struct ast_include *i)
Definition pbx_include.c:60
const char * ast_get_switch_registrar(const struct ast_sw *sw)
Definition pbx_sw.c:63
void ignorepat_free(struct ast_ignorepat *ip)
void include_free(struct ast_include *inc)
void sw_free(struct ast_sw *sw)
Definition pbx_sw.c:101
#define NULL
Definition resample.c:96
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
ast_context: An extension context
Definition pbx.c:254
const char * registrar
Definition pbx.c:256
struct ast_context * next
Definition pbx.c:262
const char * name
Definition pbx.c:255
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition pbx.c:207
char * exten
Definition pbx.c:208
struct ast_hashtab * peer_table
Definition pbx.c:221
char * name
Definition pbx.c:209
const char * registrar
Definition pbx.c:223
const char * cidmatch
Definition pbx.c:211
int priority
Definition pbx.c:213
int matchcid
Definition pbx.c:210
an iterator for traversing the buckets
Definition hashtab.h:106
ast_ignorepat: Ignore patterns in dial plan
ast_include: include= support in extensions.conf
Definition pbx_include.c:37
ast_sw: Switch statement in extensions.conf
Definition pbx_sw.c:37
struct ast_sw * next
Definition pbx_sw.c:44
structure to hold extensions
#define AST_VECTOR_REMOVE_ORDERED(vec, idx)
Remove an element from a vector by index while maintaining order.
Definition vector.h:459
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition vector.h:691

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

Referenced by ast_context_destroy().

◆ __ast_goto_if_exists()

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

Definition at line 6918 of file pbx.c.

6919{
6920 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
6921
6922 if (!chan)
6923 return -2;
6924
6925 if (context == NULL)
6927 if (exten == NULL)
6928 exten = ast_channel_exten(chan);
6929
6930 goto_func = (async) ? ast_async_goto : ast_explicit_goto;
6932 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)))
6933 return goto_func(chan, context, exten, priority);
6934 else {
6935 return AST_PBX_GOTO_FAILED;
6936 }
6937}
static int priority
const char * ast_channel_context(const struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
const char * ast_channel_exten(const struct ast_channel *chan)
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition pbx.c:2735
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition pbx.c:5223
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition pbx.c:5251
#define AST_PBX_GOTO_FAILED
Definition pbx.h:42
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition strings.h:87
Main Channel structure associated with a channel.
char exten[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
Number structure.

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

Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().

◆ __ast_internal_context_destroy()

static void __ast_internal_context_destroy ( struct ast_context con)
static

Definition at line 6297 of file pbx.c.

6298{
6299 struct ast_exten *e, *el, *en;
6300 struct ast_context *tmp = con;
6301
6302 if (con->scope == AST_CONTEXT_SCOPE_GLOBAL && con->autohints) {
6304 }
6305
6306 /* Free includes */
6309
6310 /* Free ignorepats */
6313
6314 /* Free switches */
6316 AST_VECTOR_FREE(&tmp->alts);
6317
6318 /* destroy the hash tabs */
6319 if (tmp->root_table) {
6321 }
6322 /* and destroy the pattern tree */
6323 if (tmp->pattern_tree)
6325
6326 for (e = tmp->root; e;) {
6327 for (en = e->peer; en;) {
6328 el = en;
6329 en = en->peer;
6331 }
6332 el = e;
6333 e = e->next;
6335 }
6336 tmp->root = NULL;
6337 ast_rwlock_destroy(&tmp->lock);
6338 ast_free(tmp);
6339}
static EditLine * el
Definition asterisk.c:348
void pbx_extension_state_autohint_remove(struct ast_context *context, unsigned int forced)
void ast_hashtab_destroy(struct ast_hashtab *tab, void(*objdestroyfunc)(void *obj))
This func will free the hash table and all its memory.
Definition hashtab.c:363
#define ast_rwlock_destroy(rwlock)
Definition lock.h:240
static void destroy_pattern_tree(struct match_char *pattern_tree)
Definition pbx.c:1419
static void destroy_exten(struct ast_exten *e)
Definition pbx.c:3234
struct ast_sws alts
Definition pbx.c:265
struct ast_exten * root
Definition pbx.c:259
enum ast_context_scope scope
Definition pbx.c:266
struct match_char * pattern_tree
Definition pbx.c:261
struct ast_ignorepats ignorepats
Definition pbx.c:264
struct ast_includes includes
Definition pbx.c:263
int autohints
Definition pbx.c:268
struct ast_hashtab * root_table
Definition pbx.c:260
ast_rwlock_t lock
Definition pbx.c:258
struct ast_exten * peer
Definition pbx.c:220
struct ast_exten * next
Definition pbx.c:226
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition vector.h:185
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition vector.h:873

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

Referenced by __ast_context_destroy(), and ast_merge_contexts_and_delete().

◆ __ast_pbx_run()

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

Definition at line 2866 of file pbx.c.

2868{
2869 int found = 0; /* set if we find at least one match */
2870 int res = 0;
2871 int autoloopflag;
2872 int error = 0; /* set an error conditions */
2873 struct ast_pbx *pbx;
2874 ast_callid callid;
2875
2876 /* A little initial setup here */
2877 if (ast_channel_pbx(c)) {
2878 ast_log(LOG_WARNING, "%s already has PBX structure??\n", ast_channel_name(c));
2879 /* XXX and now what ? */
2881 }
2882 if (!(pbx = ast_calloc(1, sizeof(*pbx)))) {
2883 return AST_PBX_FAILED;
2884 }
2885
2887 /* If the thread isn't already associated with a callid, we should create that association. */
2888 if (!callid) {
2889 /* Associate new PBX thread with the channel call id if it is available.
2890 * If not, create a new one instead.
2891 */
2892 callid = ast_channel_callid(c);
2893 if (!callid) {
2894 callid = ast_create_callid();
2895 if (callid) {
2897 ast_channel_callid_set(c, callid);
2899 }
2900 }
2902 callid = 0;
2903 }
2904
2905 ast_channel_pbx_set(c, pbx);
2906 /* Set reasonable defaults */
2907 ast_channel_pbx(c)->rtimeoutms = 10000;
2908 ast_channel_pbx(c)->dtimeoutms = 5000;
2909
2911 autoloopflag = ast_test_flag(ast_channel_flags(c), AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */
2914
2916 /* If not successful fall back to 's' - but only if there is no given exten */
2917 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));
2918 /* XXX the original code used the existing priority in the call to
2919 * ast_exists_extension(), and reset it to 1 afterwards.
2920 * I believe the correct thing is to set it to 1 immediately.
2921 */
2922 set_ext_pri(c, "s", 1);
2923 }
2924
2925 for (;;) {
2926 char dst_exten[256]; /* buffer to accumulate digits */
2927 int pos = 0; /* XXX should check bounds */
2928 int digit = 0;
2929 int invalid = 0;
2930 int timeout = 0;
2931
2932 /* No digits pressed yet */
2933 dst_exten[pos] = '\0';
2934
2935 /* loop on priorities in this context/exten */
2938 &found, 1))) {
2939
2940 if (!ast_check_hangup(c)) {
2942 continue;
2943 }
2944
2945 /* Check softhangup flags. */
2948 continue;
2949 }
2952 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
2953 set_ext_pri(c, "T", 1);
2954 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
2957 continue;
2958 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
2959 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
2960 raise_exception(c, "ABSOLUTETIMEOUT", 1);
2961 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
2964 continue;
2965 }
2966
2967 /* Call timed out with no special extension to jump to. */
2968 error = 1;
2969 break;
2970 }
2971 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
2973 error = 1;
2974 break;
2975 } /* end while - from here on we can use 'break' to go out */
2976 if (found && res) {
2977 /* Something bad happened, or a hangup has been requested. */
2978 if (strchr("0123456789ABCDEF*#", res)) {
2979 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
2980 pos = 0;
2981 dst_exten[pos++] = digit = res;
2982 dst_exten[pos] = '\0';
2983 } else if (res == AST_PBX_INCOMPLETE) {
2984 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));
2985 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));
2986
2987 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
2989 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
2990 invalid = 1;
2991 } else {
2992 ast_copy_string(dst_exten, ast_channel_exten(c), sizeof(dst_exten));
2993 digit = 1;
2994 pos = strlen(dst_exten);
2995 }
2996 } else {
2997 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));
2998 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));
2999
3000 if ((res == AST_PBX_ERROR)
3002 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
3003 /* if we are already on the 'e' exten, don't jump to it again */
3004 if (!strcmp(ast_channel_exten(c), "e")) {
3005 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));
3006 error = 1;
3007 } else {
3008 raise_exception(c, "ERROR", 1);
3009 continue;
3010 }
3011 }
3012
3015 continue;
3016 }
3019 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
3020 set_ext_pri(c, "T", 1);
3021 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
3024 continue;
3025 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
3026 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
3027 raise_exception(c, "ABSOLUTETIMEOUT", 1);
3028 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
3031 continue;
3032 }
3033 /* Call timed out with no special extension to jump to. */
3034 }
3035 error = 1;
3036 break;
3037 }
3038 }
3039 if (error)
3040 break;
3041
3042 /*!\note
3043 * We get here on a failure of some kind: non-existing extension or
3044 * hangup. We have options, here. We can either catch the failure
3045 * and continue, or we can drop out entirely. */
3046
3047 if (invalid
3048 || (ast_strlen_zero(dst_exten) &&
3050 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL)))) {
3051 /*!\note
3052 * If there is no match at priority 1, it is not a valid extension anymore.
3053 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
3054 * neither exist.
3055 */
3057 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
3058 ast_verb(3, "Channel '%s' sent to invalid extension: context,exten,priority=%s,%s,%d\n",
3060 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", ast_channel_exten(c));
3061 set_ext_pri(c, "i", 1);
3062 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
3063 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
3064 raise_exception(c, "INVALID", 1);
3065 } else {
3066 ast_log(LOG_WARNING, "Channel '%s' sent to invalid extension but no invalid handler: context,exten,priority=%s,%s,%d\n",
3068 error = 1; /* we know what to do with it */
3069 break;
3070 }
3072 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
3074 } else { /* keypress received, get more digits for a full extension */
3075 int waittime = 0;
3076 if (digit)
3077 waittime = ast_channel_pbx(c)->dtimeoutms;
3078 else if (!autofallthrough)
3079 waittime = ast_channel_pbx(c)->rtimeoutms;
3080 if (!waittime) {
3081 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
3082 if (!status)
3083 status = "UNKNOWN";
3084 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", ast_channel_name(c), status);
3085 if (!strcasecmp(status, "CONGESTION"))
3086 res = indicate_congestion(c, "10");
3087 else if (!strcasecmp(status, "CHANUNAVAIL"))
3088 res = indicate_congestion(c, "10");
3089 else if (!strcasecmp(status, "BUSY"))
3090 res = indicate_busy(c, "10");
3091 error = 1; /* XXX disable message */
3092 break; /* exit from the 'for' loop */
3093 }
3094
3095 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
3096 break;
3097 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
3098 timeout = 1;
3099 if (!timeout
3100 && ast_exists_extension(c, ast_channel_context(c), dst_exten, 1,
3101 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) { /* Prepare the next cycle */
3102 set_ext_pri(c, dst_exten, 1);
3103 } else {
3104 /* No such extension */
3105 if (!timeout && !ast_strlen_zero(dst_exten)) {
3106 /* An invalid extension */
3108 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
3109 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, ast_channel_context(c), ast_channel_name(c));
3110 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
3111 set_ext_pri(c, "i", 1);
3112 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
3113 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
3114 raise_exception(c, "INVALID", 1);
3115 } else {
3117 "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
3118 dst_exten, ast_channel_context(c));
3119 found = 1; /* XXX disable message */
3120 break;
3121 }
3122 } else {
3123 /* A simple timeout */
3125 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
3126 ast_verb(3, "Timeout on %s\n", ast_channel_name(c));
3127 set_ext_pri(c, "t", 1);
3128 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
3129 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
3130 raise_exception(c, "RESPONSETIMEOUT", 1);
3131 } else {
3133 "Timeout, but no rule 't' or 'e' in context '%s'\n",
3135 found = 1; /* XXX disable message */
3136 break;
3137 }
3138 }
3139 }
3140 }
3141 }
3142
3143 if (!found && !error) {
3144 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", ast_channel_name(c));
3145 }
3146
3147 if (!args || !args->no_hangup_chan) {
3151 S_COR(ast_channel_caller(c)->id.number.valid,
3152 ast_channel_caller(c)->id.number.str, NULL))) {
3154 }
3156 }
3157
3160 ast_clear_flag(ast_channel_flags(c), AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
3164
3165 if (!args || !args->no_hangup_chan) {
3166 ast_hangup(c);
3167 }
3168
3169 return AST_PBX_SUCCESS;
3170}
char digit
jack_status_t status
Definition app_jack.c:149
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
#define ast_log
Definition astobj2.c:42
const char * ast_channel_name(const struct ast_channel *chan)
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition channel.c:2423
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition channel.c:2540
#define ast_channel_lock(chan)
Definition channel.h:2983
@ AST_FLAG_BRIDGE_HANGUP_RUN
Definition channel.h:1038
@ AST_FLAG_IN_AUTOLOOP
Definition channel.h:1017
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
int ast_channel_priority(const struct ast_channel *chan)
ast_callid ast_channel_callid(const struct ast_channel *chan)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition channel.c:446
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition channel.c:2462
struct timeval * ast_channel_whentohangup(struct ast_channel *chan)
@ AST_SOFTHANGUP_ASYNCGOTO
Definition channel.h:1146
@ AST_SOFTHANGUP_TIMEOUT
Definition channel.h:1158
@ AST_SOFTHANGUP_APPUNLOAD
Definition channel.h:1163
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
int ast_channel_softhangup_internal_flag(struct ast_channel *chan)
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
void ast_channel_priority_set(struct ast_channel *chan, int value)
#define ast_channel_unlock(chan)
Definition channel.h:2984
void ast_channel_pbx_set(struct ast_channel *chan, struct ast_pbx *value)
int indicate_busy(struct ast_channel *chan, const char *data)
int indicate_congestion(struct ast_channel *chan, const char *data)
ast_callid ast_read_threadstorage_callid(void)
extracts the callid from the thread
Definition logger.c:2268
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition logger.c:2290
ast_callid ast_create_callid(void)
factory function to create a new uniquely identifying callid.
Definition logger.c:2263
unsigned int ast_callid
#define LOG_WARNING
static void pbx_destroy(struct ast_pbx *p)
Definition pbx.c:616
static int autofallthrough
Definition pbx.c:417
int raise_exception(struct ast_channel *chan, const char *reason, int priority)
Definition pbx.c:2432
void ast_pbx_h_exten_run(struct ast_channel *chan, const char *context)
Run the h exten from the given context.
Definition pbx.c:2765
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:2760
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:2755
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:2839
void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
Definition pbx.c:2824
@ AST_PBX_FAILED
Definition pbx.h:374
@ AST_PBX_SUCCESS
Definition pbx.h:373
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define AST_PBX_INCOMPLETE
Definition pbx.h:51
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
#define AST_PBX_ERROR
Definition pbx.h:50
int ast_pbx_hangup_handler_run(struct ast_channel *chan)
Run all hangup handlers on the channel.
static struct @522 args
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
Definition pbx.h:216
int rtimeoutms
Definition pbx.h:218
int dtimeoutms
Definition pbx.h:217
static struct test_val c
int error(const char *format,...)
#define ast_test_flag(p, flag)
Definition utils.h:64
#define ast_set2_flag(p, value, flag)
Definition utils.h:95
#define ast_clear_flag(p, flag)
Definition utils.h:78
#define ast_set_flag(p, flag)
Definition utils.h:71

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

Referenced by ast_pbx_run_args(), and pbx_thread().

◆ _extension_match_core()

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

Definition at line 1849 of file pbx.c.

1850{
1851 mode &= E_MATCH_MASK; /* only consider the relevant bits */
1852
1853#ifdef NEED_DEBUG_HERE
1854 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode);
1855#endif
1856
1857 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
1858 int lp = ext_cmp_exten_strlen(pattern);
1859 int ld = ext_cmp_exten_strlen(data);
1860
1861 if (lp < ld) { /* pattern too short, cannot match */
1862#ifdef NEED_DEBUG_HERE
1863 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n");
1864#endif
1865 return 0;
1866 }
1867 /* depending on the mode, accept full or partial match or both */
1868 if (mode == E_MATCH) {
1869#ifdef NEED_DEBUG_HERE
1870 ast_log(LOG_NOTICE,"return (!ext_cmp_exten(%s,%s) when mode== E_MATCH)\n", pattern, data);
1871#endif
1872 return !ext_cmp_exten(pattern, data); /* 1 on match, 0 on fail */
1873 }
1874 if (ld == 0 || !ext_cmp_exten_partial(pattern, data)) { /* partial or full match */
1875#ifdef NEED_DEBUG_HERE
1876 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld);
1877#endif
1878 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
1879 } else {
1880#ifdef NEED_DEBUG_HERE
1881 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data);
1882#endif
1883 return 0;
1884 }
1885 }
1886 if (mode == E_MATCH && data[0] == '_') {
1887 /*
1888 * XXX It is bad design that we don't know if we should be
1889 * comparing data and pattern as patterns or comparing data if
1890 * it conforms to pattern when the function is called. First,
1891 * assume they are both patterns. If they don't match then try
1892 * to see if data conforms to the given pattern.
1893 *
1894 * note: if this test is left out, then _x. will not match _x. !!!
1895 */
1896#ifdef NEED_DEBUG_HERE
1897 ast_log(LOG_NOTICE, "Comparing as patterns first. pattern:%s data:%s\n", pattern, data);
1898#endif
1899 if (!ext_cmp_pattern(pattern + 1, data + 1)) {
1900#ifdef NEED_DEBUG_HERE
1901 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n");
1902#endif
1903 return 1;
1904 }
1905 }
1906
1907 ++pattern; /* skip leading _ */
1908 /*
1909 * XXX below we stop at '/' which is a separator for the CID info. However we should
1910 * not store '/' in the pattern at all. When we insure it, we can remove the checks.
1911 */
1912 for (;;) {
1913 const char *end;
1914
1915 /* Ignore '-' chars as eye candy fluff. */
1916 while (*data == '-') {
1917 ++data;
1918 }
1919 while (*pattern == '-') {
1920 ++pattern;
1921 }
1922 if (!*data || !*pattern || *pattern == '/') {
1923 break;
1924 }
1925
1926 switch (*pattern) {
1927 case '[': /* a range */
1928 ++pattern;
1929 end = strchr(pattern, ']'); /* XXX should deal with escapes ? */
1930 if (!end) {
1931 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
1932 return 0; /* unconditional failure */
1933 }
1934 if (pattern == end) {
1935 /* Ignore empty character sets. */
1936 ++pattern;
1937 continue;
1938 }
1939 for (; pattern < end; ++pattern) {
1940 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
1941 if (*data >= pattern[0] && *data <= pattern[2])
1942 break; /* match found */
1943 else {
1944 pattern += 2; /* skip a total of 3 chars */
1945 continue;
1946 }
1947 } else if (*data == pattern[0])
1948 break; /* match found */
1949 }
1950 if (pattern >= end) {
1951#ifdef NEED_DEBUG_HERE
1952 ast_log(LOG_NOTICE,"return (0) when pattern>=end\n");
1953#endif
1954 return 0;
1955 }
1956 pattern = end; /* skip and continue */
1957 break;
1958 case 'n':
1959 case 'N':
1960 if (*data < '2' || *data > '9') {
1961#ifdef NEED_DEBUG_HERE
1962 ast_log(LOG_NOTICE,"return (0) N is not matched\n");
1963#endif
1964 return 0;
1965 }
1966 break;
1967 case 'x':
1968 case 'X':
1969 if (*data < '0' || *data > '9') {
1970#ifdef NEED_DEBUG_HERE
1971 ast_log(LOG_NOTICE,"return (0) X is not matched\n");
1972#endif
1973 return 0;
1974 }
1975 break;
1976 case 'z':
1977 case 'Z':
1978 if (*data < '1' || *data > '9') {
1979#ifdef NEED_DEBUG_HERE
1980 ast_log(LOG_NOTICE,"return (0) Z is not matched\n");
1981#endif
1982 return 0;
1983 }
1984 break;
1985 case '.': /* Must match, even with more digits */
1986#ifdef NEED_DEBUG_HERE
1987 ast_log(LOG_NOTICE, "return (1) when '.' is matched\n");
1988#endif
1989 return 1;
1990 case '!': /* Early match */
1991#ifdef NEED_DEBUG_HERE
1992 ast_log(LOG_NOTICE, "return (2) when '!' is matched\n");
1993#endif
1994 return 2;
1995 default:
1996 if (*data != *pattern) {
1997#ifdef NEED_DEBUG_HERE
1998 ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern);
1999#endif
2000 return 0;
2001 }
2002 break;
2003 }
2004 ++data;
2005 ++pattern;
2006 }
2007 if (*data) /* data longer than pattern, no match */ {
2008#ifdef NEED_DEBUG_HERE
2009 ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n");
2010#endif
2011 return 0;
2012 }
2013
2014 /*
2015 * match so far, but ran off the end of data.
2016 * Depending on what is next, determine match or not.
2017 */
2018 if (*pattern == '\0' || *pattern == '/') { /* exact match */
2019#ifdef NEED_DEBUG_HERE
2020 ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1);
2021#endif
2022 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */
2023 } else if (*pattern == '!') { /* early match */
2024#ifdef NEED_DEBUG_HERE
2025 ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n");
2026#endif
2027 return 2;
2028 } else { /* partial match */
2029#ifdef NEED_DEBUG_HERE
2030 ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1);
2031#endif
2032 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */
2033 }
2034}
char * end
Definition eagi_proxy.c:73
@ E_MATCH_MASK
Definition extconf.h:218
@ E_MATCH
Definition extconf.h:217
@ E_MATCHMORE
Definition extconf.h:215
#define LOG_NOTICE
static int ext_cmp_exten_strlen(const char *str)
Definition pbx.c:1443
static int ext_cmp_exten(const char *left, const char *right)
Definition pbx.c:1516
static int ext_cmp_pattern(const char *left, const char *right)
Definition pbx.c:1718
static int ext_cmp_exten_partial(const char *left, const char *right)
Definition pbx.c:1473

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

Referenced by extension_match_core().

◆ acf_exception_read()

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

Definition at line 2465 of file pbx.c.

2466{
2467 struct ast_datastore *ds;
2468 struct pbx_exception *exception;
2469 int res = 0;
2470
2471 ast_channel_lock(chan);
2473 if (!ds || !ds->data) {
2474 ast_channel_unlock(chan);
2475 return -1;
2476 }
2477 exception = ds->data;
2478 if (!strcasecmp(data, "REASON"))
2479 ast_copy_string(buf, exception->reason, buflen);
2480 else if (!strcasecmp(data, "CONTEXT"))
2481 ast_copy_string(buf, exception->context, buflen);
2482 else if (!strncasecmp(data, "EXTEN", 5))
2483 ast_copy_string(buf, exception->exten, buflen);
2484 else if (!strcasecmp(data, "PRIORITY"))
2485 snprintf(buf, buflen, "%d", exception->priority);
2486 else
2487 res = -1;
2488
2489 ast_channel_unlock(chan);
2490 return res;
2491}
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition channel.c:2390
char buf[BUFSIZE]
Definition eagi_proxy.c:66
static const struct ast_datastore_info exception_store_info
Definition pbx.c:2416
Structure for a data store object.
Definition datastore.h:64
void * data
Definition datastore.h:66
const ast_string_field context
Definition pbx.c:283
const ast_string_field exten
Definition pbx.c:283
int priority
Definition pbx.c:285
const ast_string_field reason
Definition pbx.c:283

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

◆ add_exten_to_pattern_tree()

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

Definition at line 1289 of file pbx.c.

1290{
1291 struct match_char *m1 = NULL;
1292 struct match_char *m2 = NULL;
1293 struct match_char **m0;
1294 const char *pos;
1295 int already;
1296 int pattern = 0;
1297 int idx_cur;
1298 int idx_next;
1299 char extenbuf[MAX_EXTENBUF_SIZE];
1300 volatile size_t required_space = strlen(e1->exten) + 1;
1301 struct pattern_node pat_node[2];
1302
1303 if (e1->matchcid) {
1304 required_space += (strlen(e1->cidmatch) + 2 /* '/' + NULL */);
1305 if (required_space > MAX_EXTENBUF_SIZE) {
1307 "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n",
1308 e1->exten, e1->cidmatch);
1309 return NULL;
1310 }
1311 sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe. We just checked. */
1312 } else {
1313 if (required_space > MAX_EXTENBUF_SIZE) {
1315 "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n",
1316 e1->exten, e1->cidmatch);
1317 return NULL;
1318 }
1319 ast_copy_string(extenbuf, e1->exten, required_space);
1320 }
1321
1322#ifdef NEED_DEBUG
1323 ast_debug(1, "Adding exten %s to tree\n", extenbuf);
1324#endif
1325 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
1326 m0 = &con->pattern_tree;
1327 already = 1;
1328
1329 pos = extenbuf;
1330 if (*pos == '_') {
1331 pattern = 1;
1332 ++pos;
1333 }
1334 idx_cur = 0;
1335 pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf);
1336 for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) {
1337 idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node);
1338 pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf);
1339
1340 /* See about adding node to tree. */
1341 m2 = NULL;
1342 if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern))
1343 && m2->next_char) {
1344 if (!pat_node[idx_next].buf[0]) {
1345 /*
1346 * This is the end of the pattern, but not the end of the tree.
1347 * Mark this node with the exten... a shorter pattern might win
1348 * if the longer one doesn't match.
1349 */
1350 if (findonly) {
1351 return m2;
1352 }
1353 if (m2->exten) {
1354 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
1355 m2->deleted ? "(deleted/invalid)" : m2->exten->name, e1->name);
1356 }
1357 m2->exten = e1;
1358 m2->deleted = 0;
1359 }
1360 m1 = m2->next_char; /* m1 points to the node to compare against */
1361 m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */
1362 } else { /* not already OR not m2 OR nor m2->next_char */
1363 if (m2) {
1364 if (findonly) {
1365 return m2;
1366 }
1367 m1 = m2; /* while m0 stays the same */
1368 } else {
1369 if (findonly) {
1370 return m1;
1371 }
1372 m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0);
1373 if (!m1) { /* m1 is the node just added */
1374 return NULL;
1375 }
1376 m0 = &m1->next_char;
1377 }
1378 if (!pat_node[idx_next].buf[0]) {
1379 if (m2 && m2->exten) {
1380 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
1381 m2->deleted ? "(deleted/invalid)" : m2->exten->name, e1->name);
1382 }
1383 m1->deleted = 0;
1384 m1->exten = e1;
1385 }
1386
1387 /* The 'already' variable is a mini-optimization designed to make it so that we
1388 * don't have to call already_in_tree when we know it will return false.
1389 */
1390 already = 0;
1391 }
1392 }
1393 return m1;
1394}
static const char name[]
Definition format_mp3.c:68
#define LOG_ERROR
static struct match_char * already_in_tree(struct match_char *current, char *pat, int is_pattern)
Definition pbx.c:1028
static struct match_char * add_pattern_node(struct ast_context *con, struct match_char *current, const struct pattern_node *pattern, int is_pattern, int already, struct match_char **nextcharptr)
Definition pbx.c:1090
#define MAX_EXTENBUF_SIZE
Definition pbx.c:1288
static const char * get_pattern_node(struct pattern_node *node, const char *src, int pattern, const char *extenbuf)
Definition pbx.c:1144
match_char: forms a syntax tree for quick matching of extension patterns
Definition pbx.c:232
int deleted
Definition pbx.c:234
struct match_char * next_char
Definition pbx.c:237
struct ast_exten * exten
Definition pbx.c:238
#define ARRAY_LEN(a)
Definition utils.h:706

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

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

◆ add_pattern_node()

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

Definition at line 1090 of file pbx.c.

1091{
1092 struct match_char *m;
1093
1094 if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) {
1095 return NULL;
1096 }
1097
1098 /* strcpy is safe here since we know its size and have allocated
1099 * just enough space for when we allocated m
1100 */
1101 strcpy(m->x, pattern->buf);
1102
1103 /* the specificity scores are the same as used in the old
1104 pattern matcher. */
1106 if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') {
1107 m->specificity = 0x0832;
1108 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') {
1109 m->specificity = 0x0931;
1110 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') {
1111 m->specificity = 0x0a30;
1112 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') {
1113 m->specificity = 0x18000;
1114 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') {
1115 m->specificity = 0x28000;
1116 } else {
1117 m->specificity = pattern->specif;
1118 }
1119
1120 if (!con->pattern_tree) {
1122 } else {
1123 if (already) { /* switch to the new regime (traversing vs appending)*/
1124 insert_in_next_chars_alt_char_list(nextcharptr, m);
1125 } else {
1127 }
1128 }
1129
1130 return m;
1131}
size_t current
static void insert_in_next_chars_alt_char_list(struct match_char **parent_ptr, struct match_char *node)
Definition pbx.c:1049
int is_pattern
Definition pbx.c:233
int specificity
Definition pbx.c:235
char x[1]
Definition pbx.c:239
char buf[256]
Definition pbx.c:1087
int specif
Definition pbx.c:1085

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

Referenced by add_exten_to_pattern_tree().

◆ add_priority()

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

add the extension in the priority chain.

Return values
0on success.
-1on failure.

Definition at line 5349 of file pbx.c.

5351{
5352 struct ast_exten *ep;
5353 struct ast_exten *eh=e;
5354 int repeated_label = 0; /* Track if this label is a repeat, assume no. */
5355
5356 for (ep = NULL; e ; ep = e, e = e->peer) {
5357 if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
5358 if (strcmp(e->name, tmp->name)) {
5360 "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n",
5361 tmp->name, tmp->priority, con->name, tmp->label, e->name, e->priority);
5362 } else {
5364 "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n",
5365 tmp->name, tmp->priority, con->name, tmp->label, e->priority);
5366 }
5367 repeated_label = 1;
5368 }
5369 if (e->priority >= tmp->priority) {
5370 break;
5371 }
5372 }
5373
5374 if (repeated_label) { /* Discard the label since it's a repeat. */
5375 tmp->label = NULL;
5376 }
5377
5378 if (!e) { /* go at the end, and ep is surely set because the list is not empty */
5380
5381 if (tmp->label) {
5383 }
5384 ep->peer = tmp;
5385 return 0; /* success */
5386 }
5387 if (e->priority == tmp->priority) {
5388 /* Can't have something exactly the same. Is this a
5389 replacement? If so, replace, otherwise, bonk. */
5390 if (!replace) {
5391 if (strcmp(e->name, tmp->name)) {
5393 "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n",
5394 tmp->name, tmp->priority, con->name, e->name);
5395 } else {
5397 "Unable to register extension '%s' priority %d in '%s', already in use\n",
5398 tmp->name, tmp->priority, con->name);
5399 }
5400
5401 return -1;
5402 }
5403 /* we are replacing e, so copy the link fields and then update
5404 * whoever pointed to e to point to us
5405 */
5406 tmp->next = e->next; /* not meaningful if we are not first in the peer list */
5407 tmp->peer = e->peer; /* always meaningful */
5408 if (ep) { /* We're in the peer list, just insert ourselves */
5410
5411 if (e->label) {
5413 }
5414
5416 if (tmp->label) {
5418 }
5419
5420 ep->peer = tmp;
5421 } else if (el) { /* We're the first extension. Take over e's functions */
5422 struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
5423 tmp->peer_table = e->peer_table;
5424 tmp->peer_label_table = e->peer_label_table;
5427 if (e->label) {
5429 }
5430 if (tmp->label) {
5432 }
5433
5436 el->next = tmp;
5437 /* The pattern trie points to this exten; replace the pointer,
5438 and all will be well */
5439 if (x) { /* if the trie isn't formed yet, don't sweat this */
5440 if (x->exten) { /* this test for safety purposes */
5441 x->exten = tmp; /* replace what would become a bad pointer */
5442 } else {
5443 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
5444 }
5445 }
5446 } else { /* We're the very first extension. */
5447 struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
5450 tmp->peer_table = e->peer_table;
5451 tmp->peer_label_table = e->peer_label_table;
5454 if (e->label) {
5456 }
5457 if (tmp->label) {
5459 }
5460
5463 con->root = tmp;
5464 /* The pattern trie points to this exten; replace the pointer,
5465 and all will be well */
5466 if (x) { /* if the trie isn't formed yet; no problem */
5467 if (x->exten) { /* this test for safety purposes */
5468 x->exten = tmp; /* replace what would become a bad pointer */
5469 } else {
5470 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
5471 }
5472 }
5473 }
5474 if (tmp->priority == PRIORITY_HINT)
5475 ast_change_hint(e,tmp);
5476 /* Destroy the old one */
5477 if (e->datad)
5478 e->datad(e->data);
5479 ast_free(e);
5480 } else { /* Slip ourselves in just before e */
5481 tmp->peer = e;
5482 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
5483 if (ep) { /* Easy enough, we're just in the peer list */
5484 if (tmp->label) {
5486 }
5488 ep->peer = tmp;
5489 } else { /* we are the first in some peer list, so link in the ext list */
5490 tmp->peer_table = e->peer_table;
5491 tmp->peer_label_table = e->peer_label_table;
5492 e->peer_table = 0;
5493 e->peer_label_table = 0;
5495 if (tmp->label) {
5497 }
5500 if (el)
5501 el->next = tmp; /* in the middle... */
5502 else
5503 con->root = tmp; /* ... or at the head */
5504 e->next = NULL; /* e is no more at the head, so e->next must be reset */
5505 }
5506 /* And immediately return success. */
5507 if (tmp->priority == PRIORITY_HINT) {
5508 ast_add_hint(tmp);
5509 }
5510 }
5511 return 0;
5512}
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
#define ast_hashtab_insert_safe(tab, obj)
Definition hashtab.h:316
void * ast_hashtab_remove_object_via_lookup(struct ast_hashtab *tab, void *obj)
Looks up the object, removes the corresponding bucket.
Definition hashtab.c:746
static struct match_char * add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
Definition pbx.c:1289
static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
Change hint for an extension.
Definition pbx.c:2680
static int ast_add_hint(struct ast_exten *e)
Definition pbx.c:2666
#define PRIORITY_HINT
Definition pbx.h:54
struct ast_hashtab * peer_label_table
Definition pbx.c:222
const char * label
Definition pbx.c:214

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

Referenced by ast_add_extension2_lockopt().

◆ already_in_tree()

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

Definition at line 1028 of file pbx.c.

1029{
1030 struct match_char *t;
1031
1032 if (!current) {
1033 return 0;
1034 }
1035
1036 for (t = current; t; t = t->alt_char) {
1037 if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */
1038 return t;
1039 }
1040 }
1041
1042 return 0;
1043}
struct match_char * alt_char
Definition pbx.c:236

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

Referenced by add_exten_to_pattern_tree().

◆ ast_active_calls()

int ast_active_calls ( void  )

Retrieve the number of active calls.

Definition at line 3320 of file pbx.c.

3321{
3322 return countcalls;
3323}
static int countcalls
Definition pbx.c:422

References countcalls.

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

◆ ast_add_extension()

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

Add and extension to an extension context.

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

Definition at line 5206 of file pbx.c.

5209{
5210 int ret = -1;
5211 struct ast_context *c;
5212
5213 c = find_context_locked(context);
5214 if (c) {
5215 ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
5216 application, data, datad, registrar, NULL, 0);
5218 }
5219
5220 return ret;
5221}
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:5539
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition pbx.c:3374
int ast_unlock_contexts(void)
Unlocks contexts.
Definition pbx.c:6631
char data[]
Definition pbx.c:275

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

Referenced by add_to_regcontext(), app_create(), ast_sip_persistent_endpoint_update_state(), AST_TEST_DEFINE(), AST_TEST_DEFINE(), create_test_dialplan(), extension_state_autohints_device_state_cb(), extension_state_get(), handle_cli_dialplan_add_extension(), join_conference_bridge(), load_module(), register_extension(), register_peer_exten(), session_register_apps(), sla_build_station(), and sla_build_trunk().

◆ ast_add_extension2()

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

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

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

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

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

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

Definition at line 5539 of file pbx.c.

5543{
5544 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
5545 application, data, datad, registrar, registrar_file, registrar_line, 1);
5546}
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:5565

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

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

◆ ast_add_extension2_lockopt()

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

Same as ast_add_extension2() but controls the context locking.

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

Definition at line 5565 of file pbx.c.

5569{
5570 /*
5571 * Sort extensions (or patterns) according to the rules indicated above.
5572 * These are implemented by the function ext_cmp()).
5573 * All priorities for the same ext/pattern/cid are kept in a list,
5574 * using the 'peer' field as a link field..
5575 */
5576 struct ast_exten *tmp, *tmp2, *e, *el = NULL;
5577 int res;
5578 int length;
5579 char *p;
5580 char expand_buf[VAR_BUF_SIZE];
5581 struct ast_exten dummy_exten = {0};
5582 char dummy_name[1024];
5583 int exten_fluff;
5584 int callerid_fluff;
5585
5587 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",
5588 con->name);
5589 /* We always need to deallocate 'data' on failure */
5590 if (datad) {
5591 datad(data);
5592 }
5593 return -1;
5594 }
5595
5596 /* If we are adding a hint evaluate in variables and global variables */
5597 if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') {
5598 int inhibited;
5600
5601 if (c) {
5604 }
5605
5606 /*
5607 * We can allow dangerous functions when adding a hint since
5608 * altering dialplan is itself a privileged activity. Otherwise,
5609 * we could never execute dangerous functions.
5610 */
5612 pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
5613 if (0 < inhibited) {
5615 }
5616
5617 application = expand_buf;
5618 if (c) {
5620 }
5621 }
5622
5623 if (priority == PRIORITY_HINT) {
5624 /* Fluff in a hint is fine. This prevents the removal of dashes from dynamically
5625 * created hints during a reload. */
5626 exten_fluff = 0;
5627 } else {
5628 exten_fluff = ext_fluff_count(extension);
5629 }
5630
5631 callerid_fluff = callerid ? ext_fluff_count(callerid) : 0;
5632
5633 length = sizeof(struct ast_exten);
5634 length += strlen(extension) + 1;
5635 if (exten_fluff) {
5636 length += strlen(extension) + 1 - exten_fluff;
5637 }
5638 length += strlen(application) + 1;
5639 if (label) {
5640 length += strlen(label) + 1;
5641 }
5642 if (callerid) {
5643 length += strlen(callerid) + 1;
5644 if (callerid_fluff) {
5645 length += strlen(callerid) + 1 - callerid_fluff;
5646 }
5647 } else {
5648 length ++; /* just the '\0' */
5649 }
5650 if (registrar_file) {
5651 length += strlen(registrar_file) + 1;
5652 }
5653
5654 /* Be optimistic: Build the extension structure first */
5655 tmp = ast_calloc(1, length);
5656 if (!tmp) {
5657 /* We always need to deallocate 'data' on failure */
5658 if (datad) {
5659 datad(data);
5660 }
5661 return -1;
5662 }
5663
5664 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
5665 label = 0;
5666
5667 /* use p as dst in assignments, as the fields are const char * */
5668 p = tmp->stuff;
5669 if (label) {
5670 tmp->label = p;
5671 strcpy(p, label);
5672 p += strlen(label) + 1;
5673 }
5674 tmp->name = p;
5675 p += ext_strncpy(p, extension, strlen(extension) + 1, 0);
5676 if (exten_fluff) {
5677 tmp->exten = p;
5678 p += ext_strncpy(p, extension, strlen(extension) + 1 - exten_fluff, 1);
5679 } else {
5680 /* no fluff, we don't need a copy. */
5681 tmp->exten = tmp->name;
5682 }
5683 tmp->priority = priority;
5684 tmp->cidmatch_display = tmp->cidmatch = p; /* but use p for assignments below */
5685
5686 /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */
5687 if (callerid) {
5688 p += ext_strncpy(p, callerid, strlen(callerid) + 1, 0);
5689 if (callerid_fluff) {
5690 tmp->cidmatch = p;
5691 p += ext_strncpy(p, callerid, strlen(callerid) + 1 - callerid_fluff, 1);
5692 }
5694 } else {
5695 *p++ = '\0';
5697 }
5698
5699 if (registrar_file) {
5700 tmp->registrar_file = p;
5701 strcpy(p, registrar_file);
5702 p += strlen(registrar_file) + 1;
5703 } else {
5704 tmp->registrar_file = NULL;
5705 }
5706
5707 tmp->app = p;
5708 strcpy(p, application);
5709 tmp->parent = con;
5710 tmp->data = data;
5711 tmp->datad = datad;
5712 tmp->registrar = registrar;
5714
5715 if (lock_context) {
5716 ast_wrlock_context(con);
5717 }
5718
5719 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
5720 an extension, and the trie exists, then we need to incrementally add this pattern to it. */
5721 ext_strncpy(dummy_name, tmp->exten, sizeof(dummy_name), 1);
5722 dummy_exten.exten = dummy_name;
5723 dummy_exten.matchcid = AST_EXT_MATCHCID_OFF;
5724 dummy_exten.cidmatch = 0;
5725 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
5726 if (!tmp2) {
5727 /* hmmm, not in the trie; */
5728 add_exten_to_pattern_tree(con, tmp, 0);
5729 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
5730 }
5731 }
5732 res = 0; /* some compilers will think it is uninitialized otherwise */
5733 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */
5734 res = ext_cmp(e->exten, tmp->exten);
5735 if (res == 0) { /* extension match, now look at cidmatch */
5736 if (e->matchcid == AST_EXT_MATCHCID_OFF && tmp->matchcid == AST_EXT_MATCHCID_OFF)
5737 res = 0;
5738 else if (tmp->matchcid == AST_EXT_MATCHCID_ON && e->matchcid == AST_EXT_MATCHCID_OFF)
5739 res = 1;
5740 else if (e->matchcid == AST_EXT_MATCHCID_ON && tmp->matchcid == AST_EXT_MATCHCID_OFF)
5741 res = -1;
5742 else
5743 res = ext_cmp(e->cidmatch, tmp->cidmatch);
5744 }
5745 if (res >= 0)
5746 break;
5747 }
5748 if (e && res == 0) { /* exact match, insert in the priority chain */
5749 res = add_priority(con, tmp, el, e, replace);
5750 if (res < 0) {
5751 if (con->pattern_tree) {
5752 struct match_char *x = add_exten_to_pattern_tree(con, tmp, 1);
5753
5754 if (x->exten) {
5755 x->deleted = 1;
5756 x->exten = 0;
5757 }
5758
5760 }
5761
5762 if (tmp->datad) {
5763 tmp->datad(tmp->data);
5764 /* if you free this, null it out */
5765 tmp->data = NULL;
5766 }
5767
5768 ast_free(tmp);
5769 }
5770 if (lock_context) {
5771 ast_unlock_context(con);
5772 }
5773 if (res < 0) {
5774 errno = EEXIST;
5775 return -1;
5776 }
5777 } else {
5778 /*
5779 * not an exact match, this is the first entry with this pattern,
5780 * so insert in the main list right before 'e' (if any)
5781 */
5782 tmp->next = e;
5788 0);
5794 0);
5795
5796 if (el) { /* there is another exten already in this context */
5797 el->next = tmp;
5798 } else { /* this is the first exten in this context */
5799 if (!con->root_table) {
5805 0);
5806 }
5807 con->root = tmp;
5808 }
5809 if (label) {
5811 }
5814
5815 if (lock_context) {
5816 ast_unlock_context(con);
5817 }
5818 if (tmp->priority == PRIORITY_HINT) {
5819 ast_add_hint(tmp);
5820 }
5821 }
5822 if (DEBUG_ATLEAST(1)) {
5823 if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
5824 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
5825 tmp->name, tmp->priority, tmp->cidmatch_display, con->name, con);
5826 } else {
5827 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s (%p)\n",
5828 tmp->name, tmp->priority, con->name, con);
5829 }
5830 }
5831
5832 return 0;
5833}
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition channel.h:3019
void ast_channel_context_set(struct ast_channel *chan, const char *value)
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition channel.h:1328
int ast_hashtab_newsize_java(struct ast_hashtab *tab)
Create a prime number roughly 2x the current table size.
Definition hashtab.c:127
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition hashtab.c:486
#define ast_hashtab_create(initial_buckets, compare, resize, newsize, hash, do_locking)
Create the hashtable list.
Definition hashtab.h:254
int ast_hashtab_resize_java(struct ast_hashtab *tab)
Determines if a table resize should occur using the Java algorithm (if the table load factor is 75% o...
Definition hashtab.c:84
#define DEBUG_ATLEAST(level)
#define LOG_DEBUG
int errno
static int hashtab_compare_extens(const void *ha_a, const void *ah_b)
Definition pbx.c:347
static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b)
Definition pbx.c:375
static int ext_cmp(const char *left, const char *right)
Definition pbx.c:1766
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:5349
static int ext_fluff_count(const char *exten)
Definition pbx.c:1788
static unsigned int hashtab_hash_extens(const void *obj)
Definition pbx.c:395
static unsigned int hashtab_hash_priority(const void *obj)
Definition pbx.c:405
static unsigned int ext_strncpy(char *dst, const char *src, size_t dst_size, int nofluff)
Definition pbx.c:5308
static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b)
Definition pbx.c:382
static unsigned int hashtab_hash_labels(const void *obj)
Definition pbx.c:411
int ast_thread_inhibit_escalations_swap(int inhibit)
Swap the current thread escalation inhibit setting.
@ AST_EXT_MATCHCID_ON
Definition pbx.h:79
@ AST_EXT_MATCHCID_OFF
Definition pbx.h:78
int ast_thread_inhibit_escalations(void)
Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations...
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition ael_main.c:211
#define VAR_BUF_SIZE
Definition pbx_private.h:76
const char * cidmatch_display
Definition pbx.c:212
char stuff[0]
Definition pbx.c:227
const char * app
Definition pbx.c:216
const char * registrar_file
Definition pbx.c:224
int registrar_line
Definition pbx.c:225
struct ast_context * parent
Definition pbx.c:215
void * data
Definition pbx.c:218
void(* datad)(void *)
Definition pbx.c:219

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

Referenced by ast_add_extension2(), and ast_add_extension2_nolock().

◆ ast_add_extension2_nolock()

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

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

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

Definition at line 5548 of file pbx.c.

5552{
5553 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
5554 application, data, datad, registrar, registrar_file, registrar_line, 0);
5555}

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

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

◆ ast_add_hint()

static int ast_add_hint ( struct ast_exten e)
static

Definition at line 2666 of file pbx.c.

2667{
2668 if (!e) {
2669 return -1;
2670 }
2671
2674 }
2675
2676 return 0;
2677}
void pbx_extension_state_hint_set(struct ast_exten *exten, struct ast_context *context)

References AST_CONTEXT_SCOPE_GLOBAL, ast_exten::parent, pbx_extension_state_hint_set(), and ast_context::scope.

Referenced by add_priority(), and ast_add_extension2_lockopt().

◆ ast_async_goto()

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

Set the channel to next execute the specified dialplan location.

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

Definition at line 5251 of file pbx.c.

5252{
5253 struct ast_channel *newchan;
5254
5255 ast_channel_lock(chan);
5256 /* Channels in a bridge or running a PBX can be sent directly to the specified destination */
5257 if (ast_channel_is_bridged(chan) || ast_channel_pbx(chan)) {
5259 priority += 1;
5260 }
5263 ast_channel_unlock(chan);
5264 return 0;
5265 }
5266 ast_channel_unlock(chan);
5267
5268 /* Otherwise, we need to gain control of the channel first */
5269 newchan = ast_channel_yank(chan);
5270 if (!newchan) {
5271 ast_log(LOG_WARNING, "Unable to gain control of channel %s\n", ast_channel_name(chan));
5272 return -1;
5273 }
5275 if (ast_pbx_start(newchan)) {
5276 ast_hangup(newchan);
5277 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(newchan));
5278 return -1;
5279 }
5280
5281 return 0;
5282}
struct ast_channel * ast_channel_yank(struct ast_channel *yankee)
Gain control of a channel in the system.
Definition channel.c:10773
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition channel.c:10725
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition channel.c:2449
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition pbx.c:3268

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

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

◆ ast_async_goto_by_name()

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

Set the channel to next execute the specified dialplan location.

Definition at line 5284 of file pbx.c.

5285{
5286 struct ast_channel *chan;
5287 int res = -1;
5288
5289 if ((chan = ast_channel_get_by_name(channame))) {
5290 res = ast_async_goto(chan, context, exten, priority);
5291 chan = ast_channel_unref(chan);
5292 }
5293
5294 return res;
5295}
struct ast_channel * ast_channel_get_by_name(const char *search)
Find a channel by name or uniqueid.
Definition channel.c:1417

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

◆ ast_async_goto_if_exists()

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

Definition at line 6944 of file pbx.c.

6945{
6946 return __ast_goto_if_exists(chan, context, exten, priority, 1);
6947}
static int __ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
Definition pbx.c:6918

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

◆ ast_async_parseable_goto()

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

Definition at line 7029 of file pbx.c.

7030{
7031 return pbx_parseable_goto(chan, goto_string, 1);
7032}
static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string, int async)
Definition pbx.c:6990

References pbx_parseable_goto().

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

◆ ast_canmatch_extension()

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

Looks for a valid matching extension.

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

Definition at line 2750 of file pbx.c.

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

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

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

◆ ast_change_hint()

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

Change hint for an extension.

Definition at line 2680 of file pbx.c.

2681{
2682 if (!oe || !ne) {
2683 return -1;
2684 }
2685
2688 }
2691 }
2692
2693 return 0;
2694}
void pbx_extension_state_hint_remove(struct ast_exten *exten, struct ast_context *context)

References AST_CONTEXT_SCOPE_GLOBAL, ast_exten::parent, pbx_extension_state_hint_remove(), pbx_extension_state_hint_set(), and ast_context::scope.

Referenced by add_priority().

◆ ast_context_add_ignorepat()

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

Add an ignorepat.

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

Adds an ignore pattern to a particular context.

Return values
0on success
-1on failure

Definition at line 5133 of file pbx.c.

5134{
5135 int ret = -1;
5136 struct ast_context *c;
5137
5138 c = find_context_locked(context);
5139 if (c) {
5142 }
5143 return ret;
5144}
int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
Definition pbx.c:5146
int value
Definition syslog.c:37

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

Referenced by handle_cli_dialplan_add_ignorepat().

◆ ast_context_add_ignorepat2()

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

Definition at line 5146 of file pbx.c.

5147{
5148 struct ast_ignorepat *ignorepat = ignorepat_alloc(value, registrar);
5149 int idx;
5150
5151 if (!ignorepat) {
5152 return -1;
5153 }
5154
5155 ast_wrlock_context(con);
5156 for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
5157 const struct ast_ignorepat *i = ast_context_ignorepats_get(con, idx);
5158
5159 if (!strcasecmp(ast_get_ignorepat_name(i), value)) {
5160 /* Already there */
5161 ast_unlock_context(con);
5162 ignorepat_free(ignorepat);
5163 errno = EEXIST;
5164 return -1;
5165 }
5166 }
5167 if (AST_VECTOR_APPEND(&con->ignorepats, ignorepat)) {
5168 ignorepat_free(ignorepat);
5169 ast_unlock_context(con);
5170 return -1;
5171 }
5172 ast_unlock_context(con);
5173
5174 return 0;
5175}
const struct ast_ignorepat * ast_context_ignorepats_get(const struct ast_context *con, int idx)
Definition pbx.c:6885
const char * ast_get_ignorepat_name(const struct ast_ignorepat *ip)
struct ast_ignorepat * ignorepat_alloc(const char *value, const char *registrar)
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition vector.h:267

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

Referenced by ast_context_add_ignorepat(), and context_merge_incls_swits_igps_other_registrars().

◆ ast_context_add_include()

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

Add a context include.

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

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

Return values
0on success
-1on error

Definition at line 4962 of file pbx.c.

4963{
4964 int ret = -1;
4965 struct ast_context *c;
4966
4967 c = find_context_locked(context);
4968 if (c) {
4969 ret = ast_context_add_include2(c, include, registrar);
4971 }
4972 return ret;
4973}
int ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
Add a context include.
Definition pbx.c:4982

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

Referenced by AST_TEST_DEFINE(), and handle_cli_dialplan_add_include().

◆ ast_context_add_include2()

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

Add a context include.

Adds an include taking a struct ast_context as the first parameter

Note
See ast_context_add_include for information on arguments

Definition at line 4982 of file pbx.c.

4984{
4985 struct ast_include *new_include;
4986 int idx;
4987
4988 /* allocate new include structure ... */
4989 new_include = include_alloc(value, registrar);
4990 if (!new_include) {
4991 return -1;
4992 }
4993
4994 ast_wrlock_context(con);
4995
4996 /* ... go to last include and check if context is already included too... */
4997 for (idx = 0; idx < ast_context_includes_count(con); idx++) {
4998 const struct ast_include *i = ast_context_includes_get(con, idx);
4999
5000 if (!strcasecmp(ast_get_include_name(i), ast_get_include_name(new_include))) {
5001 include_free(new_include);
5002 ast_unlock_context(con);
5003 errno = EEXIST;
5004 return -1;
5005 }
5006 }
5007
5008 /* ... include new context into context list, unlock, return */
5009 if (AST_VECTOR_APPEND(&con->includes, new_include)) {
5010 include_free(new_include);
5011 ast_unlock_context(con);
5012 return -1;
5013 }
5014 ast_debug(1, "Including context '%s' in context '%s'\n",
5015 ast_get_include_name(new_include), ast_get_context_name(con));
5016
5017 ast_unlock_context(con);
5018
5019 return 0;
5020}
const struct ast_include * ast_context_includes_get(const struct ast_context *con, int idx)
Definition pbx.c:6842
const char * ast_get_context_name(struct ast_context *con)
Definition pbx.c:6657
const char * ast_get_include_name(const struct ast_include *include)
Definition pbx_include.c:50
struct ast_include * include_alloc(const char *value, const char *registrar)
Definition pbx_include.c:74

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

Referenced by ast_context_add_include(), and context_merge_incls_swits_igps_other_registrars().

◆ ast_context_add_switch()

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

Add a switch.

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

This function registers a switch with the asterisk switch architecture

Return values
0on success
-1on failure

Definition at line 5027 of file pbx.c.

5028{
5029 int ret = -1;
5030 struct ast_context *c;
5031
5032 c = find_context_locked(context);
5033 if (c) { /* found, add switch to this context */
5034 ret = ast_context_add_switch2(c, sw, data, eval, registrar);
5036 }
5037 return ret;
5038}
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:5047

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

◆ ast_context_add_switch2()

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

Adds a switch (first param is a ast_context)

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

Definition at line 5047 of file pbx.c.

5049{
5050 int idx;
5051 struct ast_sw *new_sw;
5052
5053 /* allocate new sw structure ... */
5054 if (!(new_sw = sw_alloc(value, data, eval, registrar))) {
5055 return -1;
5056 }
5057
5058 /* ... try to lock this context ... */
5059 ast_wrlock_context(con);
5060
5061 /* ... go to last sw and check if context is already swd too... */
5062 for (idx = 0; idx < ast_context_switches_count(con); idx++) {
5063 const struct ast_sw *i = ast_context_switches_get(con, idx);
5064
5065 if (!strcasecmp(ast_get_switch_name(i), ast_get_switch_name(new_sw)) &&
5066 !strcasecmp(ast_get_switch_data(i), ast_get_switch_data(new_sw))) {
5067 sw_free(new_sw);
5068 ast_unlock_context(con);
5069 errno = EEXIST;
5070 return -1;
5071 }
5072 }
5073
5074 /* ... sw new context into context list, unlock, return */
5075 if (AST_VECTOR_APPEND(&con->alts, new_sw)) {
5076 sw_free(new_sw);
5077 ast_unlock_context(con);
5078 return -1;
5079 }
5080
5081 ast_verb(3, "Including switch '%s/%s' in context '%s'\n",
5083
5084 ast_unlock_context(con);
5085
5086 return 0;
5087}
const struct ast_sw * ast_context_switches_get(const struct ast_context *con, int idx)
Definition pbx.c:6797
const char * ast_get_switch_name(const struct ast_sw *sw)
Definition pbx_sw.c:48
const char * ast_get_switch_data(const struct ast_sw *sw)
Definition pbx_sw.c:53
struct ast_sw * sw_alloc(const char *value, const char *data, int eval, const char *registrar)
Definition pbx_sw.c:68
int eval
Definition pbx_sw.c:43
const char * data
Definition pbx_sw.c:42

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

Referenced by ast_context_add_switch(), and context_merge_incls_swits_igps_other_registrars().

◆ ast_context_destroy()

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

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

Parameters
concontext to destroy
registrarwho registered it

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

Definition at line 6507 of file pbx.c.

6508{
6512}
void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
Definition pbx.c:6342
int ast_wrlock_contexts(void)
Write locks the context list.
Definition pbx.c:6621
static struct ast_hashtab * contexts_table
Definition pbx.c:426

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

◆ ast_context_destroy_by_name()

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

Destroy a context by name.

Parameters
contextName of the context to destroy
registrarwho registered it

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

Return values
-1context not found
0Success

Definition at line 6491 of file pbx.c.

6492{
6493 struct ast_context *con;
6494 int ret = -1;
6495
6497 con = ast_context_find(context);
6498 if (con) {
6500 ret = 0;
6501 }
6503
6504 return ret;
6505}
void ast_context_destroy(void)
Definition ael_main.c:414
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition pbx.c:2065

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

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

◆ ast_context_find()

struct ast_context * ast_context_find ( const char *  name)

Find a context.

Parameters
namename of the context to find

Will search for the context with the given name.

Returns
the ast_context on success, NULL on failure.

Definition at line 2065 of file pbx.c.

2066{
2067 struct ast_context *tmp;
2068 struct ast_context item = {
2069 .name = name,
2070 };
2071
2072 if (!name) {
2073 return NULL;
2074 }
2076 if (contexts_table) {
2078 } else {
2079 tmp = NULL;
2080 while ((tmp = ast_walk_contexts(tmp))) {
2081 if (!strcasecmp(name, tmp->name)) {
2082 break;
2083 }
2084 }
2085 }
2087 return tmp;
2088}
struct ast_context * ast_walk_contexts(void)
Definition ael_main.c:401
int ast_rdlock_contexts(void)
Read locks the context list.
Definition pbx.c:6626
const char * name
static struct aco_type item

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

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

◆ ast_context_find_or_create()

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

Register a new context or find an existing one.

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

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

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

Returns
NULL on failure, and an ast_context structure on success

Definition at line 4542 of file pbx.c.

4543{
4544 struct ast_context *tmp, **local_contexts;
4545 struct ast_context search = {
4546 .name = name,
4547 };
4548 size_t name_bytes = strlen(name);
4549 size_t registrar_bytes = strlen(registrar);
4550 int length = sizeof(struct ast_context) + name_bytes + registrar_bytes + 2;
4551
4552 if (!contexts_table) {
4553 /* Protect creation of contexts_table from reentrancy. */
4555 if (!contexts_table) {
4561 0);
4562 }
4564 }
4565
4566 if (!extcontexts) {
4569 tmp = ast_hashtab_lookup(contexts_table, &search);
4570 if (tmp) {
4571 tmp->refcount++;
4573 return tmp;
4574 }
4575 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
4576 local_contexts = extcontexts;
4577 tmp = ast_hashtab_lookup(exttable, &search);
4578 if (tmp) {
4579 tmp->refcount++;
4580 return tmp;
4581 }
4582 }
4583
4584 if ((tmp = ast_calloc(1, length))) {
4585 ast_rwlock_init(&tmp->lock);
4586 tmp->name = memcpy(&tmp->data[0], name, name_bytes);
4587 tmp->registrar = memcpy(&tmp->data[name_bytes + 1], registrar, registrar_bytes);
4588 tmp->root = NULL;
4589 tmp->root_table = NULL;
4590 AST_VECTOR_INIT(&tmp->includes, 0);
4591 AST_VECTOR_INIT(&tmp->ignorepats, 0);
4592 AST_VECTOR_INIT(&tmp->alts, 0);
4593 tmp->refcount = 1;
4594
4595 /* The context 'name' must be stored at the beginning of 'data.' The
4596 * order of subsequent strings (currently only 'registrar') is not
4597 * relevant. */
4598 ast_assert(tmp->name == &tmp->data[0]);
4599 } else {
4600 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
4601 if (!extcontexts) {
4603 }
4604 return NULL;
4605 }
4606
4607 if (!extcontexts) {
4609 tmp->next = *local_contexts;
4610 *local_contexts = tmp;
4611 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
4613 } else {
4615 tmp->next = *local_contexts;
4616 if (exttable)
4617 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
4618
4619 *local_contexts = tmp;
4620 }
4621 ast_debug(1, "Registered extension context '%s'; registrar: %s, scope: %s\n", tmp->name, registrar,
4622 tmp->scope == AST_CONTEXT_SCOPE_LOCAL ? "local": "global");
4623 return tmp;
4624}
#define ast_hashtab_insert_immediate(tab, obj)
Insert without checking.
Definition hashtab.h:290
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
Definition lock.h:231
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
hashtable functions for contexts
Definition pbx.c:337
unsigned int ast_hashtab_hash_contexts(const void *obj)
Definition pbx.c:389
static struct ast_context * local_contexts
Definition pbx_config.c:117
int refcount
Definition pbx.c:267
#define ast_assert(a)
Definition utils.h:779
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition vector.h:124

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

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

◆ ast_context_ignorepats_count()

int ast_context_ignorepats_count ( const struct ast_context con)

◆ ast_context_ignorepats_get()

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

◆ ast_context_includes_count()

int ast_context_includes_count ( const struct ast_context con)

◆ ast_context_includes_get()

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

◆ ast_context_remove_extension()

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

Simply remove extension from context.

Note
This function will lock conlock.

Definition at line 3508 of file pbx.c.

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

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

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

◆ ast_context_remove_extension2()

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

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

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

Definition at line 3538 of file pbx.c.

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

Referenced by add_extension(), and add_hints().

◆ ast_context_remove_extension_callerid()

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

Definition at line 3513 of file pbx.c.

3514{
3515 int ret = -1; /* default error return */
3516 struct ast_context *c;
3517
3518 c = find_context_locked(context);
3519 if (c) { /* ... remove extension ... */
3521 matchcallerid, registrar, 0);
3523 }
3524
3525 return ret;
3526}

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

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

◆ ast_context_remove_extension_callerid2()

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

Definition at line 3543 of file pbx.c.

3544{
3545 struct ast_exten *exten, *prev_exten = NULL;
3546 struct ast_exten *peer;
3547 struct ast_exten ex, *exten2, *exten3;
3548 char dummy_name[1024];
3549 char dummy_cid[1024];
3550 struct ast_exten *previous_peer = NULL;
3551 struct ast_exten *next_peer = NULL;
3552 int found = 0;
3553
3554 if (!already_locked)
3555 ast_wrlock_context(con);
3556
3557#ifdef NEED_DEBUG
3558 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
3559#endif
3560#ifdef CONTEXT_DEBUG
3561 check_contexts(__FILE__, __LINE__);
3562#endif
3563 /* find this particular extension */
3564 ex.exten = dummy_name;
3565 ext_strncpy(dummy_name, extension, sizeof(dummy_name), 1);
3566 ex.matchcid = matchcallerid;
3567 if (callerid) {
3568 ex.cidmatch = dummy_cid;
3569 ext_strncpy(dummy_cid, callerid, sizeof(dummy_cid), 1);
3570 } else {
3571 ex.cidmatch = NULL;
3572 }
3573 exten = ast_hashtab_lookup(con->root_table, &ex);
3574 if (exten) {
3575 if (priority == 0) {
3577 if (!exten2)
3578 ast_log(LOG_ERROR,"Trying to delete the exten %s from context %s, but could not remove from the root_table\n", extension, con->name);
3579 if (con->pattern_tree) {
3580 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
3581
3582 if (x->exten) { /* this test for safety purposes */
3583 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
3584 x->exten = 0; /* get rid of what will become a bad pointer */
3585 } else {
3586 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
3587 }
3588 }
3589 } else {
3590 ex.priority = priority;
3591 exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
3592 if (exten2) {
3593 if (exten2->label) { /* if this exten has a label, remove that, too */
3595 if (!exten3) {
3596 ast_log(LOG_ERROR, "Did not remove this priority label (%d/%s) "
3597 "from the peer_label_table of context %s, extension %s!\n",
3598 priority, exten2->label, con->name, exten2->name);
3599 }
3600 }
3601
3603 if (!exten3) {
3604 ast_log(LOG_ERROR, "Did not remove this priority (%d) from the "
3605 "peer_table of context %s, extension %s!\n",
3606 priority, con->name, exten2->name);
3607 }
3608 if (exten2 == exten && exten2->peer) {
3611 }
3612 if (ast_hashtab_size(exten->peer_table) == 0) {
3613 /* well, if the last priority of an exten is to be removed,
3614 then, the extension is removed, too! */
3616 if (!exten3) {
3617 ast_log(LOG_ERROR, "Did not remove this exten (%s) from the "
3618 "context root_table (%s) (priority %d)\n",
3619 exten->name, con->name, priority);
3620 }
3621 if (con->pattern_tree) {
3622 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
3623 if (x->exten) { /* this test for safety purposes */
3624 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
3625 x->exten = 0; /* get rid of what will become a bad pointer */
3626 }
3627 }
3628 }
3629 } else {
3630 ast_debug(3,"Could not find priority %d of exten %s in context %s!\n",
3631 priority, exten->name, con->name);
3632 }
3633 }
3634 } else {
3635 /* hmmm? this exten is not in this pattern tree? */
3636 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
3637 extension, con->name);
3638 }
3639#ifdef NEED_DEBUG
3640 if (con->pattern_tree) {
3641 ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
3642 log_match_char_tree(con->pattern_tree, " ");
3643 }
3644#endif
3645
3646 /* scan the extension list to find first matching extension-registrar */
3647 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
3648 if (!strcmp(exten->exten, ex.exten) &&
3649 (!matchcallerid ||
3650 (!ast_strlen_zero(ex.cidmatch) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, ex.cidmatch)) ||
3651 (ast_strlen_zero(ex.cidmatch) && ast_strlen_zero(exten->cidmatch)))) {
3652 break;
3653 }
3654 }
3655 if (!exten) {
3656 /* we can't find right extension */
3657 if (!already_locked)
3658 ast_unlock_context(con);
3659 return -1;
3660 }
3661
3662 /* scan the priority list to remove extension with exten->priority == priority */
3663 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
3664 peer && !strcmp(peer->exten, ex.exten) &&
3665 (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, ex.cidmatch))) ;
3666 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
3667
3668 if ((priority == 0 || peer->priority == priority) &&
3669 (!registrar || !strcmp(peer->registrar, registrar) )) {
3670 found = 1;
3671
3672 /* we are first priority extension? */
3673 if (!previous_peer) {
3674 /*
3675 * We are first in the priority chain, so must update the extension chain.
3676 * The next node is either the next priority or the next extension
3677 */
3678 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
3679 if (peer->peer) {
3680 /* move the peer_table and peer_label_table down to the next peer, if
3681 it is there */
3684 peer->peer_table = NULL;
3686 }
3687 if (!prev_exten) { /* change the root... */
3688 con->root = next_node;
3689 } else {
3690 prev_exten->next = next_node; /* unlink */
3691 }
3692 if (peer->peer) { /* update the new head of the pri list */
3693 peer->peer->next = peer->next;
3694 }
3695 } else { /* easy, we are not first priority in extension */
3696 previous_peer->peer = peer->peer;
3697 }
3698
3699
3700 /* now, free whole priority extension */
3702 } else {
3703 previous_peer = peer;
3704 }
3705 }
3706 if (!already_locked)
3707 ast_unlock_context(con);
3708 return found ? 0 : -1;
3709}
int ast_hashtab_size(struct ast_hashtab *tab)
Returns the number of elements stored in the hashtab.
Definition hashtab.c:577

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

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

◆ ast_context_remove_ignorepat()

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

Remove an ignorepat.

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

This removes the given ignorepattern

Return values
0on success
-1on failure

Definition at line 5093 of file pbx.c.

5094{
5095 int ret = -1;
5096 struct ast_context *c;
5097
5098 c = find_context_locked(context);
5099 if (c) {
5100 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
5102 }
5103 return ret;
5104}
int ast_context_remove_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
Definition pbx.c:5106

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

Referenced by handle_cli_dialplan_remove_ignorepat().

◆ ast_context_remove_ignorepat2()

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

Definition at line 5106 of file pbx.c.

5107{
5108 int idx;
5109
5110 ast_wrlock_context(con);
5111
5112 for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
5113 struct ast_ignorepat *ip = AST_VECTOR_GET(&con->ignorepats, idx);
5114
5115 if (!strcmp(ast_get_ignorepat_name(ip), ignorepat) &&
5118 ignorepat_free(ip);
5119 ast_unlock_context(con);
5120 return 0;
5121 }
5122 }
5123
5124 ast_unlock_context(con);
5125 errno = EINVAL;
5126 return -1;
5127}

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

Referenced by ast_context_remove_ignorepat().

◆ ast_context_remove_include()

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

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

Remove a context include.

Definition at line 3396 of file pbx.c.

3397{
3398 int ret = -1;
3399 struct ast_context *c;
3400
3401 c = find_context_locked(context);
3402 if (c) {
3403 /* found, remove include from this context ... */
3404 ret = ast_context_remove_include2(c, include, registrar);
3406 }
3407 return ret;
3408}
int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
Locks context, remove included contexts, unlocks context. When we call this function,...
Definition pbx.c:3419

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

Referenced by handle_cli_dialplan_remove_include().

◆ ast_context_remove_include2()

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

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

Removes an include by an ast_context structure.

Return values
0on success.
-1on failure.

Definition at line 3419 of file pbx.c.

3420{
3421 int ret = -1;
3422 int idx;
3423
3424 ast_wrlock_context(con);
3425
3426 /* find our include */
3427 for (idx = 0; idx < ast_context_includes_count(con); idx++) {
3428 struct ast_include *i = AST_VECTOR_GET(&con->includes, idx);
3429
3430 if (!strcmp(ast_get_include_name(i), include) &&
3431 (!registrar || !strcmp(ast_get_include_registrar(i), registrar))) {
3432
3433 /* remove from list */
3434 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
3436
3437 /* free include and return */
3438 include_free(i);
3439 ret = 0;
3440 break;
3441 }
3442 }
3443
3444 ast_unlock_context(con);
3445
3446 return ret;
3447}

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

Referenced by ast_context_remove_include().

◆ ast_context_remove_switch()

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

Remove a switch.

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

Definition at line 3454 of file pbx.c.

3455{
3456 int ret = -1; /* default error return */
3457 struct ast_context *c;
3458
3459 c = find_context_locked(context);
3460 if (c) {
3461 /* remove switch from this context ... */
3464 }
3465 return ret;
3466}
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:3476

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

◆ ast_context_remove_switch2()

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

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

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

Definition at line 3476 of file pbx.c.

3477{
3478 int idx;
3479 int ret = -1;
3480
3481 ast_wrlock_context(con);
3482
3483 /* walk switches */
3484 for (idx = 0; idx < ast_context_switches_count(con); idx++) {
3485 struct ast_sw *i = AST_VECTOR_GET(&con->alts, idx);
3486
3487 if (!strcmp(ast_get_switch_name(i), sw) &&
3488 !strcmp(ast_get_switch_data(i), data) &&
3489 (!registrar || !strcmp(ast_get_switch_registrar(i), registrar))) {
3490
3491 /* found, remove from list */
3492 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
3493 AST_VECTOR_REMOVE_ORDERED(&con->alts, idx);
3494
3495 /* free switch and return */
3496 sw_free(i);
3497 ret = 0;
3498 break;
3499 }
3500 }
3501
3502 ast_unlock_context(con);
3503
3504 return ret;
3505}

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

Referenced by ast_context_remove_switch().

◆ ast_context_set_autohints()

void ast_context_set_autohints ( struct ast_context con,
int  enabled 
)

Enable or disable autohints support on a context.

Parameters
conpointer to the context
enabledwhether autohints are enabled

Definition at line 4626 of file pbx.c.

4627{
4628 con->autohints = enabled;
4629
4630 if (con->scope == AST_CONTEXT_SCOPE_GLOBAL) {
4631 if (con->autohints) {
4633 } else {
4635 }
4636 }
4637}
static int enabled
Definition dnsmgr.c:91
void pbx_extension_state_autohint_set(struct ast_context *context)

References AST_CONTEXT_SCOPE_GLOBAL, ast_context::autohints, enabled, pbx_extension_state_autohint_remove(), pbx_extension_state_autohint_set(), and ast_context::scope.

Referenced by pbx_load_config().

◆ ast_context_switches_count()

int ast_context_switches_count ( const struct ast_context con)

◆ ast_context_switches_get()

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

◆ ast_context_verify_includes()

int ast_context_verify_includes ( struct ast_context con)

Verifies includes in an ast_contect structure.

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

Definition at line 6890 of file pbx.c.

6891{
6892 int idx;
6893 int res = 0;
6894 int includecount = ast_context_includes_count(con);
6895
6896 if (includecount >= AST_PBX_MAX_STACK) {
6897 ast_log(LOG_WARNING, "Context %s contains too many includes (%d). Maximum is %d.\n",
6898 ast_get_context_name(con), includecount, AST_PBX_MAX_STACK);
6899 }
6900
6901 for (idx = 0; idx < includecount; idx++) {
6902 const struct ast_include *inc = ast_context_includes_get(con, idx);
6903
6904 if (ast_context_find(include_rname(inc))) {
6905 continue;
6906 }
6907
6908 res = -1;
6909 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
6911 break;
6912 }
6913
6914 return res;
6915}
#define AST_PBX_MAX_STACK
Definition extconf.h:225
const char * include_rname(const struct ast_include *inc)
Definition pbx_include.c:55

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

◆ ast_exists_extension()

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

Determine whether an extension exists.

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

Definition at line 2735 of file pbx.c.

2736{
2737 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
2738}

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

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

◆ ast_explicit_goto()

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

Definition at line 5223 of file pbx.c.

5224{
5225 if (!chan)
5226 return -1;
5227
5228 ast_channel_lock(chan);
5229
5231 ast_channel_unlock(chan);
5232 return -1;
5233 }
5234 if (!ast_strlen_zero(context))
5235 ast_channel_context_set(chan, context);
5236 if (!ast_strlen_zero(exten))
5237 ast_channel_exten_set(chan, exten);
5238 if (priority > -1) {
5239 /* see flag description in channel.h for explanation */
5241 --priority;
5242 }
5244 }
5245
5246 ast_channel_unlock(chan);
5247
5248 return 0;
5249}

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

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

◆ ast_extension_close()

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

Definition at line 2058 of file pbx.c.

2059{
2060 if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
2061 ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
2062 return extension_match_core(pattern, data, needmore);
2063}
static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
Definition pbx.c:2040

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

Referenced by lua_find_extension(), and realtime_switch_common().

◆ ast_extension_cmp()

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

Determine if one extension should match before another.

Parameters
aextension to compare with b
bextension to compare with a

Checks whether or extension a should match before extension b

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

Definition at line 1823 of file pbx.c.

1824{
1825 int cmp;
1826
1827 cmp = ext_cmp(a, b);
1828 if (cmp < 0) {
1829 return -1;
1830 }
1831 if (cmp > 0) {
1832 return 1;
1833 }
1834 return 0;
1835}
static struct test_val b
static struct test_val a

References a, b, and ext_cmp().

Referenced by lua_extension_cmp().

◆ ast_extension_match()

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

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

Parameters
patternpattern to match
extensionextension to check against the pattern.

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

Return values
1on match
0on failure

Definition at line 2053 of file pbx.c.

2054{
2055 return extension_match_core(pattern, extension, E_MATCH);
2056}

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

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

◆ ast_findlabel_extension()

int ast_findlabel_extension ( struct ast_channel c,
const char *  context,
const char *  exten,
const char *  label,
const char *  callerid 
)

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

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

Definition at line 2740 of file pbx.c.

2741{
2742 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
2743}
@ E_FINDLABEL
Definition extconf.h:220

References c, E_FINDLABEL, ast_exten::exten, ast_exten::label, NULL, and pbx_extension_helper().

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

◆ ast_findlabel_extension2()

int ast_findlabel_extension2 ( struct ast_channel c,
struct ast_context con,
const char *  exten,
const char *  label,
const char *  callerid 
)

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

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

Definition at line 2745 of file pbx.c.

2746{
2747 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
2748}

References c, E_FINDLABEL, ast_exten::exten, ast_exten::label, NULL, pbx_extension_helper(), and pbx_extension_helper().

Referenced by pbx_load_config().

◆ ast_get_context_name()

const char * ast_get_context_name ( struct ast_context con)

◆ ast_get_context_registrar()

const char * ast_get_context_registrar ( struct ast_context c)

Definition at line 6685 of file pbx.c.

6686{
6687 return c ? c->registrar : NULL;
6688}

References c, and NULL.

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

◆ ast_get_extension_app()

const char * ast_get_extension_app ( struct ast_exten e)

◆ ast_get_extension_app_data()

void * ast_get_extension_app_data ( struct ast_exten e)

◆ ast_get_extension_cidmatch()

const char * ast_get_extension_cidmatch ( struct ast_exten e)

◆ ast_get_extension_context()

struct ast_context * ast_get_extension_context ( struct ast_exten exten)

Definition at line 6662 of file pbx.c.

6663{
6664 return exten ? exten->parent : NULL;
6665}

References NULL, and ast_exten::parent.

Referenced by extension_is_compatible().

◆ ast_get_extension_data()

int ast_get_extension_data ( char *  buf,
int  bufsize,
struct ast_channel c,
const char *  context,
const char *  exten,
int  priority 
)

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

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

Definition at line 6725 of file pbx.c.

6727{
6728 struct ast_exten *e;
6729 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
6731 e = pbx_find_extension(c, NULL, &q, context, exten, priority, NULL, "", E_MATCH);
6732 if (e) {
6733 if (buf) {
6734 const char *tmp = ast_get_extension_app_data(e);
6735 if (tmp) {
6736 ast_copy_string(buf, tmp, bufsize);
6737 }
6738 }
6740 return 0;
6741 }
6743 return -1;
6744}
void * ast_get_extension_app_data(struct ast_exten *e)
Definition pbx.c:6720
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition pbx.c:2108

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

Referenced by eval_exten_read().

◆ ast_get_extension_label()

const char * ast_get_extension_label ( struct ast_exten exten)

Definition at line 6672 of file pbx.c.

6673{
6674 return exten ? exten->label : NULL;
6675}

References ast_exten::label, and NULL.

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

◆ ast_get_extension_matchcid()

int ast_get_extension_matchcid ( struct ast_exten e)

◆ ast_get_extension_name()

const char * ast_get_extension_name ( struct ast_exten exten)

◆ ast_get_extension_priority()

int ast_get_extension_priority ( struct ast_exten exten)

◆ ast_get_extension_registrar()

const char * ast_get_extension_registrar ( struct ast_exten e)

◆ ast_get_extension_registrar_file()

const char * ast_get_extension_registrar_file ( struct ast_exten e)

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

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

Definition at line 6695 of file pbx.c.

6696{
6697 return e ? e->registrar_file : NULL;
6698}

References NULL, and ast_exten::registrar_file.

Referenced by show_dialplan_helper_extension_output().

◆ ast_get_extension_registrar_line()

int ast_get_extension_registrar_line ( struct ast_exten e)

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

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

Definition at line 6700 of file pbx.c.

6701{
6702 return e ? e->registrar_line : 0;
6703}

References ast_exten::registrar_line.

Referenced by show_dialplan_helper_extension_output().

◆ ast_get_hint()

int ast_get_hint ( char *  hint,
int  hintsize,
char *  name,
int  namesize,
struct ast_channel c,
const char *  context,
const char *  exten 
)

Get hint for channel.

If an extension hint exists, return non-zero.

Definition at line 2697 of file pbx.c.

2698{
2699 struct ast_exten *e = ast_hint_extension(c, context, exten);
2700
2701 if (e) {
2702 if (hint)
2703 ast_copy_string(hint, ast_get_extension_app(e), hintsize);
2704 if (name) {
2705 const char *tmp = ast_get_extension_app_data(e);
2706 if (tmp)
2707 ast_copy_string(name, tmp, namesize);
2708 }
2709 return -1;
2710 }
2711 return 0;
2712}
const char * ast_get_extension_app(struct ast_exten *e)
Definition pbx.c:6715
static struct ast_exten * ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
Definition pbx.c:2644

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

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

◆ ast_goto_if_exists()

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

Definition at line 6939 of file pbx.c.

6940{
6941 return __ast_goto_if_exists(chan, context, exten, priority, 0);
6942}

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

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

◆ ast_hashtab_compare_contexts()

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

hashtable functions for contexts

Definition at line 337 of file pbx.c.

338{
339 const struct ast_context *ac = ah_a;
340 const struct ast_context *bc = ah_b;
341 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
342 return 1;
343 /* assume context names are registered in a string table! */
344 return strcmp(ac->name, bc->name);
345}
#define bc

References bc, and ast_context::name.

Referenced by ast_context_find_or_create().

◆ ast_hashtab_hash_contexts()

unsigned int ast_hashtab_hash_contexts ( const void *  obj)

Definition at line 389 of file pbx.c.

390{
391 const struct ast_context *ac = obj;
392 return ast_hashtab_hash_string(ac->name);
393}
unsigned int ast_hashtab_hash_string(const void *obj)
Hashes a string to a number.
Definition hashtab.c:153

References ast_hashtab_hash_string(), and ast_context::name.

Referenced by ast_context_find_or_create().

◆ ast_hint_extension()

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

Definition at line 2644 of file pbx.c.

2645{
2646 struct ast_exten *e;
2648 e = ast_hint_extension_nolock(c, context, exten);
2650 return e;
2651}
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:2638

References ast_hint_extension_nolock(), ast_rdlock_contexts(), ast_unlock_contexts(), c, and ast_exten::exten.

Referenced by ast_get_hint(), and ast_str_get_hint().

◆ ast_hint_extension_nolock()

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

Find hint for given extension in context.

Definition at line 2638 of file pbx.c.

2639{
2640 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
2641 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
2642}

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

Referenced by ast_hint_extension().

◆ ast_ignore_pattern()

int ast_ignore_pattern ( const char *  context,
const char *  pattern 
)

Checks to see if a number should be ignored.

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

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

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

Definition at line 5177 of file pbx.c.

5178{
5179 int ret = 0;
5180 struct ast_context *con;
5181
5183 con = ast_context_find(context);
5184 if (con) {
5185 int idx;
5186
5187 for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
5188 const struct ast_ignorepat *pat = ast_context_ignorepats_get(con, idx);
5189
5191 ret = 1;
5192 break;
5193 }
5194 }
5195 }
5197
5198 return ret;
5199}
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:2053
const char pattern[0]

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

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

◆ ast_matchmore_extension()

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

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

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

Definition at line 2755 of file pbx.c.

2756{
2757 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
2758}

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

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

◆ ast_merge_contexts_and_delete()

void ast_merge_contexts_and_delete ( struct ast_context **  extcontexts,
struct ast_hashtab exttable,
const char *  registrar 
)

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

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

Definition at line 4859 of file pbx.c.

4860{
4861 double ft;
4862 struct ast_context *tmp;
4863 struct ast_context *oldcontextslist;
4864 struct ast_hashtab *oldtable;
4865 struct ast_hashtab_iter *iter;
4866 int ctx_count = 0, promoted_count = 0;
4867 struct timeval begintime;
4868 struct timeval writelocktime;
4869 struct timeval endlocktime;
4870 struct timeval enddeltime;
4871
4872 begintime = ast_tvnow();
4874
4875 if (!contexts_table) {
4876 /* Well, that's odd. There are no contexts. */
4877 contexts_table = exttable;
4878 contexts = *extcontexts;
4879
4881 while ((tmp = ast_hashtab_next(iter))) {
4882 context_promote(tmp);
4883 }
4885
4887 return;
4888 }
4889
4891 while ((tmp = ast_hashtab_next(iter))) {
4892 ++ctx_count;
4893 context_merge(extcontexts, exttable, tmp, registrar);
4894 }
4896
4897 writelocktime = ast_tvnow();
4898
4899 /* save the old table and list */
4900 oldtable = contexts_table;
4901 oldcontextslist = contexts;
4902
4903 /* move in the new table and list */
4904 contexts_table = exttable;
4905 contexts = *extcontexts;
4906
4908 while ((tmp = ast_hashtab_next(iter))) {
4909 promoted_count += context_promote(tmp);
4910 }
4912
4913 /* ctx_count is still the number of old contexts before the merge,
4914 * use the new count when we tell the user how many contexts exist. */
4915 ctx_count = ast_hashtab_size(contexts_table);
4916
4918
4919 endlocktime = ast_tvnow();
4920
4921 /*
4922 * The old list and hashtab no longer are relevant, delete them
4923 * while the rest of asterisk is now freely using the new stuff
4924 * instead.
4925 */
4926
4927 ast_hashtab_destroy(oldtable, NULL);
4928
4929 for (tmp = oldcontextslist; tmp; ) {
4930 struct ast_context *next; /* next starting point */
4931
4932 next = tmp->next;
4934 tmp = next;
4935 }
4936 enddeltime = ast_tvnow();
4937
4938 ft = ast_tvdiff_us(writelocktime, begintime);
4939 ft /= 1000000.0;
4940 ast_verb(5,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
4941
4942 ft = ast_tvdiff_us(endlocktime, writelocktime);
4943 ft /= 1000000.0;
4944 ast_verb(5,"Time to promote contexts and swap in new dialplan: %8.6f sec\n", ft);
4945
4946 ft = ast_tvdiff_us(enddeltime, endlocktime);
4947 ft /= 1000000.0;
4948 ast_verb(5,"Time to delete the old dialplan: %8.6f sec\n", ft);
4949
4950 ft = ast_tvdiff_us(enddeltime, begintime);
4951 ft /= 1000000.0;
4952 ast_verb(5,"Total time merge_contexts_delete: %8.6f sec\n", ft);
4953 ast_verb(5, "%s successfully loaded %d contexts after incorporating %d promoted contexts (enable debug for details).\n",
4954 registrar, ctx_count, promoted_count);
4955}
static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
Definition pbx.c:4680
static int context_promote(struct ast_context *context)
Definition pbx.c:4812
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition time.h:87
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition time.h:159

References __ast_internal_context_destroy(), ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_size(), ast_hashtab_start_traversal, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), context_merge(), context_promote(), contexts, contexts_table, ast_context::next, NULL, and registrar.

◆ ast_parseable_goto()

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

Definition at line 7024 of file pbx.c.

7025{
7026 return pbx_parseable_goto(chan, goto_string, 0);
7027}

References pbx_parseable_goto().

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

◆ ast_pbx_h_exten_run()

void ast_pbx_h_exten_run ( struct ast_channel chan,
const char *  context 
)

Run the h exten from the given context.

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

Definition at line 2765 of file pbx.c.

2766{
2767 int autoloopflag;
2768 int found;
2769 int spawn_error;
2770
2771 ast_channel_lock(chan);
2772
2773 /*
2774 * Make sure that the channel is marked as hungup since we are
2775 * going to run the h exten on it.
2776 */
2778
2779 /* Set h exten location */
2780 if (context != ast_channel_context(chan)) {
2781 ast_channel_context_set(chan, context);
2782 }
2783 ast_channel_exten_set(chan, "h");
2784 ast_channel_priority_set(chan, 1);
2785
2786 /* Save autoloop flag */
2789 ast_channel_unlock(chan);
2790
2791 for (;;) {
2792 spawn_error = ast_spawn_extension(chan, ast_channel_context(chan),
2794 S_COR(ast_channel_caller(chan)->id.number.valid,
2795 ast_channel_caller(chan)->id.number.str, NULL), &found, 1);
2796
2797 ast_channel_lock(chan);
2798 if (spawn_error) {
2799 /* The code after the loop needs the channel locked. */
2800 break;
2801 }
2803 ast_channel_unlock(chan);
2804 }
2805 if (found && spawn_error) {
2806 /* Something bad happened, or a hangup has been requested. */
2807 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n",
2810 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n",
2813 }
2814
2815 /* An "h" exten has been run, so indicate that one has been run. */
2817
2818 /* Restore autoloop flag */
2820 ast_channel_unlock(chan);
2821}
@ AST_SOFTHANGUP_HANGUP_EXEC
Definition channel.h:1174

References ast_channel_caller(), ast_channel_context(), ast_channel_context_set(), ast_channel_exten(), ast_channel_exten_set(), ast_channel_flags(), ast_channel_lock, ast_channel_name(), ast_channel_priority(), ast_channel_priority_set(), ast_channel_unlock, ast_debug, AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, ast_set2_flag, ast_set_flag, AST_SOFTHANGUP_HANGUP_EXEC, ast_softhangup_nolock(), ast_spawn_extension(), ast_test_flag, ast_verb, NULL, and S_COR.

Referenced by __ast_pbx_run(), and ast_bridge_setup_after_goto().

◆ ast_pbx_init()

int ast_pbx_init ( void  )

Provided by pbx.c

Definition at line 7045 of file pbx.c.

7046{
7048 return 0;
7049}
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition clicompat.c:19
static void pbx_shutdown(void)
Definition pbx.c:7038

References ast_register_cleanup(), and pbx_shutdown().

Referenced by asterisk_daemon().

◆ ast_pbx_outgoing_app()

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

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

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

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

Definition at line 6262 of file pbx.c.

6267{
6268 return ast_pbx_outgoing_app_predial(type, cap, addr, timeout, app, appdata, reason, synchronous,
6269 cid_num, cid_name, vars, account, locked_channel, assignedids, NULL);
6270}
static const char app[]
static const char type[]
int ast_pbx_outgoing_app_predial(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, const struct ast_assigned_ids *assignedids, const char *predial_callee)
Definition pbx.c:6272

References app, ast_pbx_outgoing_app_predial(), NULL, and type.

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

◆ ast_pbx_outgoing_app_predial()

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

Definition at line 6272 of file pbx.c.

6277{
6278 if (reason) {
6279 *reason = 0;
6280 }
6281 if (locked_channel) {
6282 *locked_channel = NULL;
6283 }
6284 if (ast_strlen_zero(app)) {
6285 return -1;
6286 }
6287
6288 return pbx_outgoing_attempt(type, cap, addr, timeout, NULL, NULL, 0, app, appdata,
6289 reason, synchronous, cid_num, cid_name, vars, account, locked_channel, 0,
6290 assignedids, predial_callee);
6291}
static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids, const char *predial_callee)
Definition pbx.c:6002

References app, ast_strlen_zero(), NULL, pbx_outgoing_attempt(), and type.

Referenced by ast_pbx_outgoing_app(), and originate_exec().

◆ ast_pbx_outgoing_exten()

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

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

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

Definition at line 6198 of file pbx.c.

6203{
6204 return ast_pbx_outgoing_exten_predial(type, cap, addr, timeout, context, exten, priority, reason,
6205 synchronous, cid_num, cid_name, vars, account, locked_channel, early_media, assignedids, NULL);
6206}
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:6208

References ast_pbx_outgoing_exten_predial(), NULL, priority, and type.

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

◆ ast_pbx_outgoing_exten_predial()

int ast_pbx_outgoing_exten_predial ( const char *  type,
struct ast_format_cap cap,
const char *  addr,
int  timeout,
const char *  context,
const char *  exten,
int  priority,
int *  reason,
int  synchronous,
const char *  cid_num,
const char *  cid_name,
struct ast_variable vars,
const char *  account,
struct ast_channel **  locked_channel,
int  early_media,
const struct ast_assigned_ids assignedids,
const char *  predial_callee 
)
Todo:
XXX Not good. The channel name is not unique if more than one originate fails at a time.

Definition at line 6208 of file pbx.c.

6213{
6214 int res;
6215 int my_reason;
6216
6217 if (!reason) {
6218 reason = &my_reason;
6219 }
6220 *reason = 0;
6221 if (locked_channel) {
6222 *locked_channel = NULL;
6223 }
6224
6225 res = pbx_outgoing_attempt(type, cap, addr, timeout, context, exten, priority,
6226 NULL, NULL, reason, synchronous, cid_num, cid_name, vars, account, locked_channel,
6227 early_media, assignedids, predial_callee);
6228
6229 if (res < 0 /* Call failed to get connected for some reason. */
6230 && 0 < synchronous
6231 && ast_exists_extension(NULL, context, "failed", 1, NULL)) {
6232 struct ast_channel *failed;
6233
6234 /* We do not have to worry about a locked_channel if dialing failed. */
6235 ast_assert(!locked_channel || !*locked_channel);
6236
6237 /*!
6238 * \todo XXX Not good. The channel name is not unique if more than
6239 * one originate fails at a time.
6240 */
6241 failed = ast_channel_alloc(0, AST_STATE_DOWN, cid_num, cid_name, account,
6242 "failed", context, NULL, NULL, 0, "OutgoingSpoolFailed");
6243 if (failed) {
6244 char failed_reason[12];
6245
6246 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
6247 pbx_builtin_setvar_helper(failed, "REASON", failed_reason);
6248 ast_channel_unlock(failed);
6249 ast_set_variables(failed, vars);
6250
6251 if (ast_pbx_run(failed)) {
6252 ast_log(LOG_ERROR, "Unable to run PBX on '%s'\n",
6253 ast_channel_name(failed));
6254 ast_hangup(failed);
6255 }
6256 }
6257 }
6258
6259 return res;
6260}
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition channel.h:1299
void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars)
adds a list of channel variables to a channel
Definition channel.c:8291
@ AST_STATE_DOWN
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition pbx.c:3315

References ast_assert, ast_channel_alloc, ast_channel_name(), ast_channel_unlock, ast_exists_extension(), ast_hangup(), ast_log, ast_pbx_run(), ast_set_variables(), AST_STATE_DOWN, ast_channel::context, LOG_ERROR, NULL, pbx_builtin_setvar_helper(), pbx_outgoing_attempt(), priority, and type.

Referenced by action_originate(), ast_pbx_outgoing_exten(), and originate_exec().

◆ ast_pbx_run()

enum ast_pbx_result ast_pbx_run ( struct ast_channel c)

Execute the PBX in the current thread.

Parameters
cchannel to run the pbx on

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

Return values
Zeroon success
non-zeroon failure

Definition at line 3315 of file pbx.c.

3316{
3317 return ast_pbx_run_args(c, NULL);
3318}
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:3295

References ast_pbx_run_args(), c, and NULL.

Referenced by __analog_ss_thread(), analog_ss_thread(), ari_originate_dial(), ast_bridge_run_after_goto(), ast_pbx_outgoing_exten_predial(), do_notify(), pbx_outgoing_exec(), and unistim_ss().

◆ ast_pbx_run_args()

enum ast_pbx_result ast_pbx_run_args ( struct ast_channel c,
struct ast_pbx_args args 
)

Execute the PBX in the current thread.

Parameters
cchannel to run the pbx on
argsoptions for the pbx

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

Return values
Zeroon success
non-zeroon failure

Definition at line 3295 of file pbx.c.

3296{
3298
3299 if (!ast_fully_booted) {
3300 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
3301 return AST_PBX_FAILED;
3302 }
3303
3304 if (increase_call_count(c)) {
3305 return AST_PBX_CALL_LIMIT;
3306 }
3307
3308 res = __ast_pbx_run(c, args);
3309
3311
3312 return res;
3313}
#define ast_fully_booted
Definition options.h:127
static void decrease_call_count(void)
Definition pbx.c:3226
static int increase_call_count(const struct ast_channel *c)
Increase call count for channel.
Definition pbx.c:3177
static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c, struct ast_pbx_args *args)
Definition pbx.c:2866
ast_pbx_result
The result codes when starting the PBX on a channel with ast_pbx_start.
Definition pbx.h:372
@ AST_PBX_CALL_LIMIT
Definition pbx.h:375

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

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

◆ ast_pbx_start()

enum ast_pbx_result ast_pbx_start ( struct ast_channel c)

Create a new thread and start the PBX.

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

Definition at line 3268 of file pbx.c.

3269{
3270 pthread_t t;
3271
3272 if (!c) {
3273 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
3274 return AST_PBX_FAILED;
3275 }
3276
3277 if (!ast_fully_booted) {
3278 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
3279 return AST_PBX_FAILED;
3280 }
3281
3283 return AST_PBX_CALL_LIMIT;
3284
3285 /* Start a new thread, and get something handling this channel. */
3287 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
3289 return AST_PBX_FAILED;
3290 }
3291
3292 return AST_PBX_SUCCESS;
3293}
static void * pbx_thread(void *data)
Definition pbx.c:3248
#define ast_pthread_create_detached(a, b, c, d)
Definition utils.h:628

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

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

◆ ast_processed_calls()

int ast_processed_calls ( void  )

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

Definition at line 3325 of file pbx.c.

3326{
3327 return totalcalls;
3328}
static int totalcalls
Definition pbx.c:423

References totalcalls.

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

◆ ast_rdlock_context()

int ast_rdlock_context ( struct ast_context con)

Read locks a given context.

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

Definition at line 6644 of file pbx.c.

6645{
6646 return ast_rwlock_rdlock(&con->lock);
6647}
#define ast_rwlock_rdlock(a)
Definition lock.h:242

References ast_rwlock_rdlock, and ast_context::lock.

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

◆ ast_rdlock_contexts()

int ast_rdlock_contexts ( void  )

◆ ast_remove_hint()

static int ast_remove_hint ( struct ast_exten e)
static

Definition at line 2653 of file pbx.c.

2654{
2655 if (!e) {
2656 return -1;
2657 }
2658
2661 }
2662
2663 return 0;
2664}

References AST_CONTEXT_SCOPE_GLOBAL, ast_exten::parent, pbx_extension_state_hint_remove(), and ast_context::scope.

Referenced by destroy_exten().

◆ ast_spawn_extension()

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

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

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

This adds a new extension to the asterisk extension list.

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

Definition at line 2760 of file pbx.c.

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

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

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

◆ ast_str_get_hint()

int ast_str_get_hint ( struct ast_str **  hint,
ssize_t  hintsize,
struct ast_str **  name,
ssize_t  namesize,
struct ast_channel c,
const char *  context,
const char *  exten 
)

Get hint for channel.

If an extension hint exists, return non-zero.

Definition at line 2715 of file pbx.c.

2716{
2717 struct ast_exten *e = ast_hint_extension(c, context, exten);
2718
2719 if (!e) {
2720 return 0;
2721 }
2722
2723 if (hint) {
2724 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
2725 }
2726 if (name) {
2727 const char *tmp = ast_get_extension_app_data(e);
2728 if (tmp) {
2729 ast_str_set(name, namesize, "%s", tmp);
2730 }
2731 }
2732 return -1;
2733}
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

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

Referenced by ast_str_retrieve_variable().

◆ AST_THREADSTORAGE_CUSTOM_SCOPE()

AST_THREADSTORAGE_CUSTOM_SCOPE ( switch_data  ,
NULL  ,
ast_free_ptr  ,
static   
)

◆ ast_unlock_context()

int ast_unlock_context ( struct ast_context con)

◆ ast_unlock_contexts()

int ast_unlock_contexts ( void  )

Unlocks contexts.

Return values
0on success
-1on failure

Definition at line 6631 of file pbx.c.

6632{
6633 return ast_mutex_unlock(&conlock);
6634}
#define ast_mutex_unlock(a)
Definition lock.h:197

References ast_mutex_unlock, and conlock.

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

◆ ast_walk_context_extensions()

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

Definition at line 6754 of file pbx.c.

6756{
6757 if (!exten)
6758 return con ? con->root : NULL;
6759 else
6760 return exten->next;
6761}

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

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

◆ ast_walk_context_ignorepats()

const struct ast_ignorepat * ast_walk_context_ignorepats ( const struct ast_context con,
const struct ast_ignorepat ip 
)

Definition at line 6847 of file pbx.c.

6849{
6850 if (!con) {
6851 return NULL;
6852 }
6853
6854 if (ip) {
6855 int idx;
6856 int next = 0;
6857
6858 for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6859 const struct ast_ignorepat *i = ast_context_ignorepats_get(con, idx);
6860
6861 if (next) {
6862 return i;
6863 }
6864
6865 if (ip == i) {
6866 next = 1;
6867 }
6868 }
6869
6870 return NULL;
6871 }
6872
6873 if (!ast_context_ignorepats_count(con)) {
6874 return NULL;
6875 }
6876
6877 return ast_context_ignorepats_get(con, 0);
6878}
struct ast_ignorepat * next
Definition extconf.c:2386

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

◆ ast_walk_context_includes()

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

Definition at line 6808 of file pbx.c.

6810{
6811 if (inc) {
6812 int idx;
6813 int next = 0;
6814
6815 for (idx = 0; idx < ast_context_includes_count(con); idx++) {
6816 const struct ast_include *include = AST_VECTOR_GET(&con->includes, idx);
6817
6818 if (next) {
6819 return include;
6820 }
6821
6822 if (inc == include) {
6823 next = 1;
6824 }
6825 }
6826
6827 return NULL;
6828 }
6829
6830 if (!ast_context_includes_count(con)) {
6831 return NULL;
6832 }
6833
6834 return ast_context_includes_get(con, 0);
6835}
struct ast_include * next
Definition extconf.c:2368

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

Referenced by context_included().

◆ ast_walk_context_switches()

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

Definition at line 6763 of file pbx.c.

6765{
6766 if (sw) {
6767 int idx;
6768 int next = 0;
6769
6770 for (idx = 0; idx < ast_context_switches_count(con); idx++) {
6771 const struct ast_sw *s = ast_context_switches_get(con, idx);
6772
6773 if (next) {
6774 return s;
6775 }
6776
6777 if (sw == s) {
6778 next = 1;
6779 }
6780 }
6781
6782 return NULL;
6783 }
6784
6785 if (!ast_context_switches_count(con)) {
6786 return NULL;
6787 }
6788
6789 return ast_context_switches_get(con, 0);
6790}

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

◆ ast_walk_contexts()

struct ast_context * ast_walk_contexts ( struct ast_context con)

Definition at line 6749 of file pbx.c.

6750{
6751 return con ? con->next : contexts;
6752}

References contexts, contexts, and ast_context::next.

◆ ast_walk_extension_priorities()

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

◆ ast_wrlock_context()

int ast_wrlock_context ( struct ast_context con)

◆ ast_wrlock_contexts()

int ast_wrlock_contexts ( void  )

◆ candidate_exten_advance()

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

Definition at line 850 of file pbx.c.

851{
852 str++;
853 while (*str == '-') {
854 str++;
855 }
856 return str;
857}
const char * str
Definition app_jack.c:150

References str.

◆ cli_match_char_tree()

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

Definition at line 742 of file pbx.c.

743{
744 char extenstr[40];
745 struct ast_str *my_prefix = ast_str_alloca(1024);
746
747 extenstr[0] = '\0';
748
749 if (node->exten) {
750 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
751 }
752
753 if (strlen(node->x) > 1) {
754 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
755 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
756 node->exten ? node->exten->name : "", extenstr);
757 } else {
758 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
759 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
760 node->exten ? node->exten->name : "", extenstr);
761 }
762
763 ast_str_set(&my_prefix, 0, "%s+ ", prefix);
764
765 if (node->next_char)
766 cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd);
767
768 if (node->alt_char)
769 cli_match_char_tree(node->alt_char, prefix, fd);
770}
void ast_cli(int fd, const char *fmt,...)
Definition clicompat.c:6
static char prefix[MAX_PREFIX]
Definition http.c:145
static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
Definition pbx.c:742
#define ast_str_alloca(init_len)
Definition strings.h:848
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
Support for dynamic strings.
Definition strings.h:623

References ast_cli(), ast_str_alloca, ast_str_buffer(), ast_str_set(), cli_match_char_tree(), and prefix.

Referenced by cli_match_char_tree(), and show_debug_helper().

◆ collect_digits()

static int collect_digits ( struct ast_channel c,
int  waittime,
char *  buf,
int  buflen,
int  pos 
)
static

collect digits from the channel into the buffer.

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

Definition at line 2839 of file pbx.c.

2840{
2841 int digit;
2842
2843 buf[pos] = '\0'; /* make sure it is properly terminated */
2845 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
2846 /* As long as we're willing to wait, and as long as it's not defined,
2847 keep reading digits until we can't possibly get a right answer anymore. */
2848 digit = ast_waitfordigit(c, waittime);
2851 } else {
2852 if (!digit) /* No entry */
2853 break;
2854 if (digit < 0) /* Error, maybe a hangup */
2855 return -1;
2856 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
2857 buf[pos++] = digit;
2858 buf[pos] = '\0';
2859 }
2860 waittime = ast_channel_pbx(c)->dtimeoutms;
2861 }
2862 }
2863 return 0;
2864}
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition channel.c:3179

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

Referenced by __ast_pbx_run().

◆ compare_char()

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

Definition at line 328 of file pbx.c.

329{
330 const unsigned char *ac = a;
331 const unsigned char *bc = b;
332
333 return *ac - *bc;
334}

References a, b, and bc.

Referenced by get_pattern_node().

◆ complete_show_dialplan_context()

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

Definition at line 3793 of file pbx.c.

3795{
3796 struct ast_context *c = NULL;
3797 char *ret = NULL;
3798 int which = 0;
3799 int wordlen;
3800
3801 /* we are do completion of [exten@]context on second position only */
3802 if (pos != 2)
3803 return NULL;
3804
3806
3807 wordlen = strlen(word);
3808
3809 /* walk through all contexts and return the n-th match */
3810 while ( (c = ast_walk_contexts(c)) ) {
3811 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
3813 break;
3814 }
3815 }
3816
3818
3819 return ret;
3820}
#define ast_strdup(str)
A wrapper for strdup()
Definition astmm.h:241
short word

References ast_get_context_name(), ast_rdlock_contexts(), ast_strdup, ast_unlock_contexts(), ast_walk_contexts(), c, and NULL.

Referenced by handle_debug_dialplan(), and handle_show_dialplan().

◆ context_merge()

static void context_merge ( struct ast_context **  extcontexts,
struct ast_hashtab exttable,
struct ast_context context,
const char *  registrar 
)
static

Definition at line 4680 of file pbx.c.

4681{
4682 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
4683 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
4684 struct ast_hashtab_iter *exten_iter;
4685 struct ast_hashtab_iter *prio_iter;
4686 int insert_count = 0;
4687 int first = 1;
4688
4689 /* We'll traverse all the extensions/prios, and see which are not registrar'd with
4690 the current registrar, and copy them to the new context. If the new context does not
4691 exist, we'll create it "on demand". If no items are in this context to copy, then we'll
4692 only create the empty matching context if the old one meets the criteria */
4693
4694 if (context->root_table) {
4695 exten_iter = ast_hashtab_start_traversal(context->root_table);
4696 while ((exten_item=ast_hashtab_next(exten_iter))) {
4697 if (new) {
4698 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
4699 } else {
4700 new_exten_item = NULL;
4701 }
4702 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
4703 while ((prio_item=ast_hashtab_next(prio_iter))) {
4704 int res1;
4705 char *dupdstr;
4706
4707 if (new_exten_item) {
4708 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
4709 } else {
4710 new_prio_item = NULL;
4711 }
4712 if (strcmp(prio_item->registrar,registrar) == 0) {
4713 struct ast_exten *pattern_exten;
4714 struct pbx_find_info q = { .stacklen = 0 };
4715
4716 if (prio_item->priority != PRIORITY_HINT || prio_item->name[0] == '_' || new_prio_item || !new) {
4717 continue;
4718 }
4719
4720 /*
4721 * This hint no longer exists in the new context, but it may have been created as a result of
4722 * a pattern match so see if a pattern match matches it. If it does then we add it in to the new
4723 * context using the registrar of the pattern match.
4724 */
4725 pattern_exten = pbx_find_extension(NULL, new, &q, context->name,
4726 prio_item->name, PRIORITY_HINT, NULL, "", E_MATCH);
4727 if (pattern_exten && !strcmp(q.foundcontext, context->name)) {
4728 /*
4729 * This logic doesn't check whether it's a pattern match or not because if it was
4730 * an exact match we would have already skipped it above due to new_prio_item being
4731 * present. Logically it could only ever be a pattern match here.
4732 */
4733 dupdstr = ast_strdup(prio_item->data);
4734
4735 res1 = ast_add_extension2(new, 0, prio_item->name, prio_item->priority, prio_item->label,
4736 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, ast_free_ptr, prio_item->registrar,
4737 prio_item->registrar_file, prio_item->registrar_line);
4738 }
4739
4740 continue;
4741 }
4742 /* make sure the new context exists, so we have somewhere to stick this exten/prio */
4743 if (!new) {
4744 new = ast_context_find_or_create(extcontexts, exttable, context->name, prio_item->registrar); /* a new context created via priority from a different context in the old dialplan, gets its registrar from the prio's registrar */
4745 if (new) {
4746 new->autohints = context->autohints;
4747 if (new->autohints) {
4749 }
4750 new->scope = AST_CONTEXT_SCOPE_GLOBAL;
4751 }
4752 }
4753
4754 /* copy in the includes, switches, and ignorepats */
4755 if (first) { /* but, only need to do this once */
4757 first = 0;
4758 }
4759
4760 if (!new) {
4761 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
4762 ast_hashtab_end_traversal(prio_iter);
4763 ast_hashtab_end_traversal(exten_iter);
4764 return; /* no sense continuing. */
4765 }
4766 /* we will not replace existing entries in the new context with stuff from the old context.
4767 but, if this is because of some sort of registrar conflict, we ought to say something... */
4768
4769 dupdstr = ast_strdup(prio_item->data);
4770
4771 res1 = ast_add_extension2(new, 0, prio_item->name, prio_item->priority, prio_item->label,
4772 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, ast_free_ptr, prio_item->registrar,
4773 prio_item->registrar_file, prio_item->registrar_line);
4774 if (!res1 && new_exten_item && new_prio_item){
4775 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
4776 context->name, prio_item->name, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
4777 } else {
4778 /* we do NOT pass the priority data from the old to the new -- we pass a copy of it, so no changes to the current dialplan take place,
4779 and no double frees take place, either! */
4780 insert_count++;
4781 }
4782 }
4783 ast_hashtab_end_traversal(prio_iter);
4784 }
4785 ast_hashtab_end_traversal(exten_iter);
4786 } else if (new) {
4787 /* If the context existed but had no extensions, we still want to merge
4788 * the includes, switches and ignore patterns.
4789 */
4791 }
4792
4793 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
4794 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
4795 /* we could have given it the registrar of the other module who incremented the refcount,
4796 but that's not available, so we give it the registrar we know about */
4797 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
4798
4799 if (new) {
4800 new->autohints = context->autohints;
4801 if (new->autohints) {
4803 }
4804 new->scope = AST_CONTEXT_SCOPE_GLOBAL;
4805 }
4806
4807 /* copy in the includes, switches, and ignorepats */
4809 }
4810}
struct sla_ringing_trunk * first
Definition app_sla.c:338
void ast_free_ptr(void *ptr)
free() wrapper
Definition astmm.c:1739
static void context_merge_incls_swits_igps_other_registrars(struct ast_context *new, struct ast_context *old, const char *registrar)
Definition pbx.c:4641
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition pbx.c:4542
const char * foundcontext
Definition extconf.h:241

References ast_exten::app, ast_add_extension2(), ast_context_find_or_create(), AST_CONTEXT_SCOPE_GLOBAL, ast_free_ptr(), ast_hashtab_end_traversal(), ast_hashtab_lookup(), ast_hashtab_next(), ast_hashtab_start_traversal, ast_log, ast_strdup, ast_verb, ast_exten::cidmatch, context_merge_incls_swits_igps_other_registrars(), ast_exten::data, E_MATCH, first, pbx_find_info::foundcontext, ast_exten::label, LOG_ERROR, ast_exten::matchcid, ast_exten::name, NULL, pbx_extension_state_autohint_set(), pbx_find_extension(), ast_exten::peer_table, ast_exten::priority, PRIORITY_HINT, registrar, ast_exten::registrar, ast_exten::registrar_file, ast_exten::registrar_line, and pbx_find_info::stacklen.

Referenced by ast_merge_contexts_and_delete().

◆ context_merge_incls_swits_igps_other_registrars()

static void context_merge_incls_swits_igps_other_registrars ( struct ast_context new,
struct ast_context old,
const char *  registrar 
)
static

Definition at line 4641 of file pbx.c.

4642{
4643 int idx;
4644
4645 ast_debug(1, "merging incls/swits/igpats from old(%s) to new(%s) context, registrar = %s\n", ast_get_context_name(old), ast_get_context_name(new), registrar);
4646 /* copy in the includes, switches, and ignorepats */
4647 /* walk through includes */
4648 for (idx = 0; idx < ast_context_includes_count(old); idx++) {
4649 const struct ast_include *i = ast_context_includes_get(old, idx);
4650
4651 if (!strcmp(ast_get_include_registrar(i), registrar)) {
4652 continue; /* not mine */
4653 }
4655 }
4656
4657 /* walk through switches */
4658 for (idx = 0; idx < ast_context_switches_count(old); idx++) {
4659 const struct ast_sw *sw = ast_context_switches_get(old, idx);
4660
4661 if (!strcmp(ast_get_switch_registrar(sw), registrar)) {
4662 continue; /* not mine */
4663 }
4665 }
4666
4667 /* walk thru ignorepats ... */
4668 for (idx = 0; idx < ast_context_ignorepats_count(old); idx++) {
4669 const struct ast_ignorepat *ip = ast_context_ignorepats_get(old, idx);
4670
4671 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) {
4672 continue; /* not mine */
4673 }
4675 }
4676}
int ast_get_switch_eval(const struct ast_sw *sw)
Definition pbx_sw.c:58

References ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_ignorepats_count(), ast_context_ignorepats_get(), ast_context_includes_count(), ast_context_includes_get(), ast_context_switches_count(), ast_context_switches_get(), ast_debug, ast_get_context_name(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_eval(), ast_get_switch_name(), ast_get_switch_registrar(), and registrar.

Referenced by context_merge().

◆ context_promote()

static int context_promote ( struct ast_context context)
static

Definition at line 4812 of file pbx.c.

4813{
4814 struct ast_exten *exten_item, *prio_item;
4815 struct ast_hashtab_iter *exten_iter;
4816 struct ast_hashtab_iter *prio_iter;
4817
4818 /* Contexts already promoted to global have been handled previously, so skip */
4819 if (context->scope == AST_CONTEXT_SCOPE_GLOBAL) {
4820 return 0;
4821 }
4822
4823 /* Enable or remove autohints as needed */
4824 if (context->autohints) {
4826 } else {
4828 }
4829
4830 /* Further handling requires extensions to exist */
4831 if (!context->root_table) {
4832 return 0;
4833 }
4834
4835 /*
4836 * Hints are stateless but extension state is not. To keep extension state up to date
4837 * we go through all the hints on contexts promoted from local scope to global scope and
4838 * inform extension state as it is purely driven based on global scope dialplan.
4839 */
4840 exten_iter = ast_hashtab_start_traversal(context->root_table);
4841 while ((exten_item = ast_hashtab_next(exten_iter))) {
4842 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
4843 while ((prio_item = ast_hashtab_next(prio_iter))) {
4844 if (prio_item->priority != PRIORITY_HINT) {
4845 continue;
4846 }
4847 pbx_extension_state_hint_set(prio_item, context);
4848 }
4849 ast_hashtab_end_traversal(prio_iter);
4850 }
4851 ast_hashtab_end_traversal(exten_iter);
4852
4854
4855 return 1;
4856}

References AST_CONTEXT_SCOPE_GLOBAL, ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal, pbx_extension_state_autohint_remove(), pbx_extension_state_autohint_set(), pbx_extension_state_hint_set(), ast_exten::peer_table, ast_exten::priority, and PRIORITY_HINT.

Referenced by ast_merge_contexts_and_delete().

◆ create_match_char_tree()

static void create_match_char_tree ( struct ast_context con)
static

Definition at line 1396 of file pbx.c.

1397{
1398 struct ast_hashtab_iter *t1;
1399 struct ast_exten *e1;
1400#ifdef NEED_DEBUG
1401 int biggest_bucket, resizes, numobjs, numbucks;
1402
1403 ast_debug(1, "Creating Extension Trie for context %s(%p)\n", con->name, con);
1404 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
1405 ast_debug(1, "This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
1406 numobjs, numbucks, biggest_bucket, resizes);
1407#endif
1409 while ((e1 = ast_hashtab_next(t1))) {
1410 if (e1->exten) {
1411 add_exten_to_pattern_tree(con, e1, 0);
1412 } else {
1413 ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n");
1414 }
1415 }
1417}
void ast_hashtab_get_stats(struct ast_hashtab *tab, int *biggest_bucket_size, int *resize_count, int *num_objects, int *num_buckets)
Returns key stats for the table.
Definition hashtab.c:563

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

Referenced by pbx_find_extension().

◆ decrease_call_count()

static void decrease_call_count ( void  )
static

Definition at line 3226 of file pbx.c.

3227{
3229 if (countcalls > 0)
3230 countcalls--;
3232}
static ast_mutex_t maxcalllock
Definition pbx.c:421

References ast_mutex_lock, ast_mutex_unlock, countcalls, and maxcalllock.

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

◆ destroy_exten()

static void destroy_exten ( struct ast_exten e)
static

Definition at line 3234 of file pbx.c.

3235{
3236 if (e->priority == PRIORITY_HINT)
3237 ast_remove_hint(e);
3238
3239 if (e->peer_table)
3241 if (e->peer_label_table)
3243 if (e->datad)
3244 e->datad(e->data);
3245 ast_free(e);
3246}
static int ast_remove_hint(struct ast_exten *e)
Definition pbx.c:2653

References ast_free, ast_hashtab_destroy(), ast_remove_hint(), ast_exten::data, ast_exten::datad, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, and PRIORITY_HINT.

Referenced by __ast_internal_context_destroy(), and ast_context_remove_extension_callerid2().

◆ destroy_pattern_tree()

static void destroy_pattern_tree ( struct match_char pattern_tree)
static

Definition at line 1419 of file pbx.c.

1420{
1421 /* destroy all the alternates */
1422 if (pattern_tree->alt_char) {
1423 destroy_pattern_tree(pattern_tree->alt_char);
1424 pattern_tree->alt_char = 0;
1425 }
1426 /* destroy all the nexts */
1427 if (pattern_tree->next_char) {
1428 destroy_pattern_tree(pattern_tree->next_char);
1429 pattern_tree->next_char = 0;
1430 }
1431 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
1432 ast_free(pattern_tree);
1433}

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

Referenced by __ast_internal_context_destroy(), and destroy_pattern_tree().

◆ exception_store_free()

static void exception_store_free ( void *  data)
static

Definition at line 2409 of file pbx.c.

2410{
2411 struct pbx_exception *exception = data;
2413 ast_free(exception);
2414}
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object

References ast_free, and ast_string_field_free_memory.

◆ ext_cmp()

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

Definition at line 1766 of file pbx.c.

1767{
1768 /* Make sure non-pattern extens come first. */
1769 if (left[0] != '_') {
1770 if (right[0] == '_') {
1771 return -1;
1772 }
1773 /* Compare two non-pattern extens. */
1774 return ext_cmp_exten(left, right);
1775 }
1776 if (right[0] != '_') {
1777 return 1;
1778 }
1779
1780 /*
1781 * OK, we need full pattern sorting routine.
1782 *
1783 * Skip past the underscores
1784 */
1785 return ext_cmp_pattern(left + 1, right + 1);
1786}

References ext_cmp_exten(), and ext_cmp_pattern().

Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().

◆ ext_cmp_exten()

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

Definition at line 1516 of file pbx.c.

1517{
1518 int cmp;
1519
1520 for (;;) {
1521 /* Ignore '-' chars as eye candy fluff. */
1522 while (*left == '-') {
1523 ++left;
1524 }
1525 while (*right == '-') {
1526 ++right;
1527 }
1528
1529 cmp = *left - *right;
1530 if (cmp) {
1531 break;
1532 }
1533 if (!*left) {
1534 /*
1535 * Get here only if both strings ended at the same time. cmp
1536 * would be non-zero if only one string ended.
1537 */
1538 break;
1539 }
1540 ++left;
1541 ++right;
1542 }
1543 return cmp;
1544}

Referenced by _extension_match_core(), and ext_cmp().

◆ ext_cmp_exten_partial()

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

Definition at line 1473 of file pbx.c.

1474{
1475 int cmp;
1476
1477 for (;;) {
1478 /* Ignore '-' chars as eye candy fluff. */
1479 while (*left == '-') {
1480 ++left;
1481 }
1482 while (*right == '-') {
1483 ++right;
1484 }
1485
1486 if (!*right) {
1487 /*
1488 * Right ended first for partial match or both ended at the same
1489 * time for a match.
1490 */
1491 cmp = 0;
1492 break;
1493 }
1494
1495 cmp = *left - *right;
1496 if (cmp) {
1497 break;
1498 }
1499 ++left;
1500 ++right;
1501 }
1502 return cmp;
1503}

Referenced by _extension_match_core().

◆ ext_cmp_exten_strlen()

static int ext_cmp_exten_strlen ( const char *  str)
static

Definition at line 1443 of file pbx.c.

1444{
1445 int len;
1446
1447 len = 0;
1448 for (;;) {
1449 /* Ignore '-' chars as eye candy fluff. */
1450 while (*str == '-') {
1451 ++str;
1452 }
1453 if (!*str) {
1454 break;
1455 }
1456 ++str;
1457 ++len;
1458 }
1459 return len;
1460}
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

References len(), and str.

Referenced by _extension_match_core().

◆ ext_cmp_pattern()

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

Definition at line 1718 of file pbx.c.

1719{
1720 int cmp;
1721 int left_pos;
1722 int right_pos;
1723
1724 for (;;) {
1725 unsigned char left_bitwise[32] = { 0, };
1726 unsigned char right_bitwise[32] = { 0, };
1727
1728 left_pos = ext_cmp_pattern_pos(&left, left_bitwise);
1729 right_pos = ext_cmp_pattern_pos(&right, right_bitwise);
1730 cmp = left_pos - right_pos;
1731 if (!cmp) {
1732 /*
1733 * Are the character sets different, even though they score the same?
1734 *
1735 * Note: Must swap left and right to get the sense of the
1736 * comparison correct. Otherwise, we would need to multiply by
1737 * -1 instead.
1738 */
1739 cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise));
1740 }
1741 if (cmp) {
1742 break;
1743 }
1744 if (!left) {
1745 /*
1746 * Get here only if both patterns ended at the same time. cmp
1747 * would be non-zero if only one pattern ended.
1748 */
1749 break;
1750 }
1751 }
1752 return cmp;
1753}
static int ext_cmp_pattern_pos(const char **p, unsigned char *bitwise)
helper functions to sort extension patterns in the desired way, so that more specific patterns appear...
Definition pbx.c:1603

References ARRAY_LEN, and ext_cmp_pattern_pos().

Referenced by _extension_match_core(), and ext_cmp().

◆ ext_cmp_pattern_pos()

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

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

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

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

Definition at line 1603 of file pbx.c.

1604{
1605#define BITS_PER 8 /* Number of bits per unit (byte). */
1606 unsigned char c;
1607 unsigned char cmin;
1608 int count;
1609 const char *end;
1610
1611 do {
1612 /* Get character and advance. (Ignore '-' chars as eye candy fluff.) */
1613 do {
1614 c = *(*p)++;
1615 } while (c == '-');
1616
1617 /* always return unless we have a set of chars */
1618 switch (c) {
1619 default:
1620 /* ordinary character */
1621 bitwise[c / BITS_PER] = 1 << ((BITS_PER - 1) - (c % BITS_PER));
1622 return 0x0100 | c;
1623
1624 case 'n':
1625 case 'N':
1626 /* 2..9 */
1627 bitwise[6] = 0x3f;
1628 bitwise[7] = 0xc0;
1629 return 0x0800 | '2';
1630
1631 case 'x':
1632 case 'X':
1633 /* 0..9 */
1634 bitwise[6] = 0xff;
1635 bitwise[7] = 0xc0;
1636 return 0x0A00 | '0';
1637
1638 case 'z':
1639 case 'Z':
1640 /* 1..9 */
1641 bitwise[6] = 0x7f;
1642 bitwise[7] = 0xc0;
1643 return 0x0900 | '1';
1644
1645 case '.':
1646 /* wildcard */
1647 return 0x18000;
1648
1649 case '!':
1650 /* earlymatch */
1651 return 0x28000; /* less specific than '.' */
1652
1653 case '\0':
1654 /* empty string */
1655 *p = NULL;
1656 return 0x30000;
1657
1658 case '[':
1659 /* char set */
1660 break;
1661 }
1662 /* locate end of set */
1663 end = strchr(*p, ']');
1664
1665 if (!end) {
1666 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
1667 return 0x40000; /* XXX make this entry go last... */
1668 }
1669
1670 count = 0;
1671 cmin = 0xFF;
1672 for (; *p < end; ++*p) {
1673 unsigned char c1; /* first char in range */
1674 unsigned char c2; /* last char in range */
1675
1676 c1 = (*p)[0];
1677 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
1678 c2 = (*p)[2];
1679 *p += 2; /* skip a total of 3 chars */
1680 } else { /* individual character */
1681 c2 = c1;
1682 }
1683 if (c1 < cmin) {
1684 cmin = c1;
1685 }
1686 for (; c1 <= c2; ++c1) {
1687 unsigned char mask = 1 << ((BITS_PER - 1) - (c1 % BITS_PER));
1688
1689 /*
1690 * Note: If two character sets score the same, the one with the
1691 * lowest ASCII values will compare as coming first. Must fill
1692 * in most significant bits for lower ASCII values to accomplish
1693 * the desired sort order.
1694 */
1695 if (!(bitwise[c1 / BITS_PER] & mask)) {
1696 /* Add the character to the set. */
1697 bitwise[c1 / BITS_PER] |= mask;
1698 count += 0x100;
1699 }
1700 }
1701 }
1702 ++*p;
1703 } while (!count);/* While the char set was empty. */
1704 return count | cmin;
1705}
#define BITS_PER

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

Referenced by ext_cmp_pattern().

◆ ext_fluff_count()

static int ext_fluff_count ( const char *  exten)
static

Definition at line 1788 of file pbx.c.

1789{
1790 int fluff = 0;
1791
1792 if (*exten != '_') {
1793 /* not a pattern, simple check. */
1794 while (*exten) {
1795 if (*exten == '-') {
1796 fluff++;
1797 }
1798 exten++;
1799 }
1800
1801 return fluff;
1802 }
1803
1804 /* do pattern check */
1805 while (*exten) {
1806 if (*exten == '-') {
1807 fluff++;
1808 } else if (*exten == '[') {
1809 /* skip set, dashes here matter. */
1810 exten = strchr(exten, ']');
1811
1812 if (!exten) {
1813 /* we'll end up warning about this later, don't spam logs */
1814 return fluff;
1815 }
1816 }
1817 exten++;
1818 }
1819
1820 return fluff;
1821}

References ast_exten::exten.

Referenced by ast_add_extension2_lockopt().

◆ ext_strncpy()

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

Definition at line 5308 of file pbx.c.

5309{
5310 unsigned int count;
5311 unsigned int insquares;
5312 unsigned int is_pattern;
5313
5314 if (!dst_size--) {
5315 /* There really is no dst buffer */
5316 return 0;
5317 }
5318
5319 count = 0;
5320 insquares = 0;
5321 is_pattern = *src == '_';
5322 while (*src && count < dst_size) {
5323 if (*src == '[') {
5324 if (is_pattern) {
5325 insquares = 1;
5326 }
5327 } else if (*src == ']') {
5328 insquares = 0;
5329 } else if (*src == ' ' && !insquares) {
5330 ++src;
5331 continue;
5332 } else if (*src == '-' && !insquares && nofluff) {
5333 ++src;
5334 continue;
5335 }
5336 *dst++ = *src++;
5337 ++count;
5338 }
5339 *dst = '\0';
5340
5341 return count + 1;
5342}

Referenced by ast_add_extension2_lockopt(), and ast_context_remove_extension_callerid2().

◆ extension_match_core()

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

Definition at line 2040 of file pbx.c.

2041{
2042 int i;
2043 static int prof_id = -2; /* marker for 'unallocated' id */
2044 if (prof_id == -2) {
2045 prof_id = ast_add_profile("ext_match", 0);
2046 }
2047 ast_mark(prof_id, 1);
2048 i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode);
2049 ast_mark(prof_id, 0);
2050 return i;
2051}
int ast_add_profile(const char *, uint64_t scale)
support for event profiling
Definition astman.c:92
int64_t ast_mark(int, int start1_stop0)
Definition astman.c:103
static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
Definition pbx.c:1849

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

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

◆ find_context()

static struct ast_context * find_context ( const char *  context)
static

lookup for a context with a given name,

Return values
foundcontext or NULL if not found.

Definition at line 3360 of file pbx.c.

3361{
3362 struct ast_context item = {
3363 .name = context,
3364 };
3365
3367}

References ast_hashtab_lookup(), contexts_table, item, and aco_type::name.

Referenced by pbx_find_extension().

◆ find_context_locked()

static struct ast_context * find_context_locked ( const char *  context)
static

lookup for a context with a given name,

Return values
withconlock held if found.
NULLif not found.

Definition at line 3374 of file pbx.c.

3375{
3376 struct ast_context *c;
3377 struct ast_context item = {
3378 .name = context,
3379 };
3380
3383 if (!c) {
3385 }
3386
3387 return c;
3388}

References ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), c, contexts_table, item, and aco_type::name.

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

◆ get_canmatch_exten()

static struct ast_exten * get_canmatch_exten ( struct match_char node)
static

Definition at line 772 of file pbx.c.

773{
774 /* find the exten at the end of the rope */
775 struct match_char *node2 = node;
776
777 for (node2 = node; node2; node2 = node2->next_char) {
778 if (node2->exten) {
779#ifdef NEED_DEBUG_HERE
780 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten);
781#endif
782 return node2->exten;
783 }
784 }
785#ifdef NEED_DEBUG_HERE
786 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x);
787#endif
788 return 0;
789}

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

◆ get_pattern_node()

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

Definition at line 1144 of file pbx.c.

1145{
1146#define INC_DST_OVERFLOW_CHECK \
1147 do { \
1148 if (dst - node->buf < sizeof(node->buf) - 1) { \
1149 ++dst; \
1150 } else { \
1151 overflow = 1; \
1152 } \
1153 } while (0)
1154
1155 node->specif = 0;
1156 node->buf[0] = '\0';
1157 while (*src) {
1158 if (*src == '[' && pattern) {
1159 char *dst = node->buf;
1160 const char *src_next;
1161 int length;
1162 int overflow = 0;
1163
1164 /* get past the '[' */
1165 ++src;
1166 for (;;) {
1167 if (*src == '\\') {
1168 /* Escaped character. */
1169 ++src;
1170 if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') {
1171 *dst = *src++;
1173 }
1174 } else if (*src == '-') {
1175 unsigned char first;
1176 unsigned char last;
1177
1178 src_next = src;
1179 first = *(src_next - 1);
1180 last = *++src_next;
1181
1182 if (last == '\\') {
1183 /* Escaped character. */
1184 last = *++src_next;
1185 }
1186
1187 /* Possible char range. */
1188 if (node->buf[0] && last) {
1189 /* Expand the char range. */
1190 while (++first <= last) {
1191 *dst = first;
1193 }
1194 src = src_next + 1;
1195 } else {
1196 /*
1197 * There was no left or right char for the range.
1198 * It is just a '-'.
1199 */
1200 *dst = *src++;
1202 }
1203 } else if (*src == '\0') {
1205 "A matching ']' was not found for '[' in exten pattern '%s'\n",
1206 extenbuf);
1207 break;
1208 } else if (*src == ']') {
1209 ++src;
1210 break;
1211 } else {
1212 *dst = *src++;
1214 }
1215 }
1216 /* null terminate the exploded range */
1217 *dst = '\0';
1218
1219 if (overflow) {
1221 "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n",
1222 extenbuf);
1223 node->buf[0] = '\0';
1224 continue;
1225 }
1226
1227 /* Sort the characters in character set. */
1228 length = strlen(node->buf);
1229 if (!length) {
1230 ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n",
1231 extenbuf);
1232 node->buf[0] = '\0';
1233 continue;
1234 }
1235 qsort(node->buf, length, 1, compare_char);
1236
1237 /* Remove duplicate characters from character set. */
1238 dst = node->buf;
1239 src_next = node->buf;
1240 while (*src_next++) {
1241 if (*dst != *src_next) {
1242 *++dst = *src_next;
1243 }
1244 }
1245
1246 length = strlen(node->buf);
1247 length <<= 8;
1248 node->specif = length | (unsigned char) node->buf[0];
1249 break;
1250 } else if (*src == '-') {
1251 /* Skip dashes in all extensions. */
1252 ++src;
1253 } else {
1254 if (*src == '\\') {
1255 /*
1256 * XXX The escape character here does not remove any special
1257 * meaning to characters except the '[', '\\', and '-'
1258 * characters since they are special only in this function.
1259 */
1260 node->buf[0] = *++src;
1261 if (!node->buf[0]) {
1262 break;
1263 }
1264 } else {
1265 node->buf[0] = *src;
1266 if (pattern) {
1267 /* make sure n,x,z patterns are canonicalized to N,X,Z */
1268 if (node->buf[0] == 'n') {
1269 node->buf[0] = 'N';
1270 } else if (node->buf[0] == 'x') {
1271 node->buf[0] = 'X';
1272 } else if (node->buf[0] == 'z') {
1273 node->buf[0] = 'Z';
1274 }
1275 }
1276 }
1277 node->buf[1] = '\0';
1278 node->specif = 1;
1279 ++src;
1280 break;
1281 }
1282 }
1283 return src;
1284
1285#undef INC_DST_OVERFLOW_CHECK
1286}
struct sla_ringing_trunk * last
Definition app_sla.c:338
static int compare_char(const void *a, const void *b)
Definition pbx.c:328
#define INC_DST_OVERFLOW_CHECK

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

Referenced by add_exten_to_pattern_tree().

◆ handle_debug_dialplan()

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

Send ack once.

Definition at line 4145 of file pbx.c.

4146{
4147 char *exten = NULL, *context = NULL;
4148 /* Variables used for different counters */
4149 struct dialplan_counters counters;
4150 const char *incstack[AST_PBX_MAX_STACK];
4151
4152 switch (cmd) {
4153 case CLI_INIT:
4154 e->command = "dialplan debug";
4155 e->usage =
4156 "Usage: dialplan debug [context]\n"
4157 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
4158 return NULL;
4159 case CLI_GENERATE:
4160 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
4161 }
4162
4163 memset(&counters, 0, sizeof(counters));
4164
4165 if (a->argc != 2 && a->argc != 3)
4166 return CLI_SHOWUSAGE;
4167
4168 /* we obtain [exten@]context? if yes, split them ... */
4169 /* note: we ignore the exten totally here .... */
4170 if (a->argc == 3) {
4171 if (strchr(a->argv[2], '@')) { /* split into exten & context */
4172 context = ast_strdupa(a->argv[2]);
4173 exten = strsep(&context, "@");
4174 /* change empty strings to NULL */
4175 if (ast_strlen_zero(exten))
4176 exten = NULL;
4177 } else { /* no '@' char, only context given */
4178 context = ast_strdupa(a->argv[2]);
4179 }
4180 if (ast_strlen_zero(context))
4181 context = NULL;
4182 }
4183 /* else Show complete dial plan, context and exten are NULL */
4184 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
4185
4186 /* check for input failure and throw some error messages */
4187 if (context && !counters.context_existence) {
4188 ast_cli(a->fd, "There is no existence of '%s' context\n", context);
4189 return CLI_FAILURE;
4190 }
4191
4192
4193 ast_cli(a->fd,"-= %d %s. =-\n",
4194 counters.total_context, counters.total_context == 1 ? "context" : "contexts");
4195
4196 /* everything ok */
4197 return CLI_SUCCESS;
4198}
char * strsep(char **str, const char *delims)
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#define CLI_SHOWUSAGE
Definition cli.h:45
#define CLI_SUCCESS
Definition cli.h:44
@ CLI_INIT
Definition cli.h:152
@ CLI_GENERATE
Definition cli.h:153
#define CLI_FAILURE
Definition cli.h:46
static char * complete_show_dialplan_context(const char *line, const char *word, int pos, int state)
Definition pbx.c:3793
static int show_debug_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
Definition pbx.c:4023
char * command
Definition cli.h:186
const char * usage
Definition cli.h:177
Counters for the show dialplan manager command.
Definition pbx.c:3823

References a, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), dialplan_counters::context_existence, NULL, show_debug_helper(), strsep(), dialplan_counters::total_context, and ast_cli_entry::usage.

◆ handle_set_extenpatternmatchnew()

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

Definition at line 4451 of file pbx.c.

4452{
4453 int oldval = 0;
4454
4455 switch (cmd) {
4456 case CLI_INIT:
4457 e->command = "dialplan set extenpatternmatchnew true";
4458 e->usage =
4459 "Usage: dialplan set extenpatternmatchnew true|false\n"
4460 " Use the NEW extension pattern matching algorithm, true or false.\n";
4461 return NULL;
4462 case CLI_GENERATE:
4463 return NULL;
4464 }
4465
4466 if (a->argc != 4)
4467 return CLI_SHOWUSAGE;
4468
4469 oldval = pbx_set_extenpatternmatchnew(1);
4470
4471 if (oldval)
4472 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
4473 else
4474 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
4475
4476 return CLI_SUCCESS;
4477}
int pbx_set_extenpatternmatchnew(int newval)
Definition pbx.c:3337

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

◆ handle_show_dialplan()

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

Definition at line 4078 of file pbx.c.

4079{
4080 char *exten = NULL, *context = NULL;
4081 /* Variables used for different counters */
4082 struct dialplan_counters counters;
4083 const char *incstack[AST_PBX_MAX_STACK];
4084
4085 switch (cmd) {
4086 case CLI_INIT:
4087 e->command = "dialplan show";
4088 e->usage =
4089 "Usage: dialplan show [[exten@]context]\n"
4090 " Show dialplan\n";
4091 return NULL;
4092 case CLI_GENERATE:
4093 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
4094 }
4095
4096 memset(&counters, 0, sizeof(counters));
4097
4098 if (a->argc != 2 && a->argc != 3)
4099 return CLI_SHOWUSAGE;
4100
4101 /* we obtain [exten@]context? if yes, split them ... */
4102 if (a->argc == 3) {
4103 if (strchr(a->argv[2], '@')) { /* split into exten & context */
4104 context = ast_strdupa(a->argv[2]);
4105 exten = strsep(&context, "@");
4106 /* change empty strings to NULL */
4107 if (ast_strlen_zero(exten))
4108 exten = NULL;
4109 } else { /* no '@' char, only context given */
4110 context = ast_strdupa(a->argv[2]);
4111 }
4112 if (ast_strlen_zero(context))
4113 context = NULL;
4114 }
4115 /* else Show complete dial plan, context and exten are NULL */
4116 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
4117
4118 /* check for input failure and throw some error messages */
4119 if (context && !counters.context_existence) {
4120 ast_cli(a->fd, "There is no existence of '%s' context\n", context);
4121 return CLI_FAILURE;
4122 }
4123
4124 if (exten && !counters.extension_existence) {
4125 if (context)
4126 ast_cli(a->fd, "There is no existence of %s@%s extension\n",
4127 exten, context);
4128 else
4129 ast_cli(a->fd,
4130 "There is no existence of '%s' extension in all contexts\n",
4131 exten);
4132 return CLI_FAILURE;
4133 }
4134
4135 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
4136 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
4137 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
4138 counters.total_context, counters.total_context == 1 ? "context" : "contexts");
4139
4140 /* everything ok */
4141 return CLI_SUCCESS;
4142}
static int show_dialplan_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, const struct ast_include *rinclude, int includecount, const char *includes[])
Definition pbx.c:3862
int total_context
Definition pbx.c:3825

References a, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), dialplan_counters::context_existence, dialplan_counters::extension_existence, NULL, show_dialplan_helper(), strsep(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_prio, and ast_cli_entry::usage.

◆ handle_unset_extenpatternmatchnew()

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

Definition at line 4479 of file pbx.c.

4480{
4481 int oldval = 0;
4482
4483 switch (cmd) {
4484 case CLI_INIT:
4485 e->command = "dialplan set extenpatternmatchnew false";
4486 e->usage =
4487 "Usage: dialplan set extenpatternmatchnew true|false\n"
4488 " Use the NEW extension pattern matching algorithm, true or false.\n";
4489 return NULL;
4490 case CLI_GENERATE:
4491 return NULL;
4492 }
4493
4494 if (a->argc != 4)
4495 return CLI_SHOWUSAGE;
4496
4497 oldval = pbx_set_extenpatternmatchnew(0);
4498
4499 if (!oldval)
4500 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
4501 else
4502 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
4503
4504 return CLI_SUCCESS;
4505}

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

◆ hashtab_compare_exten_labels()

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

Definition at line 382 of file pbx.c.

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

References bc, ast_exten::label, and S_OR.

Referenced by ast_add_extension2_lockopt().

◆ hashtab_compare_exten_numbers()

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

Definition at line 375 of file pbx.c.

376{
377 const struct ast_exten *ac = ah_a;
378 const struct ast_exten *bc = ah_b;
379 return ac->priority != bc->priority;
380}

References bc, and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

◆ hashtab_compare_extens()

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

Definition at line 347 of file pbx.c.

348{
349 const struct ast_exten *ac = ah_a;
350 const struct ast_exten *bc = ah_b;
351 int x = strcmp(ac->exten, bc->exten);
352 if (x) { /* if exten names are diff, then return */
353 return x;
354 }
355
356 /* but if they are the same, do the cidmatch values match? */
357 /* not sure which side may be using ast_ext_matchcid_types, so check both */
358 if (ac->matchcid == AST_EXT_MATCHCID_ANY || bc->matchcid == AST_EXT_MATCHCID_ANY) {
359 return 0;
360 }
361 if (ac->matchcid == AST_EXT_MATCHCID_OFF && bc->matchcid == AST_EXT_MATCHCID_OFF) {
362 return 0;
363 }
364 if (ac->matchcid != bc->matchcid) {
365 return 1;
366 }
367 /* all other cases already disposed of, match now required on callerid string (cidmatch) */
368 /* although ast_add_extension2_lockopt() enforces non-zero ptr, caller may not have */
369 if (ast_strlen_zero(ac->cidmatch) && ast_strlen_zero(bc->cidmatch)) {
370 return 0;
371 }
372 return strcmp(ac->cidmatch, bc->cidmatch);
373}

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

Referenced by ast_add_extension2_lockopt().

◆ hashtab_hash_extens()

static unsigned int hashtab_hash_extens ( const void *  obj)
static

Definition at line 395 of file pbx.c.

396{
397 const struct ast_exten *ac = obj;
398 unsigned int x = ast_hashtab_hash_string(ac->exten);
399 unsigned int y = 0;
400 if (ac->matchcid == AST_EXT_MATCHCID_ON)
402 return x+y;
403}

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

Referenced by ast_add_extension2_lockopt().

◆ hashtab_hash_labels()

static unsigned int hashtab_hash_labels ( const void *  obj)
static

Definition at line 411 of file pbx.c.

412{
413 const struct ast_exten *ac = obj;
414 return ast_hashtab_hash_string(S_OR(ac->label, ""));
415}

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

Referenced by ast_add_extension2_lockopt().

◆ hashtab_hash_priority()

static unsigned int hashtab_hash_priority ( const void *  obj)
static

Definition at line 405 of file pbx.c.

406{
407 const struct ast_exten *ac = obj;
408 return ast_hashtab_hash_int(ac->priority);
409}
unsigned int ast_hashtab_hash_int(const int num)
Definition hashtab.c:205

References ast_hashtab_hash_int(), and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

◆ increase_call_count()

static int increase_call_count ( const struct ast_channel c)
static

Increase call count for channel.

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

Definition at line 3177 of file pbx.c.

3178{
3179 int failed = 0;
3180 double curloadavg;
3181#if defined(HAVE_SYSINFO)
3182 struct sysinfo sys_info;
3183#endif
3184
3186 if (ast_option_maxcalls) {
3188 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", ast_option_maxcalls, ast_channel_name(c));
3189 failed = -1;
3190 }
3191 }
3192 if (ast_option_maxload) {
3193 getloadavg(&curloadavg, 1);
3194 if (curloadavg >= ast_option_maxload) {
3195 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", ast_option_maxload, ast_channel_name(c), curloadavg);
3196 failed = -1;
3197 }
3198 }
3199#if defined(HAVE_SYSINFO)
3200 if (option_minmemfree) {
3201 /* Make sure that the free system memory is above the configured low watermark */
3202 if (!sysinfo(&sys_info)) {
3203 /* Convert the amount of available RAM from mem_units to MB. The calculation
3204 * was done this way to avoid overflow problems */
3205 uint64_t curfreemem = sys_info.freeram + sys_info.bufferram;
3206 curfreemem *= sys_info.mem_unit;
3207 curfreemem /= 1024 * 1024;
3208 if (curfreemem < option_minmemfree) {
3209 ast_log(LOG_WARNING, "Available system memory (~%" PRIu64 "MB) is below the configured low watermark (%ldMB)\n",
3210 curfreemem, option_minmemfree);
3211 failed = -1;
3212 }
3213 }
3214 }
3215#endif
3216
3217 if (!failed) {
3218 countcalls++;
3219 totalcalls++;
3220 }
3222
3223 return failed;
3224}
int getloadavg(double *list, int nelem)
int ast_option_maxcalls
Definition options.c:80
double ast_option_maxload
Definition options.c:78
long option_minmemfree
Definition options.c:87

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

Referenced by ast_pbx_run_args(), and ast_pbx_start().

◆ insert_in_next_chars_alt_char_list()

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

Definition at line 1049 of file pbx.c.

1050{
1051 struct match_char *curr, *lcurr;
1052
1053 /* insert node into the tree at "current", so the alt_char list from current is
1054 sorted in increasing value as you go to the leaves */
1055 if (!(*parent_ptr)) {
1056 *parent_ptr = node;
1057 return;
1058 }
1059
1060 if ((*parent_ptr)->specificity > node->specificity) {
1061 /* insert at head */
1062 node->alt_char = (*parent_ptr);
1063 *parent_ptr = node;
1064 return;
1065 }
1066
1067 lcurr = *parent_ptr;
1068 for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
1069 if (curr->specificity > node->specificity) {
1070 node->alt_char = curr;
1071 lcurr->alt_char = node;
1072 break;
1073 }
1074 lcurr = curr;
1075 }
1076
1077 if (!curr) {
1078 lcurr->alt_char = node;
1079 }
1080
1081}

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

Referenced by add_pattern_node().

◆ load_pbx()

int load_pbx ( void  )

Provided by pbx.c

Definition at line 6594 of file pbx.c.

6595{
6596 int res = 0;
6597
6599
6600 /* Initialize the PBX */
6601 ast_verb(1, "Asterisk PBX Core Initializing\n");
6602
6603 ast_verb(5, "Registering builtin functions:\n");
6607
6608 /* Register manager application */
6610
6611 if (res) {
6612 return -1;
6613 }
6614
6615 return 0;
6616}
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition cli.h:265
#define EVENT_FLAG_REPORTING
Definition manager.h:84
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition manager.h:204
#define EVENT_FLAG_CONFIG
Definition manager.h:82
static int manager_show_dialplan(struct mansession *s, const struct message *m)
Manager listing of dial plan.
Definition pbx.c:4365
static void unload_pbx(void)
Definition pbx.c:6586
static struct ast_custom_function testtime_function
Definition pbx.c:6563
static struct ast_cli_entry pbx_cli[]
Definition pbx.c:4510
static struct ast_custom_function exception_function
Definition pbx.c:2493
int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
Register a custom function.

References __ast_custom_function_register(), ARRAY_LEN, ast_cli_register_multiple, ast_manager_register_xml_core, ast_register_cleanup(), ast_verb, EVENT_FLAG_CONFIG, EVENT_FLAG_REPORTING, exception_function, manager_show_dialplan(), NULL, pbx_cli, testtime_function, and unload_pbx().

Referenced by asterisk_daemon().

◆ manager_dpsendack()

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

Send ack once.

Definition at line 4201 of file pbx.c.

4202{
4203 astman_send_listack(s, m, "DialPlan list will follow", "start");
4204}
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition manager.c:2042

References astman_send_listack().

Referenced by manager_show_dialplan(), and manager_show_dialplan_helper().

◆ manager_show_dialplan()

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

Manager listing of dial plan.

Definition at line 4365 of file pbx.c.

4366{
4367 const char *exten, *context;
4368 const char *id = astman_get_header(m, "ActionID");
4369 const char *incstack[AST_PBX_MAX_STACK];
4370 char idtext[256];
4371
4372 /* Variables used for different counters */
4373 struct dialplan_counters counters;
4374
4375 if (!ast_strlen_zero(id))
4376 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
4377 else
4378 idtext[0] = '\0';
4379
4380 memset(&counters, 0, sizeof(counters));
4381
4382 exten = astman_get_header(m, "Extension");
4383 context = astman_get_header(m, "Context");
4384
4385 manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL, 0, incstack);
4386
4387 if (!ast_strlen_zero(context) && !counters.context_existence) {
4388 char errorbuf[BUFSIZ];
4389
4390 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
4391 astman_send_error(s, m, errorbuf);
4392 return 0;
4393 }
4394 if (!ast_strlen_zero(exten) && !counters.extension_existence) {
4395 char errorbuf[BUFSIZ];
4396
4397 if (!ast_strlen_zero(context))
4398 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
4399 else
4400 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
4401 astman_send_error(s, m, errorbuf);
4402 return 0;
4403 }
4404
4405 if (!counters.total_items) {
4406 manager_dpsendack(s, m);
4407 }
4408
4409 astman_send_list_complete_start(s, m, "ShowDialPlanComplete", counters.total_items);
4410 astman_append(s,
4411 "ListExtensions: %d\r\n"
4412 "ListPriorities: %d\r\n"
4413 "ListContexts: %d\r\n",
4414 counters.total_exten, counters.total_prio, counters.total_context);
4416
4417 /* everything ok */
4418 return 0;
4419}
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition manager.c:2000
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition manager.c:2078
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition manager.c:1661
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition manager.c:2086
void astman_append(struct mansession *s, const char *fmt,...)
Definition manager.c:1921
static void manager_dpsendack(struct mansession *s, const struct message *m)
Send ack once.
Definition pbx.c:4201
static int manager_show_dialplan_helper(struct mansession *s, const struct message *m, const char *actionidtext, const char *context, const char *exten, struct dialplan_counters *dpc, const struct ast_include *rinclude, int includecount, const char *includes[])
Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dial...
Definition pbx.c:4210

References AST_PBX_MAX_STACK, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_send_list_complete_end(), astman_send_list_complete_start(), dialplan_counters::context_existence, dialplan_counters::extension_existence, manager_dpsendack(), manager_show_dialplan_helper(), NULL, dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.

Referenced by load_pbx().

◆ manager_show_dialplan_helper()

static int manager_show_dialplan_helper ( struct mansession s,
const struct message m,
const char *  actionidtext,
const char *  context,
const char *  exten,
struct dialplan_counters dpc,
const struct ast_include rinclude,
int  includecount,
const char *  includes[] 
)
static

Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dialplan. Must check whether the difference is intentional or not.

Definition at line 4210 of file pbx.c.

4215{
4216 struct ast_context *c;
4217 int res = 0, old_total_exten = dpc->total_exten;
4218
4219 if (ast_strlen_zero(exten))
4220 exten = NULL;
4221 if (ast_strlen_zero(context))
4222 context = NULL;
4223
4224 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
4225
4226 /* try to lock contexts */
4227 if (ast_rdlock_contexts()) {
4228 astman_send_error(s, m, "Failed to lock contexts");
4229 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
4230 return -1;
4231 }
4232
4233 c = NULL; /* walk all contexts ... */
4234 while ( (c = ast_walk_contexts(c)) ) {
4235 int idx;
4236 struct ast_exten *e;
4237
4238 if (context && strcmp(ast_get_context_name(c), context) != 0)
4239 continue; /* not the name we want */
4240
4241 dpc->context_existence = 1;
4242 dpc->total_context++;
4243
4244 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
4245
4246 if (ast_rdlock_context(c)) { /* failed to lock */
4247 ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
4248 continue;
4249 }
4250
4251 /* XXX note- an empty context is not printed */
4252 e = NULL; /* walk extensions in context */
4253 while ( (e = ast_walk_context_extensions(c, e)) ) {
4254 struct ast_exten *p;
4255
4256 /* looking for extension? is this our extension? */
4258 /* not the one we are looking for, continue */
4259 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
4260 continue;
4261 }
4262 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
4263
4264 dpc->extension_existence = 1;
4265
4266 dpc->total_exten++;
4267
4268 p = NULL; /* walk next extension peers */
4269 while ( (p = ast_walk_extension_priorities(e, p)) ) {
4270 int prio = ast_get_extension_priority(p);
4271
4272 dpc->total_prio++;
4273 if (!dpc->total_items++)
4274 manager_dpsendack(s, m);
4275 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
4276 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
4277
4278 /* XXX maybe make this conditional, if p != e ? */
4280 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
4281
4282 if (prio == PRIORITY_HINT) {
4283 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
4284 } else {
4285 astman_append(s, "Priority: %d\r\nApplication: %s\r\nAppData: %s\r\n", prio, ast_get_extension_app(p), (char *) ast_get_extension_app_data(p));
4286 }
4287 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
4288 }
4289 }
4290
4291 for (idx = 0; idx < ast_context_includes_count(c); idx++) {
4292 const struct ast_include *i = ast_context_includes_get(c, idx);
4293
4294 if (exten) {
4295 /* Check all includes for the requested extension */
4296 if (includecount >= AST_PBX_MAX_STACK) {
4297 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
4298 } else {
4299 int dupe = 0;
4300 int x;
4301 for (x = 0; x < includecount; x++) {
4302 if (!strcasecmp(includes[x], ast_get_include_name(i))) {
4303 dupe++;
4304 break;
4305 }
4306 }
4307 if (!dupe) {
4308 includes[includecount] = ast_get_include_name(i);
4309 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
4310 } else {
4311 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
4312 }
4313 }
4314 } else {
4315 if (!dpc->total_items++)
4316 manager_dpsendack(s, m);
4317 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
4318 astman_append(s, "Context: %s\r\nIncludeContext: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_include_name(i), ast_get_include_registrar(i));
4319 astman_append(s, "\r\n");
4320 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
4321 }
4322 }
4323
4324 for (idx = 0; idx < ast_context_ignorepats_count(c); idx++) {
4325 const struct ast_ignorepat *ip = ast_context_ignorepats_get(c, idx);
4326 const char *ipname = ast_get_ignorepat_name(ip);
4327 char ignorepat[AST_MAX_EXTENSION];
4328
4329 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
4330 if (!exten || ast_extension_match(ignorepat, exten)) {
4331 if (!dpc->total_items++)
4332 manager_dpsendack(s, m);
4333 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
4334 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
4335 astman_append(s, "\r\n");
4336 }
4337 }
4338 if (!rinclude) {
4339 for (idx = 0; idx < ast_context_switches_count(c); idx++) {
4340 const struct ast_sw *sw = ast_context_switches_get(c, idx);
4341
4342 if (!dpc->total_items++)
4343 manager_dpsendack(s, m);
4344 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
4345 astman_append(s, "Context: %s\r\nSwitch: %s/%s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_switch_name(sw), ast_get_switch_data(sw), ast_get_switch_registrar(sw));
4346 astman_append(s, "\r\n");
4347 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
4348 }
4349 }
4350
4352 }
4354
4355 if (dpc->total_exten == old_total_exten) {
4356 ast_debug(3, "manager_show_dialplan: Found nothing new\n");
4357 /* Nothing new under the sun */
4358 return -1;
4359 } else {
4360 return res;
4361 }
4362}
int ast_get_extension_priority(struct ast_exten *exten)
Definition pbx.c:6677
const char * ast_get_extension_label(struct ast_exten *exten)
Definition pbx.c:6672
struct ast_exten * ast_walk_extension_priorities(struct ast_exten *exten, struct ast_exten *priority)
Definition pbx.c:6802
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *exten)
Definition pbx.c:6754
const char * ast_get_extension_name(struct ast_exten *exten)
Definition pbx.c:6667
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition pbx.c:6644
const char * ast_get_extension_registrar(struct ast_exten *e)
Definition pbx.c:6690
int context_existence
Definition pbx.c:3828
int extension_existence
Definition pbx.c:3829

References ast_context_ignorepats_count(), ast_context_ignorepats_get(), ast_context_includes_count(), ast_context_includes_get(), ast_context_switches_count(), ast_context_switches_get(), ast_debug, ast_extension_match(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_app_data(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_priority(), ast_get_extension_registrar(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_log, AST_MAX_EXTENSION, AST_PBX_MAX_STACK, ast_rdlock_context(), ast_rdlock_contexts(), ast_strlen_zero(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), astman_append(), astman_send_error(), c, dialplan_counters::context_existence, ast_exten::exten, dialplan_counters::extension_existence, LOG_WARNING, manager_dpsendack(), manager_show_dialplan_helper(), NULL, PRIORITY_HINT, dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.

Referenced by manager_show_dialplan(), and manager_show_dialplan_helper().

◆ matchcid()

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

Definition at line 2096 of file pbx.c.

2097{
2098 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
2099 failing to get a number should count as a match, otherwise not */
2100
2101 if (ast_strlen_zero(callerid)) {
2102 return ast_strlen_zero(cidpattern) ? 1 : 0;
2103 }
2104
2105 return ast_extension_match(cidpattern, callerid);
2106}

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

◆ new_find_extension()

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

Definition at line 862 of file pbx.c.

863{
864 struct match_char *p; /* note minimal stack storage requirements */
865 struct ast_exten pattern = { .label = label };
866#ifdef DEBUG_THIS
867 if (tree)
868 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action));
869 else
870 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action));
871#endif
872 for (p = tree; p; p = p->alt_char) {
873 if (p->is_pattern) {
874 if (p->x[0] == 'N') {
875 if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
876#define NEW_MATCHER_CHK_MATCH \
877 if (p->exten && !MORE(str)) { /* if a shorter pattern matches along the way, might as well report it */ \
878 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \
879 update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \
880 if (!p->deleted) { \
881 if (action == E_FINDLABEL) { \
882 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \
883 ast_debug(4, "Found label in preferred extension\n"); \
884 return; \
885 } \
886 } else { \
887 ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->name); \
888 return; /* the first match, by definition, will be the best, because of the sorted tree */ \
889 } \
890 } \
891 } \
892 }
893
894#define NEW_MATCHER_RECURSE \
895 if (p->next_char && (MORE(str) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \
896 || p->next_char->x[0] == '!')) { \
897 if (MORE(str) || p->next_char->x[0] == '!') { \
898 new_find_extension(ADVANCE(str), score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
899 if (score->exten) { \
900 ast_debug(4 ,"returning an exact match-- %s\n", score->exten->name); \
901 return; /* the first match is all we need */ \
902 } \
903 } else { \
904 new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
905 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \
906 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->name : \
907 "NULL"); \
908 return; /* the first match is all we need */ \
909 } \
910 } \
911 } else if ((p->next_char || action == E_CANMATCH) && !MORE(str)) { \
912 score->canmatch = 1; \
913 score->canmatch_exten = get_canmatch_exten(p); \
914 if (action == E_CANMATCH || action == E_MATCHMORE) { \
915 ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \
916 return; \
917 } \
918 }
919
922 }
923 } else if (p->x[0] == 'Z') {
924 if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
927 }
928 } else if (p->x[0] == 'X') {
929 if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
932 }
933 } else if (p->x[0] == '.' && p->x[1] == 0) {
934 /* how many chars will the . match against? */
935 int i = 0;
936 const char *str2 = str;
937 while (*str2 && *str2 != '/') {
938 str2++;
939 i++;
940 }
941 if (p->exten && *str2 != '/') {
942 update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p);
943 if (score->exten) {
944 ast_debug(4, "return because scoreboard has a match with '/'--- %s\n",
945 score->exten->name);
946 return; /* the first match is all we need */
947 }
948 }
949 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
950 new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action);
951 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
952 ast_debug(4, "return because scoreboard has exact match OR "
953 "CANMATCH/MATCHMORE & canmatch set--- %s\n",
954 score->exten ? score->exten->name : "NULL");
955 return; /* the first match is all we need */
956 }
957 }
958 } else if (p->x[0] == '!' && p->x[1] == 0) {
959 /* how many chars will the . match against? */
960 int i = 1;
961 const char *str2 = str;
962 while (*str2 && *str2 != '/') {
963 str2++;
964 i++;
965 }
966 if (p->exten && *str2 != '/') {
967 update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p);
968 if (score->exten) {
969 ast_debug(4, "return because scoreboard has a '!' match--- %s\n",
970 score->exten->name);
971 return; /* the first match is all we need */
972 }
973 }
974 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
975 new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action);
976 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
977 ast_debug(4, "return because scoreboard has exact match OR "
978 "CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n",
979 score->exten ? score->exten->name : "NULL");
980 return; /* the first match is all we need */
981 }
982 }
983 } else if (p->x[0] == '/' && p->x[1] == 0) {
984 /* the pattern in the tree includes the cid match! */
985 if (p->next_char && callerid && *callerid) {
986 new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action);
987 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
988 ast_debug(4, "return because scoreboard has exact match OR "
989 "CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n",
990 score->exten ? score->exten->name : "NULL");
991 return; /* the first match is all we need */
992 }
993 }
994 } else if (strchr(p->x, *str)) {
995 ast_debug(4, "Nothing strange about this match\n");
998 }
999 } else if (strchr(p->x, *str)) {
1000 ast_debug(4, "Nothing strange about this match\n");
1003 }
1004 }
1005 ast_debug(4, "return at end of func\n");
1006}
static void update_scoreboard(struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node)
Definition pbx.c:695
static void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action)
Definition pbx.c:862
#define NEW_MATCHER_RECURSE
#define NEW_MATCHER_CHK_MATCH
int canmatch
Definition pbx.c:247
struct ast_exten * exten
Definition pbx.c:250

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

Referenced by new_find_extension(), and pbx_find_extension().

◆ pbx_checkcondition()

int pbx_checkcondition ( const char *  condition)

Evaluate a condition.

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

Definition at line 6568 of file pbx.c.

6569{
6570 int res;
6571 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */
6572 return 0;
6573 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
6574 return res;
6575 } else { /* Strings are true */
6576 return 1;
6577 }
6578}

References ast_strlen_zero().

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

◆ pbx_destroy()

static void pbx_destroy ( struct ast_pbx p)
static

Definition at line 616 of file pbx.c.

617{
618 ast_free(p);
619}

References ast_free.

Referenced by __ast_pbx_run().

◆ pbx_dial_reason()

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

Attempt to convert disconnect cause to old originate reason.

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

Definition at line 5963 of file pbx.c.

5964{
5965 enum ast_control_frame_type pbx_reason;
5966
5967 if (dial_result == AST_DIAL_RESULT_ANSWERED) {
5968 /* Remote end answered. */
5969 pbx_reason = AST_CONTROL_ANSWER;
5970 } else if (dial_result == AST_DIAL_RESULT_HANGUP) {
5971 /* Caller hungup */
5972 pbx_reason = AST_CONTROL_HANGUP;
5973 } else {
5974 switch (cause) {
5976 pbx_reason = AST_CONTROL_BUSY;
5977 break;
5984 pbx_reason = AST_CONTROL_CONGESTION;
5985 break;
5988 /* Remote end was ringing (but isn't anymore) */
5989 pbx_reason = AST_CONTROL_RINGING;
5990 break;
5992 default:
5993 /* Call Failure (not BUSY, and not NO_ANSWER, maybe Circuit busy or down?) */
5994 pbx_reason = 0;
5995 break;
5996 }
5997 }
5998
5999 return pbx_reason;
6000}
#define AST_CAUSE_SWITCH_CONGESTION
Definition causes.h:123
#define AST_CAUSE_UNALLOCATED
Definition causes.h:98
#define AST_CAUSE_DESTINATION_OUT_OF_ORDER
Definition causes.h:115
#define AST_CAUSE_NORMAL_TEMPORARY_FAILURE
Definition causes.h:122
#define AST_CAUSE_NORMAL_CIRCUIT_CONGESTION
Definition causes.h:120
#define AST_CAUSE_CALL_REJECTED
Definition causes.h:111
#define AST_CAUSE_NETWORK_OUT_OF_ORDER
Definition causes.h:121
#define AST_CAUSE_ANSWERED_ELSEWHERE
Definition causes.h:114
#define AST_CAUSE_NO_ANSWER
Definition causes.h:109
#define AST_CAUSE_USER_BUSY
Definition causes.h:107
@ AST_DIAL_RESULT_HANGUP
Definition dial.h:63
@ AST_DIAL_RESULT_ANSWERED
Definition dial.h:61
ast_control_frame_type
Internal control frame subtype field values.
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_ANSWER
@ AST_CONTROL_RINGING
@ AST_CONTROL_HANGUP

References AST_CAUSE_ANSWERED_ELSEWHERE, AST_CAUSE_CALL_REJECTED, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_UNALLOCATED, AST_CAUSE_USER_BUSY, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, AST_DIAL_RESULT_ANSWERED, and AST_DIAL_RESULT_HANGUP.

Referenced by pbx_outgoing_attempt().

◆ pbx_extension_helper()

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

The return value depends on the action:

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

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

Definition at line 2516 of file pbx.c.

2519{
2520 struct ast_exten *e;
2521 struct ast_app *app;
2522 char *substitute = NULL;
2523 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
2524 char passdata[EXT_DATA_SIZE];
2525 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
2526
2528
2529 if (!context) {
2530 context = con->name;
2531 }
2532
2533 if (found)
2534 *found = 0;
2535
2536 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
2537 if (e) {
2538 if (found)
2539 *found = 1;
2540 if (matching_action) {
2542 return -1; /* success, we found it */
2543 } else if (action == E_FINDLABEL) { /* map the label to a priority */
2544 int res = e->priority;
2545
2547
2548 /* the priority we were looking for */
2549 return res;
2550 } else { /* spawn */
2551 if (!e->cached_app)
2552 e->cached_app = pbx_findapp(e->app);
2553 app = e->cached_app;
2554 if (ast_strlen_zero(e->data)) {
2555 *passdata = '\0';
2556 } else {
2557 const char *tmp;
2558 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
2559 /* no variables to substitute, copy on through */
2560 ast_copy_string(passdata, e->data, sizeof(passdata));
2561 } else {
2562 /* save e->data on stack for later processing after lock released */
2563 substitute = ast_strdupa(e->data);
2564 }
2565 }
2567 if (!app) {
2568 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
2569 return -1;
2570 }
2574 return 0;
2575 }
2576 if (ast_channel_context(c) != context)
2577 ast_channel_context_set(c, context);
2578 if (ast_channel_exten(c) != exten)
2579 ast_channel_exten_set(c, exten);
2582 if (substitute) {
2583 pbx_substitute_variables_helper(c, substitute, passdata, sizeof(passdata)-1);
2584 }
2585 ast_debug(1, "Launching '%s'\n", app_name(app));
2586 if (VERBOSITY_ATLEAST(3)) {
2587 ast_verb(3, "Executing [%s@%s:%d] " COLORIZE_FMT "(\"" COLORIZE_FMT "\", \"" COLORIZE_FMT "\") %s\n",
2588 exten, context, priority,
2591 COLORIZE(COLOR_BRMAGENTA, 0, passdata),
2592 "in new stack");
2593 }
2594 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */
2595 }
2596 } else if (q.swo) { /* not found here, but in another switch */
2597 if (found)
2598 *found = 1;
2600 if (matching_action) {
2601 return -1;
2602 } else {
2603 if (!q.swo->exec) {
2604 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
2605 return -1;
2606 }
2607 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
2608 }
2609 } else { /* not found anywhere, see what happened */
2611 /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
2612 switch (q.status) {
2613 case STATUS_NO_CONTEXT:
2614 if (!matching_action && !combined_find_spawn)
2615 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
2616 break;
2618 if (!matching_action && !combined_find_spawn)
2619 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
2620 break;
2621 case STATUS_NO_PRIORITY:
2622 if (!matching_action && !combined_find_spawn)
2623 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
2624 break;
2625 case STATUS_NO_LABEL:
2626 if (context && !combined_find_spawn)
2627 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", S_OR(label, ""), exten, S_OR(context, ""));
2628 break;
2629 default:
2630 ast_debug(1, "Shouldn't happen!\n");
2631 }
2632
2633 return (matching_action) ? 0 : -1;
2634 }
2635}
#define VERBOSITY_ATLEAST(level)
#define STATUS_NO_LABEL
Definition pbx.c:2093
#define STATUS_NO_EXTENSION
Definition pbx.c:2091
#define STATUS_NO_CONTEXT
Definition pbx.c:2090
#define EXT_DATA_SIZE
Definition pbx.c:182
#define STATUS_NO_PRIORITY
Definition pbx.c:2092
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition pbx_app.c:483
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition ael_main.c:165
const char * app_name(struct ast_app *app)
Definition pbx_app.c:475
ast_app: A registered application
Definition pbx_app.c:45
struct ast_app * cached_app
Definition pbx.c:217
ast_switch_f * exec
Definition pbx.h:169
const char * name
Definition pbx.h:164
struct ast_switch * swo
Definition extconf.h:239
const char * data
Definition extconf.h:240
#define COLOR_BRCYAN
Definition term.h:63
#define COLORIZE(fg, bg, str)
Definition term.h:72
#define COLORIZE_FMT
Shortcut macros for coloring a set of text.
Definition term.h:71
#define COLOR_BRMAGENTA
Definition term.h:61

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

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

◆ pbx_find_extension()

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

Definition at line 2108 of file pbx.c.

2112{
2113 int x, res;
2114 struct ast_context *tmp = NULL;
2115 struct ast_exten *e = NULL, *eroot = NULL;
2116 struct ast_exten pattern = {NULL, };
2117 struct scoreboard score = {0, };
2118 struct ast_str *tmpdata = NULL;
2119 int idx;
2120
2121 pattern.label = label;
2122 pattern.priority = priority;
2123#ifdef NEED_DEBUG_HERE
2124 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
2125#endif
2126
2127 /* Initialize status if appropriate */
2128 if (q->stacklen == 0) {
2130 q->swo = NULL;
2131 q->data = NULL;
2132 q->foundcontext = NULL;
2133 } else if (q->stacklen >= AST_PBX_MAX_STACK) {
2134 ast_log(LOG_WARNING, "Maximum PBX stack (%d) exceeded. Too many includes?\n", AST_PBX_MAX_STACK);
2135 return NULL;
2136 }
2137
2138 /* Check first to see if we've already been checked */
2139 for (x = 0; x < q->stacklen; x++) {
2140 if (!strcasecmp(q->incstack[x], context))
2141 return NULL;
2142 }
2143
2144 if (bypass) { /* bypass means we only look there */
2145 tmp = bypass;
2146 } else { /* look in contexts */
2147 tmp = find_context(context);
2148 if (!tmp) {
2149 return NULL;
2150 }
2151 }
2152
2153 if (q->status < STATUS_NO_EXTENSION)
2155
2156 /* Do a search for matching extension */
2157
2158 eroot = NULL;
2159 score.total_specificity = 0;
2160 score.exten = 0;
2161 score.total_length = 0;
2162 if (!tmp->pattern_tree && tmp->root_table) {
2164#ifdef NEED_DEBUG
2165 ast_debug(1, "Tree Created in context %s:\n", context);
2166 log_match_char_tree(tmp->pattern_tree," ");
2167#endif
2168 }
2169#ifdef NEED_DEBUG
2170 ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
2171 log_match_char_tree(tmp->pattern_tree, ":: ");
2172#endif
2173
2174 do {
2176 char *osw = ast_strdupa(overrideswitch), *name;
2177 struct ast_switch *asw;
2178 ast_switch_f *aswf = NULL;
2179 char *datap;
2180 int eval = 0;
2181
2182 name = strsep(&osw, "/");
2183 asw = pbx_findswitch(name);
2184
2185 if (!asw) {
2186 ast_log(LOG_WARNING, "No such switch '%s'\n", name);
2187 break;
2188 }
2189
2190 if (osw && strchr(osw, '$')) {
2191 eval = 1;
2192 }
2193
2194 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
2195 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n");
2196 break;
2197 } else if (eval) {
2198 /* Substitute variables now */
2199 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
2200 datap = ast_str_buffer(tmpdata);
2201 } else {
2202 datap = osw;
2203 }
2204
2205 /* equivalent of extension_match_core() at the switch level */
2206 if (action == E_CANMATCH)
2207 aswf = asw->canmatch;
2208 else if (action == E_MATCHMORE)
2209 aswf = asw->matchmore;
2210 else /* action == E_MATCH */
2211 aswf = asw->exists;
2212 if (!aswf) {
2213 res = 0;
2214 } else {
2215 if (chan) {
2217 }
2218 res = aswf(chan, context, exten, priority, callerid, datap);
2219 if (chan) {
2221 }
2222 }
2223 if (res) { /* Got a match */
2224 q->swo = asw;
2225 q->data = datap;
2226 q->foundcontext = context;
2227 /* XXX keep status = STATUS_NO_CONTEXT ? */
2228 return NULL;
2229 }
2230 }
2231 } while (0);
2232
2234 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
2235 eroot = score.exten;
2236
2237 if (score.last_char == '!' && action == E_MATCHMORE) {
2238 /* We match an extension ending in '!'.
2239 * The decision in this case is final and is NULL (no match).
2240 */
2241#ifdef NEED_DEBUG_HERE
2242 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
2243#endif
2244 return NULL;
2245 }
2246
2247 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
2249#ifdef NEED_DEBUG_HERE
2250 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
2251#endif
2252 return score.canmatch_exten;
2253 }
2254
2255 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) {
2256 if (score.node) {
2257 struct ast_exten *z = trie_find_next_match(score.node);
2258 if (z) {
2259#ifdef NEED_DEBUG_HERE
2260 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
2261#endif
2262 } else {
2263 if (score.canmatch_exten) {
2264#ifdef NEED_DEBUG_HERE
2265 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
2266#endif
2267 return score.canmatch_exten;
2268 } else {
2269#ifdef NEED_DEBUG_HERE
2270 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
2271#endif
2272 }
2273 }
2274 return z;
2275 }
2276#ifdef NEED_DEBUG_HERE
2277 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
2278#endif
2279 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */
2280 }
2281
2282 if (eroot) {
2283 /* found entry, now look for the right priority */
2284 if (q->status < STATUS_NO_PRIORITY)
2286 e = NULL;
2287 if (action == E_FINDLABEL && label ) {
2288 if (q->status < STATUS_NO_LABEL)
2290 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
2291 } else {
2292 e = ast_hashtab_lookup(eroot->peer_table, &pattern);
2293 }
2294 if (e) { /* found a valid match */
2296 q->foundcontext = context;
2297#ifdef NEED_DEBUG_HERE
2298 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
2299#endif
2300 return e;
2301 }
2302 }
2303 } else { /* the old/current default exten pattern match algorithm */
2304
2305 /* scan the list trying to match extension and CID */
2306 eroot = NULL;
2307 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
2308 int match = extension_match_core(eroot->exten, exten, action);
2309 /* 0 on fail, 1 on match, 2 on earlymatch */
2310
2311 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
2312 continue; /* keep trying */
2313 if (match == 2 && action == E_MATCHMORE) {
2314 /* We match an extension ending in '!'.
2315 * The decision in this case is final and is NULL (no match).
2316 */
2317 return NULL;
2318 }
2319 /* found entry, now look for the right priority */
2320 if (q->status < STATUS_NO_PRIORITY)
2322 e = NULL;
2323 if (action == E_FINDLABEL && label ) {
2324 if (q->status < STATUS_NO_LABEL)
2326 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
2327 } else {
2328 e = ast_hashtab_lookup(eroot->peer_table, &pattern);
2329 }
2330 if (e) { /* found a valid match */
2332 q->foundcontext = context;
2333 return e;
2334 }
2335 }
2336 }
2337
2338 /* Check alternative switches */
2339 for (idx = 0; idx < ast_context_switches_count(tmp); idx++) {
2340 const struct ast_sw *sw = ast_context_switches_get(tmp, idx);
2342 ast_switch_f *aswf = NULL;
2343 const char *datap;
2344
2345 if (!asw) {
2346 ast_log(LOG_WARNING, "No such switch '%s'\n", ast_get_switch_name(sw));
2347 continue;
2348 }
2349
2350 /* Substitute variables now */
2351 if (ast_get_switch_eval(sw)) {
2352 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
2353 ast_log(LOG_WARNING, "Can't evaluate switch?!\n");
2354 continue;
2355 }
2357 ast_str_buffer(tmpdata), ast_str_size(tmpdata));
2358 datap = ast_str_buffer(tmpdata);
2359 } else {
2360 datap = ast_get_switch_data(sw);
2361 }
2362
2363 /* equivalent of extension_match_core() at the switch level */
2364 if (action == E_CANMATCH)
2365 aswf = asw->canmatch;
2366 else if (action == E_MATCHMORE)
2367 aswf = asw->matchmore;
2368 else /* action == E_MATCH */
2369 aswf = asw->exists;
2370 if (!aswf)
2371 res = 0;
2372 else {
2373 if (chan)
2375 res = aswf(chan, context, exten, priority, callerid, datap);
2376 if (chan)
2378 }
2379 if (res) { /* Got a match */
2380 q->swo = asw;
2381 q->data = datap;
2382 q->foundcontext = context;
2383 /* XXX keep status = STATUS_NO_CONTEXT ? */
2384 return NULL;
2385 }
2386 }
2387 /* Technically we should be using tmp->name here, but if we used that we
2388 * would have to cast away the constness of the 'name' pointer and I do
2389 * not want to do that. */
2390 q->incstack[q->stacklen++] = tmp->data; /* Setup the stack */
2391 /* Now try any includes we have in this context */
2392 for (idx = 0; idx < ast_context_includes_count(tmp); idx++) {
2393 const struct ast_include *i = ast_context_includes_get(tmp, idx);
2394
2395 if (include_valid(i)) {
2396 if ((e = pbx_find_extension(chan, bypass, q, include_rname(i), exten, priority, label, callerid, action))) {
2397#ifdef NEED_DEBUG_HERE
2398 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
2399#endif
2400 return e;
2401 }
2402 if (q->swo)
2403 return NULL;
2404 }
2405 }
2406 return NULL;
2407}
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition chan_iax2.c:2401
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
static struct ast_exten * trie_find_next_match(struct match_char *node)
Definition pbx.c:791
static int extenpatternmatchnew
Definition pbx.c:418
static void create_match_char_tree(struct ast_context *con)
Definition pbx.c:1396
static char * overrideswitch
Definition pbx.c:419
static int matchcid(const char *cidpattern, const char *callerid)
Definition pbx.c:2096
static struct ast_context * find_context(const char *context)
lookup for a context with a given name,
Definition pbx.c:3360
#define STATUS_SUCCESS
Definition pbx.c:2094
int() ast_switch_f(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
All switch functions have the same interface, so define a type for them.
Definition pbx.h:158
int include_valid(const struct ast_include *inc)
Definition pbx_include.c:65
struct ast_switch * pbx_findswitch(const char *sw)
Definition pbx_switch.c:40
size_t attribute_pure ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition strings.h:742
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition strings.h:909
ast_switch_f * canmatch
Definition pbx.h:168
ast_switch_f * exists
Definition pbx.h:167
ast_switch_f * matchmore
Definition pbx.h:170
char * incstack[AST_PBX_MAX_STACK]
Definition extconf.h:236
int total_length
Definition pbx.c:245
int total_specificity
Definition pbx.c:244
char last_char
Definition pbx.c:246
struct match_char * node
Definition pbx.c:248
struct ast_exten * canmatch_exten
Definition pbx.c:249

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

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

◆ pbx_outgoing_attempt()

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

Definition at line 6002 of file pbx.c.

6008{
6010 struct ast_channel *dialed;
6011 pthread_t thread;
6012 char tmp_cid_name[128];
6013 char tmp_cid_num[128];
6014
6016 if (!outgoing) {
6017 return -1;
6018 }
6019 ast_cond_init(&outgoing->cond, NULL);
6020
6021 if (!ast_strlen_zero(app)) {
6023 outgoing->appdata = ast_strdup(appdata);
6024 } else {
6028 }
6029
6030 if (!(outgoing->dial = ast_dial_create())) {
6031 return -1;
6032 }
6033
6034 if (ast_dial_append(outgoing->dial, type, addr, assignedids)) {
6035 return -1;
6036 }
6037
6038 ast_dial_set_global_timeout(outgoing->dial, timeout);
6039
6040 if (!ast_strlen_zero(predial_callee)) {
6041 /* note casting to void * here to suppress compiler warning message (passing const to non-const function) */
6042 ast_dial_option_global_enable(outgoing->dial, AST_DIAL_OPTION_PREDIAL, (void *)predial_callee);
6043 }
6044
6045 if (ast_dial_prerun(outgoing->dial, NULL, cap)) {
6046 if (synchronous && reason) {
6048 ast_dial_reason(outgoing->dial, 0));
6049 }
6050 return -1;
6051 }
6052
6054 if (!dialed) {
6055 return -1;
6056 }
6057
6058 if (vars) {
6060 }
6062 if (!ast_strlen_zero(account)) {
6064 ast_channel_accountcode_set(dialed, account);
6065 ast_channel_peeraccount_set(dialed, account);
6067 }
6069
6070 if (!ast_strlen_zero(predial_callee)) {
6071 char *tmp = NULL;
6072 /*
6073 * The predial sub routine may have set callerid so set this into the new channel
6074 * Note... cid_num and cid_name parameters to this function will always be NULL if
6075 * predial_callee is non-NULL so we are not overwriting anything here.
6076 */
6078 if (tmp) {
6079 ast_copy_string(tmp_cid_num, tmp, sizeof(tmp_cid_num));
6080 cid_num = tmp_cid_num;
6081 }
6083 if (tmp) {
6084 ast_copy_string(tmp_cid_name, tmp, sizeof(tmp_cid_name));
6085 cid_name = tmp_cid_name;
6086 }
6087 }
6089
6090 if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) {
6092
6093 /*
6094 * It seems strange to set the CallerID on an outgoing call leg
6095 * to whom we are calling, but this function's callers are doing
6096 * various Originate methods. This call leg goes to the local
6097 * user. Once the called party answers, the dialplan needs to
6098 * be able to access the CallerID from the CALLERID function as
6099 * if the called party had placed this call.
6100 */
6101 ast_set_callerid(dialed, cid_num, cid_name, cid_num);
6102
6104 if (!ast_strlen_zero(cid_num)) {
6105 connected.id.number.valid = 1;
6106 connected.id.number.str = (char *) cid_num;
6108 }
6109 if (!ast_strlen_zero(cid_name)) {
6110 connected.id.name.valid = 1;
6111 connected.id.name.str = (char *) cid_name;
6113 }
6115 }
6116
6117 if (early_media) {
6119 }
6120
6121 if (locked_channel) {
6122 /*
6123 * Keep a dialed channel ref since the caller wants
6124 * the channel returned. We must get the ref before
6125 * spawning off pbx_outgoing_exec().
6126 */
6127 ast_channel_ref(dialed);
6128 if (!synchronous) {
6129 /*
6130 * Lock it now to hold off pbx_outgoing_exec() in case the
6131 * calling function needs the channel state/snapshot before
6132 * dialing actually happens.
6133 */
6134 ast_channel_lock(dialed);
6135 }
6136 }
6137
6138 /* This extra reference is dereferenced by pbx_outgoing_exec */
6139 ao2_ref(outgoing, +1);
6140
6141 if (synchronous == AST_OUTGOING_WAIT_COMPLETE) {
6142 /*
6143 * Because we are waiting until this is complete anyway, there is no
6144 * sense in creating another thread that we will just need to wait
6145 * for, so instead we commandeer the current thread.
6146 */
6148 } else {
6149 outgoing->in_separate_thread = 1;
6150
6152 ast_log(LOG_WARNING, "Unable to spawn dialing thread for '%s/%s'\n", type, addr);
6153 ao2_ref(outgoing, -1);
6154 if (locked_channel) {
6155 if (!synchronous) {
6156 ast_channel_unlock(dialed);
6157 }
6158 ast_channel_unref(dialed);
6159 }
6160 return -1;
6161 }
6162
6163 if (synchronous) {
6165 /* Wait for dialing to complete */
6166 while (!outgoing->dialed) {
6168 }
6170 }
6171 }
6172
6173 if (synchronous) {
6174 /* Determine the outcome of the dialing attempt up to it being answered. */
6175 if (reason) {
6176 *reason = pbx_dial_reason(outgoing->dial_res,
6177 ast_dial_reason(outgoing->dial, 0));
6178 }
6179
6180 if (outgoing->dial_res != AST_DIAL_RESULT_ANSWERED) {
6181 /* The dial operation failed. */
6182 if (locked_channel) {
6183 ast_channel_unref(dialed);
6184 }
6185 return -1;
6186 }
6187 if (locked_channel) {
6188 ast_channel_lock(dialed);
6189 }
6190 }
6191
6192 if (locked_channel) {
6193 *locked_channel = dialed;
6194 }
6195 return 0;
6196}
pthread_t thread
Definition app_sla.c:335
#define ao2_cleanup(obj)
Definition astobj2.h:1934
#define ao2_unlock(a)
Definition astobj2.h:729
#define ao2_lock(a)
Definition astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition astobj2.c:476
#define ao2_alloc(data_size, destructor_fn)
Definition astobj2.h:409
#define AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED
Definition callerid.h:437
static int connected
Definition cdr_pgsql.c:73
void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Set the connected line information in the Asterisk channel.
Definition channel.c:8484
@ AST_FLAG_ORIGINATED
Definition channel.h:1059
#define ast_channel_ref(c)
Increase channel reference count.
Definition channel.h:3008
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition channel.c:7370
void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide)
Initialize the given connected line structure using the given guide for a set update operation.
Definition channel.c:2032
@ AST_DIAL_RESULT_FAILED
Definition dial.h:56
void ast_dial_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback)
Set a callback for state changes.
Definition dial.c:1272
int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
Append a channel.
Definition dial.c:280
struct ast_dial * ast_dial_create(void)
New dialing structure.
Definition dial.c:223
int ast_dial_prerun(struct ast_dial *dial, struct ast_channel *chan, struct ast_format_cap *cap)
Request all appended channels, but do not dial.
Definition dial.c:431
void ast_dial_set_global_timeout(struct ast_dial *dial, int timeout)
Set the maximum time (globally) allowed for trying to ring phones.
Definition dial.c:1287
int ast_dial_reason(struct ast_dial *dial, int num)
Get the reason an outgoing channel has failed.
Definition dial.c:1250
@ AST_DIAL_OPTION_PREDIAL
Definition dial.h:47
struct ast_channel * ast_dial_get_channel(struct ast_dial *dial, int num)
Get the dialing channel, if prerun has been executed.
Definition dial.c:1261
int ast_dial_option_global_enable(struct ast_dial *dial, enum ast_dial_option option, void *data)
Enables an option globally.
Definition dial.c:1148
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
#define ast_cond_wait(cond, mutex)
Definition lock.h:212
#define ast_cond_init(cond, attr)
Definition lock.h:208
static void pbx_outgoing_state_callback(struct ast_dial *dial)
Internal dialing state callback which causes early media to trigger an answer.
Definition pbx.c:5937
static enum ast_control_frame_type pbx_dial_reason(enum ast_dial_result dial_result, int cause)
Attempt to convert disconnect cause to old originate reason.
Definition pbx.c:5963
static void * pbx_outgoing_exec(void *data)
Internal function which dials an outgoing leg and sends it to a provided extension or application.
Definition pbx.c:5874
static void pbx_outgoing_destroy(void *obj)
Destructor for outgoing structure.
Definition pbx.c:5860
@ AST_OUTGOING_WAIT_COMPLETE
Definition pbx.h:1146
struct ast_party_dialed dialed
Dialed/Called information.
Connected Line/Party information.
Definition channel.h:458
const ast_string_field app
Definition pbx_spool.c:95
const ast_string_field context
Definition pbx_spool.c:95
const ast_string_field exten
Definition pbx_spool.c:95
int priority
Definition pbx_spool.c:96
Structure which contains information about an outgoing dial.
Definition pbx.c:5836
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition utils.h:981

References ao2_alloc, ao2_cleanup, ao2_lock, ao2_object_get_lockaddr(), ao2_ref, ao2_unlock, app, outgoing::app, ast_channel_caller(), ast_channel_connected(), ast_channel_flags(), ast_channel_lock, ast_channel_ref, ast_channel_set_connected_line(), ast_channel_stage_snapshot(), ast_channel_stage_snapshot_done(), ast_channel_unlock, ast_channel_unref, ast_cond_init, ast_cond_wait, ast_copy_string(), ast_dial_append(), ast_dial_create(), ast_dial_get_channel(), ast_dial_option_global_enable(), AST_DIAL_OPTION_PREDIAL, ast_dial_prerun(), ast_dial_reason(), AST_DIAL_RESULT_ANSWERED, AST_DIAL_RESULT_FAILED, ast_dial_set_global_timeout(), ast_dial_set_state_callback(), AST_FLAG_ORIGINATED, ast_log, AST_OUTGOING_WAIT_COMPLETE, ast_party_connected_line_set_init(), AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, ast_pthread_create_detached, ast_set_callerid(), ast_set_flag, ast_set_variables(), ast_strdup, ast_strlen_zero(), connected, ast_channel::context, outgoing::context, ast_channel::dialed, ast_channel::exten, outgoing::exten, LOG_WARNING, name, NULL, pbx_dial_reason(), pbx_outgoing_destroy(), pbx_outgoing_exec(), pbx_outgoing_state_callback(), priority, outgoing::priority, RAII_VAR, S_COR, thread, and type.

Referenced by ast_pbx_outgoing_app_predial(), and ast_pbx_outgoing_exten_predial().

◆ pbx_outgoing_destroy()

static void pbx_outgoing_destroy ( void *  obj)
static

Destructor for outgoing structure.

Definition at line 5860 of file pbx.c.

5861{
5862 struct pbx_outgoing *outgoing = obj;
5863
5864 if (outgoing->dial) {
5866 }
5867
5868 ast_cond_destroy(&outgoing->cond);
5869
5870 ast_free(outgoing->appdata);
5871}
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition dial.c:1094
#define ast_cond_destroy(cond)
Definition lock.h:209

References ast_cond_destroy, ast_dial_destroy(), and ast_free.

Referenced by pbx_outgoing_attempt().

◆ pbx_outgoing_exec()

static void * pbx_outgoing_exec ( void *  data)
static

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

Definition at line 5874 of file pbx.c.

5875{
5876 RAII_VAR(struct pbx_outgoing *, outgoing, data, ao2_cleanup);
5877 enum ast_dial_result res;
5878 struct ast_channel *chan;
5879
5880 res = ast_dial_run(outgoing->dial, NULL, 0);
5881
5882 if (outgoing->in_separate_thread) {
5883 /* Notify anyone interested that dialing is complete */
5885 outgoing->dial_res = res;
5886 outgoing->dialed = 1;
5887 ast_cond_signal(&outgoing->cond);
5889 } else {
5890 /* We still need the dial result, but we don't need to lock */
5891 outgoing->dial_res = res;
5892 }
5893
5894 /* If the outgoing leg was not answered we can immediately return and go no further */
5895 if (res != AST_DIAL_RESULT_ANSWERED) {
5896 return NULL;
5897 }
5898
5899 /* We steal the channel so we get ownership of when it is hung up */
5900 chan = ast_dial_answered_steal(outgoing->dial);
5901
5902 if (!ast_strlen_zero(outgoing->app)) {
5903 struct ast_app *app = pbx_findapp(outgoing->app);
5904
5905 if (app) {
5906 ast_verb(4, "Launching %s(%s) on %s\n", outgoing->app, S_OR(outgoing->appdata, ""),
5907 ast_channel_name(chan));
5908 pbx_exec(chan, app, outgoing->appdata);
5909 } else {
5910 ast_log(LOG_WARNING, "No such application '%s'\n", outgoing->app);
5911 }
5912
5913 ast_hangup(chan);
5914 } else {
5917 }
5918
5921 }
5922
5923 if (outgoing->priority > 0) {
5925 }
5926
5927 if (ast_pbx_run(chan)) {
5928 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(chan));
5929 ast_hangup(chan);
5930 }
5931 }
5932
5933 return NULL;
5934}
ast_dial_result
List of return codes for dial run API calls.
Definition dial.h:54
enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *chan, int async)
Execute dialing synchronously or asynchronously.
Definition dial.c:938
struct ast_channel * ast_dial_answered_steal(struct ast_dial *dial)
Steal the channel that answered.
Definition dial.c:992
#define ast_cond_signal(cond)
Definition lock.h:210

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

Referenced by pbx_outgoing_attempt().

◆ pbx_outgoing_state_callback()

static void pbx_outgoing_state_callback ( struct ast_dial dial)
static

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

Definition at line 5937 of file pbx.c.

5938{
5939 struct ast_channel *channel;
5940
5942 return;
5943 }
5944
5945 if (!(channel = ast_dial_get_channel(dial, 0))) {
5946 return;
5947 }
5948
5949 ast_verb(4, "Treating progress as answer on '%s' due to early media option\n",
5950 ast_channel_name(channel));
5951
5953}
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition channel.c:1289
enum ast_dial_result ast_dial_state(struct ast_dial *dial)
Return state of dial.
Definition dial.c:1011
@ AST_DIAL_RESULT_PROGRESS
Definition dial.h:59

References ast_channel_name(), AST_CONTROL_ANSWER, ast_dial_get_channel(), AST_DIAL_RESULT_PROGRESS, ast_dial_state(), ast_queue_control(), and ast_verb.

Referenced by pbx_outgoing_attempt().

◆ pbx_parse_location()

int pbx_parse_location ( struct ast_channel chan,
char **  context,
char **  exten,
char **  pri,
int *  ipri,
int *  mode,
char *  rest 
)

Parses a dialplan location into context, extension, priority.

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

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

Return values
0success
non-zerofailure

Definition at line 6949 of file pbx.c.

6950{
6951 char *context, *exten, *pri;
6952 /* do the strsep before here, so we don't have to alloc and free */
6953 if (!*extenp) {
6954 /* Only a priority in this one */
6955 *prip = *contextp;
6956 *extenp = NULL;
6957 *contextp = NULL;
6958 } else if (!*prip) {
6959 /* Only an extension and priority in this one */
6960 *prip = *extenp;
6961 *extenp = *contextp;
6962 *contextp = NULL;
6963 }
6964 context = *contextp;
6965 exten = *extenp;
6966 pri = *prip;
6967 if (mode) {
6968 if (*pri == '+') {
6969 *mode = 1;
6970 pri++;
6971 } else if (*pri == '-') {
6972 *mode = -1;
6973 pri++;
6974 }
6975 }
6976 if ((rest && sscanf(pri, "%30d%1s", ipri, rest) != 1) || sscanf(pri, "%30d", ipri) != 1) {
6977 *ipri = ast_findlabel_extension(chan, context ? context : ast_channel_context(chan),
6978 exten ? exten : ast_channel_exten(chan), pri,
6980 if (*ipri < 1) {
6981 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
6982 return -1;
6983 } else if (mode) {
6984 *mode = 0;
6985 }
6986 }
6987 return 0;
6988}
enum queue_result id
Definition app_queue.c:1790
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:2740

References ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_findlabel_extension(), ast_log, ast_channel::context, ast_channel::exten, LOG_WARNING, NULL, and S_COR.

Referenced by eval_exten_read(), and pbx_parseable_goto().

◆ pbx_parseable_goto()

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

Definition at line 6990 of file pbx.c.

6991{
6992 char *exten, *pri, *context;
6993 char *stringp;
6994 int ipri;
6995 int mode = 0;
6996 char rest[2] = "";
6997
6998 if (ast_strlen_zero(goto_string)) {
6999 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
7000 return -1;
7001 }
7002 stringp = ast_strdupa(goto_string);
7003 context = strsep(&stringp, ","); /* guaranteed non-null */
7004 exten = strsep(&stringp, ",");
7005 pri = strsep(&stringp, ",");
7006
7007 if (pbx_parse_location(chan, &context, &exten, &pri, &ipri, &mode, rest)) {
7008 return -1;
7009 }
7010 /* At this point we have a priority and maybe an extension and a context */
7011
7012 if (mode)
7013 ipri = ast_channel_priority(chan) + (ipri * mode);
7014
7015 if (async)
7016 ast_async_goto(chan, context, exten, ipri);
7017 else
7018 ast_explicit_goto(chan, context, exten, ipri);
7019
7020 return 0;
7021
7022}
int pbx_parse_location(struct ast_channel *chan, char **contextp, char **extenp, char **prip, int *ipri, int *mode, char *rest)
Parses a dialplan location into context, extension, priority.
Definition pbx.c:6949

References ast_async_goto(), ast_channel_priority(), ast_explicit_goto(), ast_log, ast_strdupa, ast_strlen_zero(), ast_channel::context, ast_channel::exten, LOG_WARNING, pbx_parse_location(), and strsep().

Referenced by ast_async_parseable_goto(), and ast_parseable_goto().

◆ pbx_set_autofallthrough()

int pbx_set_autofallthrough ( int  newval)

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

Definition at line 3330 of file pbx.c.

3331{
3332 int oldval = autofallthrough;
3333 autofallthrough = newval;
3334 return oldval;
3335}

References autofallthrough.

Referenced by pbx_load_module().

◆ pbx_set_extenpatternmatchnew()

int pbx_set_extenpatternmatchnew ( int  newval)

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

Definition at line 3337 of file pbx.c.

3338{
3339 int oldval = extenpatternmatchnew;
3340 extenpatternmatchnew = newval;
3341 return oldval;
3342}

References extenpatternmatchnew.

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

◆ pbx_set_overrideswitch()

void pbx_set_overrideswitch ( const char *  newval)

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

Since
1.6.1

Definition at line 3344 of file pbx.c.

3345{
3346 if (overrideswitch) {
3348 }
3349 if (!ast_strlen_zero(newval)) {
3350 overrideswitch = ast_strdup(newval);
3351 } else {
3353 }
3354}

References ast_free, ast_strdup, ast_strlen_zero(), NULL, and overrideswitch.

Referenced by pbx_load_module().

◆ pbx_shutdown()

static void pbx_shutdown ( void  )
static

Definition at line 7038 of file pbx.c.

7039{
7040 if (contexts_table) {
7042 }
7043}

References ast_hashtab_destroy(), contexts_table, and NULL.

Referenced by ast_pbx_init().

◆ pbx_thread()

static void * pbx_thread ( void *  data)
static

Definition at line 3248 of file pbx.c.

3249{
3250 /* Oh joyous kernel, we're a new thread, with nothing to do but
3251 answer this channel and get it going.
3252 */
3253 /* NOTE:
3254 The launcher of this function _MUST_ increment 'countcalls'
3255 before invoking the function; it will be decremented when the
3256 PBX has finished running on the channel
3257 */
3258 struct ast_channel *c = data;
3259
3262
3263 pthread_exit(NULL);
3264
3265 return NULL;
3266}
const char * data

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

Referenced by ast_pbx_start().

◆ print_ext()

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

helper function to print an extension

Definition at line 3833 of file pbx.c.

3834{
3835 int prio = ast_get_extension_priority(e);
3836 if (prio == PRIORITY_HINT) {
3837 snprintf(buf, buflen, "hint: %s",
3839 } else {
3840 snprintf(buf, buflen, "%d. %s(%s)",
3841 prio, ast_get_extension_app(e),
3843 }
3844}

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

Referenced by show_dialplan_helper().

◆ raise_exception()

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

pbx.c functions needed by pbx_builtins.c

Definition at line 2432 of file pbx.c.

2433{
2434 struct ast_datastore *ds;
2435 struct pbx_exception *exception;
2436
2437 ast_channel_lock(chan);
2439 if (!ds) {
2441 if (!ds) {
2442 ast_channel_unlock(chan);
2443 return -1;
2444 }
2445 if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
2447 ast_channel_unlock(chan);
2448 return -1;
2449 }
2450 ds->data = exception;
2451 ast_channel_datastore_add(chan, ds);
2452 } else
2453 exception = ds->data;
2454
2455 ast_string_field_set(exception, reason, reason);
2457 ast_string_field_set(exception, exten, ast_channel_exten(chan));
2458 exception->priority = ast_channel_priority(chan);
2459 ast_channel_unlock(chan);
2460
2461 set_ext_pri(chan, "e", priority);
2462 return 0;
2463}
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition channel.c:2376
#define ast_datastore_alloc(info, uid)
Definition datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition datastore.c:68
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.

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

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

◆ set_ext_pri()

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

helper function to set extension and priority

Definition at line 2824 of file pbx.c.

2825{
2827 ast_channel_exten_set(c, exten);
2830}

References ast_channel_exten_set(), ast_channel_lock, ast_channel_priority_set(), ast_channel_unlock, c, and ast_exten::exten.

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

◆ show_debug_helper()

static int show_debug_helper ( int  fd,
const char *  context,
const char *  exten,
struct dialplan_counters dpc,
struct ast_include rinclude,
int  includecount,
const char *  includes[] 
)
static

Definition at line 4023 of file pbx.c.

4024{
4025 struct ast_context *c = NULL;
4026 int res = 0, old_total_exten = dpc->total_exten;
4027
4028 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
4029
4030 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
4031 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
4032 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
4033 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
4034 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
4035 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
4036 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
4038
4039 /* walk all contexts ... */
4040 while ( (c = ast_walk_contexts(c)) ) {
4041 int context_info_printed = 0;
4042
4043 if (context && strcmp(ast_get_context_name(c), context))
4044 continue; /* skip this one, name doesn't match */
4045
4046 dpc->context_existence = 1;
4047
4048 if (!c->pattern_tree) {
4049 /* Ignore check_return warning from Coverity for ast_exists_extension below */
4050 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
4051 }
4052
4054
4055 dpc->total_context++;
4056 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
4058 context_info_printed = 1;
4059
4060 if (c->pattern_tree)
4061 {
4062 cli_match_char_tree(c->pattern_tree, " ", fd);
4063 } else {
4064 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
4065 }
4066
4068
4069 /* if we print something in context, make an empty line */
4070 if (context_info_printed)
4071 ast_cli(fd, "\n");
4072 }
4074
4075 return (dpc->total_exten == old_total_exten) ? -1 : res;
4076}
const char * ast_get_context_registrar(struct ast_context *c)
Definition pbx.c:6685
const char * name

References ast_cli(), ast_exists_extension(), ast_get_context_name(), ast_get_context_registrar(), ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_contexts(), c, cli_match_char_tree(), dialplan_counters::context_existence, test_val::name, NULL, dialplan_counters::total_context, and dialplan_counters::total_exten.

Referenced by handle_debug_dialplan().

◆ show_dialplan_helper()

static int show_dialplan_helper ( int  fd,
const char *  context,
const char *  exten,
struct dialplan_counters dpc,
const struct ast_include rinclude,
int  includecount,
const char *  includes[] 
)
static

Definition at line 3862 of file pbx.c.

3863{
3864 struct ast_context *c = NULL;
3865 int res = 0, old_total_exten = dpc->total_exten;
3866
3868
3869 /* walk all contexts ... */
3870 while ( (c = ast_walk_contexts(c)) ) {
3871 int idx;
3872 struct ast_exten *e;
3873#ifndef LOW_MEMORY
3874 char buf[1024], buf2[1024];
3875#else
3876 char buf[256], buf2[256];
3877#endif
3878 int context_info_printed = 0;
3879
3880 if (context && strcmp(ast_get_context_name(c), context))
3881 continue; /* skip this one, name doesn't match */
3882
3883 dpc->context_existence = 1;
3884
3886
3887 /* are we looking for exten too? if yes, we print context
3888 * only if we find our extension.
3889 * Otherwise print context even if empty ?
3890 * XXX i am not sure how the rinclude is handled.
3891 * I think it ought to go inside.
3892 */
3893 if (!exten) {
3894 dpc->total_context++;
3895 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
3897 if (c->autohints) {
3898 ast_cli(fd, "Autohints support enabled\n");
3899 }
3900 context_info_printed = 1;
3901 }
3902
3903 /* walk extensions ... */
3904 e = NULL;
3905 while ( (e = ast_walk_context_extensions(c, e)) ) {
3906 struct ast_exten *p;
3907
3909 continue; /* skip, extension match failed */
3910
3911 dpc->extension_existence = 1;
3912
3913 /* may we print context info? */
3914 if (!context_info_printed) {
3915 dpc->total_context++;
3916 if (rinclude) { /* TODO Print more info about rinclude */
3917 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
3919 } else {
3920 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
3922 if (c->autohints) {
3923 ast_cli(fd, "Autohints support enabled\n");
3924 }
3925 }
3926 context_info_printed = 1;
3927 }
3928 dpc->total_prio++;
3929
3930 /* write extension name and first peer */
3931 if (e->matchcid == AST_EXT_MATCHCID_ON)
3932 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
3933 else
3934 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
3935
3936 print_ext(e, buf2, sizeof(buf2));
3937
3939
3940 dpc->total_exten++;
3941 /* walk next extension peers */
3942 p = e; /* skip the first one, we already got it */
3943 while ( (p = ast_walk_extension_priorities(e, p)) ) {
3944 const char *el = ast_get_extension_label(p);
3945 dpc->total_prio++;
3946 if (el)
3947 snprintf(buf, sizeof(buf), " [%s]", el);
3948 else
3949 buf[0] = '\0';
3950 print_ext(p, buf2, sizeof(buf2));
3951
3953 }
3954 }
3955
3956 /* walk included and write info ... */
3957 for (idx = 0; idx < ast_context_includes_count(c); idx++) {
3958 const struct ast_include *i = ast_context_includes_get(c, idx);
3959
3960 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
3961 if (exten) {
3962 /* Check all includes for the requested extension */
3963 if (includecount >= AST_PBX_MAX_STACK) {
3964 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
3965 } else {
3966 int dupe = 0;
3967 int x;
3968 for (x = 0; x < includecount; x++) {
3969 if (!strcasecmp(includes[x], ast_get_include_name(i))) {
3970 dupe++;
3971 break;
3972 }
3973 }
3974 if (!dupe) {
3975 includes[includecount] = ast_get_include_name(i);
3976 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
3977 } else {
3978 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
3979 }
3980 }
3981 } else {
3982 ast_cli(fd, " Include => %-45s [%s]\n",
3984 }
3985 }
3986
3987 /* walk ignore patterns and write info ... */
3988 for (idx = 0; idx < ast_context_ignorepats_count(c); idx++) {
3989 const struct ast_ignorepat *ip = ast_context_ignorepats_get(c, idx);
3990 const char *ipname = ast_get_ignorepat_name(ip);
3991 char ignorepat[AST_MAX_EXTENSION];
3992
3993 snprintf(buf, sizeof(buf), "'%s'", ipname);
3994 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
3995 if (!exten || ast_extension_match(ignorepat, exten)) {
3996 ast_cli(fd, " Ignore pattern => %-45s [%s]\n",
3998 }
3999 }
4000 if (!rinclude) {
4001 for (idx = 0; idx < ast_context_switches_count(c); idx++) {
4002 const struct ast_sw *sw = ast_context_switches_get(c, idx);
4003
4004 snprintf(buf, sizeof(buf), "'%s/%s'",
4007 ast_cli(fd, " Alt. Switch => %-45s [%s]\n",
4009 }
4010 }
4011
4013
4014 /* if we print something in context, make an empty line */
4015 if (context_info_printed)
4016 ast_cli(fd, "\n");
4017 }
4019
4020 return (dpc->total_exten == old_total_exten) ? -1 : res;
4021}
static void show_dialplan_helper_extension_output(int fd, char *buf1, char *buf2, struct ast_exten *exten)
Writes CLI output of a single extension for show dialplan.
Definition pbx.c:3847
static void print_ext(struct ast_exten *e, char *buf, int buflen)
helper function to print an extension
Definition pbx.c:3833

References ast_cli(), ast_context_ignorepats_count(), ast_context_ignorepats_get(), ast_context_includes_count(), ast_context_includes_get(), ast_context_switches_count(), ast_context_switches_get(), AST_EXT_MATCHCID_ON, ast_extension_match(), ast_get_context_name(), ast_get_context_registrar(), ast_get_extension_label(), ast_get_extension_name(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_log, AST_MAX_EXTENSION, AST_PBX_MAX_STACK, ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), buf, c, ast_exten::cidmatch, dialplan_counters::context_existence, el, ast_exten::exten, dialplan_counters::extension_existence, LOG_WARNING, ast_exten::matchcid, NULL, print_ext(), show_dialplan_helper(), show_dialplan_helper_extension_output(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.

Referenced by handle_show_dialplan(), and show_dialplan_helper().

◆ show_dialplan_helper_extension_output()

static void show_dialplan_helper_extension_output ( int  fd,
char *  buf1,
char *  buf2,
struct ast_exten exten 
)
static

Writes CLI output of a single extension for show dialplan.

Definition at line 3847 of file pbx.c.

3848{
3850 ast_cli(fd, " %-17s %-45s [%s:%d]\n",
3851 buf1, buf2,
3854 return;
3855 }
3856
3857 ast_cli(fd, " %-17s %-45s [%s]\n",
3858 buf1, buf2, ast_get_extension_registrar(exten));
3859}
int ast_get_extension_registrar_line(struct ast_exten *e)
Get line number of configuration file used by registrar to register this extension.
Definition pbx.c:6700
const char * ast_get_extension_registrar_file(struct ast_exten *e)
Get name of configuration file used by registrar to register this extension.
Definition pbx.c:6695

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

Referenced by show_dialplan_helper().

◆ trie_find_next_match()

static struct ast_exten * trie_find_next_match ( struct match_char node)
static

Definition at line 791 of file pbx.c.

792{
793 struct match_char *m3;
794 struct match_char *m4;
795 struct ast_exten *e3;
796
797 if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */
798 return node->exten;
799 }
800
801 if (node && node->x[0] == '!' && !node->x[1]) {
802 return node->exten;
803 }
804
805 if (!node || !node->next_char) {
806 return NULL;
807 }
808
809 m3 = node->next_char;
810
811 if (m3->exten) {
812 return m3->exten;
813 }
814 for (m4 = m3->alt_char; m4; m4 = m4->alt_char) {
815 if (m4->exten) {
816 return m4->exten;
817 }
818 }
819 for (m4 = m3; m4; m4 = m4->alt_char) {
820 e3 = trie_find_next_match(m3);
821 if (e3) {
822 return e3;
823 }
824 }
825
826 return NULL;
827}

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

Referenced by pbx_find_extension(), and trie_find_next_match().

◆ unload_pbx()

static void unload_pbx ( void  )
static

Definition at line 6586 of file pbx.c.

6587{
6588 ast_manager_unregister("ShowDialPlan");
6592}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition manager.c:7716
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.

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

Referenced by load_pbx().

◆ unreference_cached_app()

void unreference_cached_app ( struct ast_app app)

pbx.c function needed by pbx_app.c

Definition at line 4523 of file pbx.c.

4524{
4525 struct ast_context *context = NULL;
4526 struct ast_exten *eroot = NULL, *e = NULL;
4527
4529 while ((context = ast_walk_contexts(context))) {
4530 while ((eroot = ast_walk_context_extensions(context, eroot))) {
4531 while ((e = ast_walk_extension_priorities(eroot, e))) {
4532 if (e->cached_app == app)
4533 e->cached_app = NULL;
4534 }
4535 }
4536 }
4538
4539 return;
4540}

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

Referenced by ast_unregister_application().

◆ update_scoreboard()

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

Definition at line 695 of file pbx.c.

696{
697 /* if this extension is marked as deleted, then skip this -- if it never shows
698 on the scoreboard, it will never be found, nor will halt the traversal. */
699 if (deleted)
700 return;
701 board->total_specificity = spec;
702 board->total_length = length;
703 board->exten = exten;
704 board->last_char = last;
705 board->node = node;
706#ifdef NEED_DEBUG_HERE
707 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec);
708#endif
709}

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

Referenced by new_find_extension().

◆ wait_for_hangup()

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

Definition at line 6514 of file pbx.c.

6515{
6516 int res;
6517 struct ast_frame *f;
6518 double waitsec;
6519 int waittime;
6520
6521 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
6522 waitsec = -1;
6523 if (waitsec > -1) {
6524 waittime = waitsec * 1000.0;
6525 ast_safe_sleep_without_silence(chan, waittime);
6526 } else do {
6527 res = ast_waitfor(chan, -1);
6528 if (res < 0)
6529 return;
6530 f = ast_read(chan);
6531 if (f)
6532 ast_frfree(f);
6533 } while(f);
6534}
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition channel.c:3166
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition channel.c:4278
int ast_safe_sleep_without_silence(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups, and do not generate silence.
Definition channel.c:1566
#define ast_frfree(fr)
Data structure associated with a single frame of data.
union ast_frame::@237 data

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

Referenced by indicate_busy(), and indicate_congestion().

Variable Documentation

◆ autofallthrough

int autofallthrough = 1
static

Definition at line 417 of file pbx.c.

Referenced by __ast_pbx_run(), and pbx_set_autofallthrough().

◆ conlock

Lock for the ast_context list.

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

Definition at line 434 of file pbx.c.

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

◆ contexts

struct ast_context* contexts
static

◆ contexts_table

struct ast_hashtab* contexts_table = NULL
static

◆ countcalls

int countcalls
static

Definition at line 422 of file pbx.c.

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

◆ exception_function

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

Definition at line 2493 of file pbx.c.

2493 {
2494 .name = "EXCEPTION",
2495 .read = acf_exception_read,
2496};

Referenced by load_pbx(), and unload_pbx().

◆ exception_store_info

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

Definition at line 2416 of file pbx.c.

2416 {
2417 .type = "EXCEPTION",
2418 .destroy = exception_store_free,
2419};

Referenced by acf_exception_read(), and raise_exception().

◆ extenpatternmatchnew

int extenpatternmatchnew = 0
static

Definition at line 418 of file pbx.c.

Referenced by pbx_find_extension(), and pbx_set_extenpatternmatchnew().

◆ maxcalllock

ast_mutex_t maxcalllock = AST_MUTEX_INIT_VALUE
static

Definition at line 421 of file pbx.c.

Referenced by decrease_call_count(), and increase_call_count().

◆ overrideswitch

char* overrideswitch = NULL
static

Definition at line 419 of file pbx.c.

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

◆ pbx_cli

struct ast_cli_entry pbx_cli[]
static

Definition at line 4510 of file pbx.c.

4510 {
4511#if 0
4512 AST_CLI_DEFINE(handle_eat_memory, "Eats all available memory"),
4513#endif
4514#ifdef AST_DEVMODE
4515 AST_CLI_DEFINE(handle_show_device2extenstate, "Show expected exten state from multiple device states"),
4516#endif
4517 AST_CLI_DEFINE(handle_show_dialplan, "Show dialplan"),
4518 AST_CLI_DEFINE(handle_debug_dialplan, "Show fast extension pattern matching data structures"),
4519 AST_CLI_DEFINE(handle_unset_extenpatternmatchnew, "Use the Old extension pattern matching algorithm."),
4520 AST_CLI_DEFINE(handle_set_extenpatternmatchnew, "Use the New extension pattern matching algorithm."),
4521};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197
static char * handle_unset_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition pbx.c:4479
static char * handle_debug_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Send ack once.
Definition pbx.c:4145
static char * handle_set_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition pbx.c:4451
static char * handle_show_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition pbx.c:4078

Referenced by load_pbx(), and unload_pbx().

◆ testtime_function

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

Definition at line 6563 of file pbx.c.

6563 {
6564 .name = "TESTTIME",
6565 .write = testtime_write,
6566};

Referenced by load_pbx(), and unload_pbx().

◆ totalcalls

int totalcalls
static

Definition at line 423 of file pbx.c.

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