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/cel.h"
#include "asterisk/config.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/ast_expr.h"
#include "asterisk/linkedlists.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/devicestate.h"
#include "asterisk/event.h"
#include "asterisk/hashtab.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/xmldoc.h"
#include "asterisk/astobj2.h"
Go to the source code of this file.
Data Structures | |
struct | acf_root |
struct | app_tmp |
struct | apps |
struct | ast_app |
ast_app: A registered application More... | |
struct | ast_context |
ast_context: An extension context More... | |
struct | ast_exten |
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own linked list of extensions - one item per priority. More... | |
struct | ast_hint |
Structure for dial plan hints. More... | |
struct | ast_ignorepat |
ast_ignorepat: Ignore patterns in dial plan More... | |
struct | ast_include |
ast_include: include= support in extensions.conf More... | |
struct | ast_state_cb |
ast_state_cb: An extension state notify register item More... | |
struct | ast_sw |
ast_sw: Switch statement in extensions.conf More... | |
struct | async_stat |
struct | cfextension_states |
struct | dialplan_counters |
Counters for the show dialplan manager command. More... | |
struct | fake_context |
struct | match_char |
match_char: forms a syntax tree for quick matching of extension patterns More... | |
struct | pattern_node |
struct | pbx_builtin |
Declaration of builtin applications. More... | |
struct | pbx_exception |
struct | scoreboard |
struct | statechange |
struct | store_hint |
struct | store_hints |
struct | switches |
Defines | |
#define | AST_PBX_MAX_STACK 128 |
#define | BACKGROUND_MATCHEXTEN (1 << 2) |
#define | BACKGROUND_NOANSWER (1 << 1) |
#define | BACKGROUND_PLAYBACK (1 << 3) |
#define | BACKGROUND_SKIP (1 << 0) |
#define | BITS_PER 8 |
#define | EXT_DATA_SIZE 8192 |
#define | HASH_EXTENHINT_SIZE 563 |
#define | INC_DST_OVERFLOW_CHECK |
#define | NEW_MATCHER_CHK_MATCH |
#define | NEW_MATCHER_RECURSE |
#define | SAY_STUBS |
#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_BUF_SIZE 4096 |
#define | VAR_HARDTRAN 3 |
#define | VAR_NORMAL 1 |
#define | VAR_SOFTTRAN 2 |
#define | WAITEXTEN_DIALTONE (1 << 1) |
#define | WAITEXTEN_MOH (1 << 0) |
Functions | |
void | __ast_context_destroy (struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar) |
int | __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod) |
Register a custom function. | |
static int | __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async) |
static void | __ast_internal_context_destroy (struct ast_context *con) |
static enum ast_pbx_result | __ast_pbx_run (struct ast_channel *c, struct ast_pbx_args *args) |
static void | __init_extensionstate_buf (void) |
static void | __init_switch_data (void) |
static int | _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
static int | acf_exception_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen) |
static int | acf_retrieve_docs (struct ast_custom_function *acf) |
static struct match_char * | add_exten_to_pattern_tree (struct ast_context *con, struct ast_exten *e1, int findonly) |
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 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_char * | already_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) |
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, int lock_context) |
Same as ast_add_extension2() but controls the context locking. | |
static int | ast_add_extension_nolock (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
static int | ast_add_hint (struct ast_exten *e) |
Add hint to hint list, check initial extension state. | |
int | ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
Set the channel to next execute the specified dialplan location. | |
int | ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority) |
Set the channel to next execute the specified dialplan location. | |
int | ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string) |
int | ast_build_timing (struct ast_timing *i, const char *info_in) |
Construct a timing bitmap, for use in time-based conditionals. | |
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_check_timing (const struct ast_timing *i) |
Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified. | |
int | ast_check_timing2 (const struct ast_timing *i, const struct timeval tv) |
Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified. | |
char * | ast_complete_applications (const char *line, const char *word, int state) |
Command completion for the list of installed applications. | |
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). | |
struct ast_context * | ast_context_find (const char *name) |
Find a context. | |
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. | |
int | ast_context_lockmacro (const char *context) |
locks the macrolock in the given given context | |
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) |
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. | |
int | ast_context_unlockmacro (const char *context) |
Unlocks the macrolock in the given context. | |
int | ast_context_verify_includes (struct ast_context *con) |
Verifies includes in an ast_contect structure. | |
struct ast_custom_function * | ast_custom_function_find (const char *name) |
int | ast_custom_function_unregister (struct ast_custom_function *acf) |
Unregister a custom function. | |
int | ast_destroy_timing (struct ast_timing *i) |
Deallocates memory structures associated with a timing bitmap. | |
enum ast_extension_states | ast_devstate_to_extenstate (enum ast_device_state devstate) |
Map devstate to an extension state. | |
int | ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Determine whether an extension exists. | |
int | ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_extension_close (const char *pattern, const char *data, int needmore) |
int | ast_extension_cmp (const char *a, const char *b) |
Determine if one extension should match before another. | |
int | ast_extension_match (const char *pattern, const char *data) |
Determine if a given extension matches a given pattern (in NXX format). | |
int | ast_extension_state (struct ast_channel *c, const char *context, const char *exten) |
Check extension state for an extension by using hint. | |
static int | ast_extension_state2 (struct ast_exten *e) |
Check state of extension by using hints. | |
const char * | ast_extension_state2str (int extension_state) |
Return extension_state as string. | |
static int | ast_extension_state3 (struct ast_str *hint_app) |
int | ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type change_cb, void *data) |
Add watcher for extension states. | |
int | ast_extension_state_add_destroy (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data) |
Add watcher for extension states with destructor. | |
int | ast_extension_state_del (int id, ast_state_cb_type change_cb) |
ast_extension_state_del: Remove a watcher from the callback list | |
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. | |
int | ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len) |
executes a read operation on a function | |
int | ast_func_read2 (struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen) |
executes a read operation on a function | |
int | ast_func_write (struct ast_channel *chan, const char *function, const char *value) |
executes a write operation on a function | |
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_context * | ast_get_extension_context (struct ast_exten *exten) |
const char * | ast_get_extension_label (struct ast_exten *exten) |
int | ast_get_extension_matchcid (struct ast_exten *e) |
const char * | ast_get_extension_name (struct ast_exten *exten) |
int | ast_get_extension_priority (struct ast_exten *exten) |
const char * | ast_get_extension_registrar (struct ast_exten *e) |
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. | |
const char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
const char * | ast_get_ignorepat_registrar (struct ast_ignorepat *ip) |
const char * | ast_get_include_name (struct ast_include *inc) |
const char * | ast_get_include_registrar (struct ast_include *i) |
const char * | ast_get_switch_data (struct ast_sw *sw) |
int | ast_get_switch_eval (struct ast_sw *sw) |
const char * | ast_get_switch_name (struct ast_sw *sw) |
const char * | ast_get_switch_registrar (struct ast_sw *sw) |
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_exten * | ast_hint_extension (struct ast_channel *c, const char *context, const char *exten) |
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. | |
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) |
int | ast_pbx_init (void) |
int | ast_pbx_outgoing_app (const char *type, format_t format, void *data, 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) |
static int | ast_pbx_outgoing_cdr_failed (void) |
Function to post an empty cdr after a spool call fails. | |
int | ast_pbx_outgoing_exten (const char *type, format_t format, void *data, 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 **channel) |
enum ast_pbx_result | ast_pbx_run (struct ast_channel *c) |
Execute the PBX in the current thread. | |
static void * | ast_pbx_run_app (void *data) |
run the application and free the descriptor once done | |
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. | |
int | ast_register_application2 (const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod) |
Dynamically register a new dial plan application. | |
int | ast_register_switch (struct ast_switch *sw) |
Register an alternative dialplan switch. | |
static int | ast_remove_hint (struct ast_exten *e) |
Remove hint from extension. | |
int | ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn) |
Launch a new extension (i.e. new stack). | |
int | ast_str_get_hint (struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten) |
Get hint for channel. | |
const char * | ast_str_retrieve_variable (struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var) |
void | ast_str_substitute_variables (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ) |
void | ast_str_substitute_variables_full (struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used) |
void | ast_str_substitute_variables_varshead (struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ) |
static const char * | ast_str_substring (struct ast_str *value, int offset, int length) |
int | ast_unlock_context (struct ast_context *con) |
int | ast_unlock_contexts (void) |
Unlocks contexts. | |
int | ast_unregister_application (const char *app) |
Unregister an application. | |
void | ast_unregister_switch (struct ast_switch *sw) |
Unregister an alternative switch. | |
struct ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten) |
struct ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
struct ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
struct ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
struct ast_context * | ast_walk_contexts (struct ast_context *con) |
struct ast_exten * | ast_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 void * | async_wait (void *data) |
static void | cli_match_char_tree (struct match_char *node, char *prefix, int fd) |
static int | collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos) |
collect digits from the channel into the buffer. | |
static int | compare_char (const void *a, const void *b) |
static char * | complete_core_show_hint (const char *line, const char *word, int pos, int state) |
autocomplete for CLI command 'core show hint' | |
static char * | complete_show_dialplan_context (const char *line, const char *word, int pos, int state) |
static void | context_merge (struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar) |
static void | context_merge_incls_swits_igps_other_registrars (struct ast_context *new, struct ast_context *old, const char *registrar) |
static void | create_match_char_tree (struct ast_context *con) |
static void | decrease_call_count (void) |
static void | destroy_exten (struct ast_exten *e) |
static void | destroy_hint (void *obj) |
static void | destroy_pattern_tree (struct match_char *pattern_tree) |
static void | destroy_state_cb (void *doomed) |
static void | device_state_cb (const struct ast_event *event, void *unused) |
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_strncpy (char *dst, const char *src, int len) |
copy a string skipping whitespace | |
static int | extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
static struct ast_context * | find_context (const char *context) |
lookup for a context with a given name, | |
static struct ast_context * | find_context_locked (const char *context) |
lookup for a context with a given name, | |
static int | find_hint_by_cb_id (void *obj, void *arg, int flags) |
Remove a watcher from the callback list. | |
static char * | func_args (char *function) |
return a pointer to the arguments of the function, and terminates the function name with '\0' | |
static struct ast_exten * | get_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 unsigned | get_range (char *src, int max, const char *const names[], const char *msg) |
helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers. | |
static void | get_timerange (struct ast_timing *i, char *times) |
store a bitmask of valid times, one bit each 1 minute | |
static char * | handle_debug_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Send ack once. | |
static char * | handle_set_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_set_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_set_global (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_application (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_applications (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
CLI support for listing chanvar's variables in a parseable way. | |
static char * | handle_show_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_function (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_functions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_globals (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
CLI support for listing global variables in a parseable way. | |
static char * | handle_show_hint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
handle_show_hint: CLI support for listing registered dial plan hint | |
static char * | handle_show_hints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
handle_show_hints: CLI support for listing registered dial plan hints | |
static char * | handle_show_switches (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
handle_show_switches: CLI support for listing registered dial plan switches | |
static int | handle_statechange (void *datap) |
static char * | handle_unset_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | hashtab_compare_exten_labels (const void *ah_a, const void *ah_b) |
static int | hashtab_compare_exten_numbers (const void *ah_a, const void *ah_b) |
static int | hashtab_compare_extens (const void *ha_a, const void *ah_b) |
static unsigned int | hashtab_hash_extens (const void *obj) |
static unsigned int | hashtab_hash_labels (const void *obj) |
static unsigned int | hashtab_hash_priority (const void *obj) |
static int | hint_cmp (void *obj, void *arg, int flags) |
static int | hint_hash (const void *obj, const int flags) |
static int | hint_id_cmp (void *obj, void *arg, int flags) |
static int | hints_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root) |
static int | include_valid (struct ast_include *i) |
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 int | lookup_name (const char *s, const char *const names[], int max) |
Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values. | |
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, struct ast_include *rinclude) |
Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dialplan. Must check whether the difference is intentional or not. | |
static int | matchcid (const char *cidpattern, const char *callerid) |
static void | new_find_extension (const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action) |
static int | parse_variable_name (char *var, int *offset, int *length, int *isfunc) |
extract offset:length from variable name. | |
static int | pbx_builtin_answer (struct ast_channel *, const char *) |
static int | pbx_builtin_background (struct ast_channel *, const char *) |
static int | pbx_builtin_busy (struct ast_channel *, const char *) |
void | pbx_builtin_clear_globals (void) |
static int | pbx_builtin_congestion (struct ast_channel *, const char *) |
static int | pbx_builtin_execiftime (struct ast_channel *, const char *) |
const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
Return a pointer to the value of the corresponding channel variable. | |
static int | pbx_builtin_goto (struct ast_channel *, const char *) |
static int | pbx_builtin_gotoif (struct ast_channel *, const char *) |
static int | pbx_builtin_gotoiftime (struct ast_channel *, const char *) |
static int | pbx_builtin_hangup (struct ast_channel *, const char *) |
static int | pbx_builtin_importvar (struct ast_channel *, const char *) |
static int | pbx_builtin_incomplete (struct ast_channel *, const char *) |
static int | pbx_builtin_noop (struct ast_channel *, const char *) |
static int | pbx_builtin_proceeding (struct ast_channel *, const char *) |
static int | pbx_builtin_progress (struct ast_channel *, const char *) |
void | pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value) |
Add a variable to the channel variable stack, without removing any previously set value. | |
int | pbx_builtin_raise_exception (struct ast_channel *chan, const char *reason) |
static int | pbx_builtin_resetcdr (struct ast_channel *, const char *) |
static int | pbx_builtin_ringing (struct ast_channel *, const char *) |
static int | pbx_builtin_saycharacters (struct ast_channel *, const char *) |
static int | pbx_builtin_saydigits (struct ast_channel *, const char *) |
static int | pbx_builtin_saynumber (struct ast_channel *, const char *) |
static int | pbx_builtin_sayphonetic (struct ast_channel *, const char *) |
int | pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf) |
Create a human-readable string, specifying all variables and their corresponding values. | |
static int | pbx_builtin_setamaflags (struct ast_channel *, const char *) |
int | pbx_builtin_setvar (struct ast_channel *chan, const char *data) |
Parse and set a single channel variable, where the name and value are separated with an '=' character. | |
int | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
Add a variable to the channel variable stack, removing the most recently set value for the same name. | |
int | pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *vdata) |
Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character. | |
static int | pbx_builtin_wait (struct ast_channel *, const char *) |
static int | pbx_builtin_waitexten (struct ast_channel *, const char *) |
int | pbx_checkcondition (const char *condition) |
Evaluate a condition. | |
static void | pbx_destroy (struct ast_pbx *p) |
int | pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data) |
Execute an application. | |
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_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) |
struct ast_app * | pbx_findapp (const char *app) |
Find application handle in linked list. | |
static struct ast_switch * | pbx_findswitch (const char *sw) |
static int | pbx_parseable_goto (struct ast_channel *chan, const char *goto_string, int async) |
void | pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp) |
Support for Asterisk built-in variables in the dialplan. | |
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_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e) |
void | pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count) |
void | pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used) |
void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
static void * | pbx_thread (void *data) |
static void | print_app_docs (struct ast_app *aa, int fd) |
static void | print_ext (struct ast_exten *e, char *buf, int buflen) |
helper function to print an extension | |
static int | raise_exception (struct ast_channel *chan, const char *reason, int priority) |
static 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, struct ast_include *rinclude, int includecount, const char *includes[]) |
static int | statecbs_cmp (void *obj, void *arg, int flags) |
static char * | substring (const char *value, int offset, int length, char *workspace, size_t workspace_len) |
takes a substring. It is ok to call with value == workspace. | |
static int | testtime_write (struct ast_channel *chan, const char *cmd, char *var, const char *value) |
static struct ast_exten * | trie_find_next_match (struct match_char *node) |
static void | unload_pbx (void) |
static 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) |
static void | wait_for_hangup (struct ast_channel *chan, const void *data) |
Variables | |
static int | autofallthrough = 1 |
static struct ast_app_option | background_opts [128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },} |
static struct pbx_builtin | builtins [] |
Declaration of builtin applications. | |
static ast_mutex_t | conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
Lock for the ast_context list. | |
static ast_mutex_t | context_merge_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete. | |
static struct ast_context * | contexts |
static struct ast_hashtab * | contexts_table = NULL |
static int | countcalls |
static const char *const | days [] |
static struct ast_event_sub * | device_state_sub |
Subscription for device state change events. | |
static struct ast_taskprocessor * | device_state_tps |
static struct ast_custom_function | exception_function |
static struct ast_datastore_info | exception_store_info |
static int | extenpatternmatchnew = 0 |
static struct cfextension_states | extension_states [] |
static struct ast_threadstorage | extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , } |
static struct varshead | globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE |
static ast_rwlock_t | globalslock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } |
static struct ao2_container * | hints |
static struct ast_data_handler | hints_data_provider |
static ast_mutex_t | maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
static const char *const | months [] |
static char * | overrideswitch = NULL |
static struct ast_cli_entry | pbx_cli [] |
static struct ast_data_entry | pbx_data_providers [] |
static struct ast_app_option | resetcdr_opts [128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },} |
static struct ao2_container * | statecbs |
static int | stateid = 1 |
static struct ast_threadstorage | switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , } |
static struct ast_custom_function | testtime_function |
static int | totalcalls |
static struct ast_app_option | waitexten_opts [128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },} |
Core PBX routines.
Definition in file pbx.c.
#define AST_PBX_MAX_STACK 128 |
#define BACKGROUND_MATCHEXTEN (1 << 2) |
Definition at line 799 of file pbx.c.
Referenced by pbx_builtin_background().
#define BACKGROUND_NOANSWER (1 << 1) |
Definition at line 798 of file pbx.c.
Referenced by pbx_builtin_background().
#define BACKGROUND_PLAYBACK (1 << 3) |
Definition at line 800 of file pbx.c.
Referenced by pbx_builtin_background().
#define BACKGROUND_SKIP (1 << 0) |
Definition at line 797 of file pbx.c.
Referenced by pbx_builtin_background().
#define BITS_PER 8 |
Referenced by ext_cmp_pattern_pos().
#define EXT_DATA_SIZE 8192 |
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 786 of file pbx.c.
Referenced by pbx_extension_helper(), and realtime_exec().
#define HASH_EXTENHINT_SIZE 563 |
Definition at line 975 of file pbx.c.
Referenced by ast_pbx_init().
#define INC_DST_OVERFLOW_CHECK |
Referenced by get_pattern_node().
#define NEW_MATCHER_CHK_MATCH |
Referenced by new_find_extension().
#define NEW_MATCHER_RECURSE |
Referenced by new_find_extension().
#define VAR_BUF_SIZE 4096 |
Definition at line 791 of file pbx.c.
Referenced by ast_add_extension2_lockopt(), ast_func_read2(), pbx_builtin_importvar(), and pbx_substitute_variables_helper_full().
#define WAITEXTEN_DIALTONE (1 << 1) |
Definition at line 810 of file pbx.c.
Referenced by pbx_builtin_waitexten().
#define WAITEXTEN_MOH (1 << 0) |
Definition at line 809 of file pbx.c.
Referenced by pbx_builtin_waitexten().
void __ast_context_destroy | ( | struct ast_context * | list, | |
struct ast_hashtab * | contexttab, | |||
struct ast_context * | con, | |||
const char * | registrar | |||
) |
Definition at line 9390 of file pbx.c.
References __ast_internal_context_destroy(), ast_context::alts, ast_context_remove_extension_callerid2(), ast_copy_string(), ast_debug, ast_free, ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_remove_this_object(), ast_hashtab_start_traversal(), AST_LIST_EMPTY, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_MAX_EXTENSION, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, contexts, ast_exten::exten, ast_context::ignorepats, ast_context::includes, ast_context::name, ast_include::next, ast_ignorepat::next, ast_context::next, ast_sw::next, ast_exten::peer_table, ast_exten::priority, ast_context::refcount, ast_exten::registrar, ast_sw::registrar, ast_include::registrar, ast_ignorepat::registrar, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by ast_context_destroy().
09391 { 09392 struct ast_context *tmp, *tmpl=NULL; 09393 struct ast_exten *exten_item, *prio_item; 09394 09395 for (tmp = list; tmp; ) { 09396 struct ast_context *next = NULL; /* next starting point */ 09397 /* The following code used to skip forward to the next 09398 context with matching registrar, but this didn't 09399 make sense; individual priorities registrar'd to 09400 the matching registrar could occur in any context! */ 09401 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar); 09402 if (con) { 09403 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */ 09404 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar); 09405 if ( !strcasecmp(tmp->name, con->name) ) { 09406 break; /* found it */ 09407 } 09408 } 09409 } 09410 09411 if (!tmp) /* not found, we are done */ 09412 break; 09413 ast_wrlock_context(tmp); 09414 09415 if (registrar) { 09416 /* then search thru and remove any extens that match registrar. */ 09417 struct ast_hashtab_iter *exten_iter; 09418 struct ast_hashtab_iter *prio_iter; 09419 struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL; 09420 struct ast_include *i, *pi = NULL, *ni = NULL; 09421 struct ast_sw *sw = NULL; 09422 09423 /* remove any ignorepats whose registrar matches */ 09424 for (ip = tmp->ignorepats; ip; ip = ipn) { 09425 ipn = ip->next; 09426 if (!strcmp(ip->registrar, registrar)) { 09427 if (ipl) { 09428 ipl->next = ip->next; 09429 ast_free(ip); 09430 continue; /* don't change ipl */ 09431 } else { 09432 tmp->ignorepats = ip->next; 09433 ast_free(ip); 09434 continue; /* don't change ipl */ 09435 } 09436 } 09437 ipl = ip; 09438 } 09439 /* remove any includes whose registrar matches */ 09440 for (i = tmp->includes; i; i = ni) { 09441 ni = i->next; 09442 if (strcmp(i->registrar, registrar) == 0) { 09443 /* remove from list */ 09444 if (pi) { 09445 pi->next = i->next; 09446 /* free include */ 09447 ast_free(i); 09448 continue; /* don't change pi */ 09449 } else { 09450 tmp->includes = i->next; 09451 /* free include */ 09452 ast_free(i); 09453 continue; /* don't change pi */ 09454 } 09455 } 09456 pi = i; 09457 } 09458 /* remove any switches whose registrar matches */ 09459 AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) { 09460 if (strcmp(sw->registrar,registrar) == 0) { 09461 AST_LIST_REMOVE_CURRENT(list); 09462 ast_free(sw); 09463 } 09464 } 09465 AST_LIST_TRAVERSE_SAFE_END; 09466 09467 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */ 09468 exten_iter = ast_hashtab_start_traversal(tmp->root_table); 09469 while ((exten_item=ast_hashtab_next(exten_iter))) { 09470 int end_traversal = 1; 09471 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 09472 while ((prio_item=ast_hashtab_next(prio_iter))) { 09473 char extension[AST_MAX_EXTENSION]; 09474 char cidmatch[AST_MAX_EXTENSION]; 09475 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) { 09476 continue; 09477 } 09478 ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n", 09479 tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL); 09480 /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */ 09481 ast_copy_string(extension, prio_item->exten, sizeof(extension)); 09482 if (prio_item->cidmatch) { 09483 ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch)); 09484 } 09485 end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, prio_item->cidmatch ? cidmatch : NULL, 1, NULL, 1); 09486 } 09487 /* Explanation: 09488 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This 09489 * destruction includes destroying the exten's peer_table, which we are currently traversing. If 09490 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed 09491 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result 09492 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply 09493 * free the iterator 09494 */ 09495 if (end_traversal) { 09496 ast_hashtab_end_traversal(prio_iter); 09497 } else { 09498 ast_free(prio_iter); 09499 } 09500 } 09501 ast_hashtab_end_traversal(exten_iter); 09502 } 09503 09504 /* delete the context if it's registrar matches, is empty, has refcount of 1, */ 09505 /* it's not empty, if it has includes, ignorepats, or switches that are registered from 09506 another registrar. It's not empty if there are any extensions */ 09507 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) { 09508 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 09509 ast_hashtab_remove_this_object(contexttab, tmp); 09510 09511 next = tmp->next; 09512 if (tmpl) 09513 tmpl->next = next; 09514 else 09515 contexts = next; 09516 /* Okay, now we're safe to let it go -- in a sense, we were 09517 ready to let it go as soon as we locked it. */ 09518 ast_unlock_context(tmp); 09519 __ast_internal_context_destroy(tmp); 09520 } else { 09521 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar, 09522 tmp->refcount, tmp->root); 09523 ast_unlock_context(tmp); 09524 next = tmp->next; 09525 tmpl = tmp; 09526 } 09527 } else if (con) { 09528 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar); 09529 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 09530 ast_hashtab_remove_this_object(contexttab, tmp); 09531 09532 next = tmp->next; 09533 if (tmpl) 09534 tmpl->next = next; 09535 else 09536 contexts = next; 09537 /* Okay, now we're safe to let it go -- in a sense, we were 09538 ready to let it go as soon as we locked it. */ 09539 ast_unlock_context(tmp); 09540 __ast_internal_context_destroy(tmp); 09541 } 09542 09543 /* if we have a specific match, we are done, otherwise continue */ 09544 tmp = con ? NULL : next; 09545 } 09546 }
int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
struct ast_module * | mod | |||
) |
Register a custom function.
Definition at line 3814 of file pbx.c.
References acf_retrieve_docs(), ast_custom_function::acflist, ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_verb, COLOR_BRCYAN, ast_custom_function::docsrc, LOG_ERROR, ast_custom_function::mod, ast_custom_function::name, and term_color().
Referenced by load_pbx().
03815 { 03816 struct ast_custom_function *cur; 03817 char tmps[80]; 03818 03819 if (!acf) { 03820 return -1; 03821 } 03822 03823 acf->mod = mod; 03824 #ifdef AST_XML_DOCS 03825 acf->docsrc = AST_STATIC_DOC; 03826 #endif 03827 03828 if (acf_retrieve_docs(acf)) { 03829 return -1; 03830 } 03831 03832 AST_RWLIST_WRLOCK(&acf_root); 03833 03834 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03835 if (!strcmp(acf->name, cur->name)) { 03836 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03837 AST_RWLIST_UNLOCK(&acf_root); 03838 return -1; 03839 } 03840 } 03841 03842 /* Store in alphabetical order */ 03843 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03844 if (strcasecmp(acf->name, cur->name) < 0) { 03845 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03846 break; 03847 } 03848 } 03849 AST_RWLIST_TRAVERSE_SAFE_END; 03850 03851 if (!cur) { 03852 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03853 } 03854 03855 AST_RWLIST_UNLOCK(&acf_root); 03856 03857 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03858 03859 return 0; 03860 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 10820 of file pbx.c.
References ast_async_goto(), ast_exists_extension(), ast_explicit_goto(), AST_PBX_GOTO_FAILED, ast_channel::caller, ast_channel::context, ast_channel::exten, ast_party_caller::id, ast_party_id::number, S_COR, ast_party_number::str, and ast_party_number::valid.
Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().
10821 { 10822 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 10823 10824 if (!chan) 10825 return -2; 10826 10827 if (context == NULL) 10828 context = chan->context; 10829 if (exten == NULL) 10830 exten = chan->exten; 10831 10832 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 10833 if (ast_exists_extension(chan, context, exten, priority, 10834 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) 10835 return goto_func(chan, context, exten, priority); 10836 else { 10837 return AST_PBX_GOTO_FAILED; 10838 } 10839 }
static void __ast_internal_context_destroy | ( | struct ast_context * | con | ) | [static] |
Definition at line 9343 of file pbx.c.
References ast_context::alts, ast_free, ast_hashtab_destroy(), AST_LIST_REMOVE_HEAD, ast_rwlock_destroy, destroy_exten(), destroy_pattern_tree(), el, ast_context::ignorepats, ast_context::includes, ast_context::lock, ast_exten::next, ast_ignorepat::next, ast_include::next, ast_context::pattern_tree, ast_exten::peer, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by __ast_context_destroy(), and ast_merge_contexts_and_delete().
09344 { 09345 struct ast_include *tmpi; 09346 struct ast_sw *sw; 09347 struct ast_exten *e, *el, *en; 09348 struct ast_ignorepat *ipi; 09349 struct ast_context *tmp = con; 09350 09351 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 09352 struct ast_include *tmpil = tmpi; 09353 tmpi = tmpi->next; 09354 ast_free(tmpil); 09355 } 09356 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 09357 struct ast_ignorepat *ipl = ipi; 09358 ipi = ipi->next; 09359 ast_free(ipl); 09360 } 09361 if (tmp->registrar) 09362 ast_free(tmp->registrar); 09363 09364 /* destroy the hash tabs */ 09365 if (tmp->root_table) { 09366 ast_hashtab_destroy(tmp->root_table, 0); 09367 } 09368 /* and destroy the pattern tree */ 09369 if (tmp->pattern_tree) 09370 destroy_pattern_tree(tmp->pattern_tree); 09371 09372 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 09373 ast_free(sw); 09374 for (e = tmp->root; e;) { 09375 for (en = e->peer; en;) { 09376 el = en; 09377 en = en->peer; 09378 destroy_exten(el); 09379 } 09380 el = e; 09381 e = e->next; 09382 destroy_exten(el); 09383 } 09384 tmp->root = NULL; 09385 ast_rwlock_destroy(&tmp->lock); 09386 ast_free(tmp); 09387 }
static enum ast_pbx_result __ast_pbx_run | ( | struct ast_channel * | c, | |
struct ast_pbx_args * | args | |||
) | [static] |
Definition at line 5173 of file pbx.c.
References ast_channel::_softhangup, ast_calloc, ast_cdr_end(), ast_cdr_update(), ast_channel_clear_softhangup(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, ast_copy_string(), ast_debug, ast_exists_extension(), AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, ast_free, ast_hangup(), ast_log(), ast_matchmore_extension(), ast_opt_end_cdr_before_h_exten, AST_PBX_ERROR, AST_PBX_INCOMPLETE, 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, ast_channel::caller, ast_channel::cdr, collect_digits(), ast_channel::context, ast_pbx::dtimeoutms, ast_channel::exten, ast_party_caller::id, LOG_WARNING, ast_pbx_args::no_hangup_chan, ast_party_id::number, ast_channel::pbx, pbx_builtin_busy(), pbx_builtin_congestion(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_destroy(), ast_channel::priority, raise_exception(), ast_pbx::rtimeoutms, S_COR, set_ext_pri(), status, ast_party_number::str, ast_party_number::valid, and ast_channel::whentohangup.
Referenced by ast_pbx_run_args(), and pbx_thread().
05175 { 05176 int found = 0; /* set if we find at least one match */ 05177 int res = 0; 05178 int autoloopflag; 05179 int error = 0; /* set an error conditions */ 05180 05181 /* A little initial setup here */ 05182 if (c->pbx) { 05183 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 05184 /* XXX and now what ? */ 05185 ast_free(c->pbx); 05186 } 05187 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 05188 return -1; 05189 /* Set reasonable defaults */ 05190 c->pbx->rtimeoutms = 10000; 05191 c->pbx->dtimeoutms = 5000; 05192 05193 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 05194 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 05195 05196 /* Start by trying whatever the channel is set to */ 05197 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 05198 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05199 /* If not successful fall back to 's' */ 05200 ast_verb(2, "Starting %s at %s,%s,%d failed so falling back to exten 's'\n", c->name, c->context, c->exten, c->priority); 05201 /* XXX the original code used the existing priority in the call to 05202 * ast_exists_extension(), and reset it to 1 afterwards. 05203 * I believe the correct thing is to set it to 1 immediately. 05204 */ 05205 set_ext_pri(c, "s", 1); 05206 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 05207 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05208 /* JK02: And finally back to default if everything else failed */ 05209 ast_verb(2, "Starting %s at %s,%s,%d still failed so falling back to context 'default'\n", c->name, c->context, c->exten, c->priority); 05210 ast_copy_string(c->context, "default", sizeof(c->context)); 05211 } 05212 } 05213 ast_channel_lock(c); 05214 if (c->cdr) { 05215 /* allow CDR variables that have been collected after channel was created to be visible during call */ 05216 ast_cdr_update(c); 05217 } 05218 ast_channel_unlock(c); 05219 for (;;) { 05220 char dst_exten[256]; /* buffer to accumulate digits */ 05221 int pos = 0; /* XXX should check bounds */ 05222 int digit = 0; 05223 int invalid = 0; 05224 int timeout = 0; 05225 05226 /* No digits pressed yet */ 05227 dst_exten[pos] = '\0'; 05228 05229 /* loop on priorities in this context/exten */ 05230 while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority, 05231 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 05232 &found, 1))) { 05233 if (!ast_check_hangup(c)) { 05234 ++c->priority; 05235 continue; 05236 } 05237 05238 /* Check softhangup flags. */ 05239 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05240 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05241 continue; 05242 } 05243 if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05244 if (ast_exists_extension(c, c->context, "T", 1, 05245 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05246 set_ext_pri(c, "T", 1); 05247 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05248 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05249 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05250 continue; 05251 } else if (ast_exists_extension(c, c->context, "e", 1, 05252 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05253 raise_exception(c, "ABSOLUTETIMEOUT", 1); 05254 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05255 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05256 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05257 continue; 05258 } 05259 05260 /* Call timed out with no special extension to jump to. */ 05261 error = 1; 05262 break; 05263 } 05264 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n", 05265 c->exten, c->priority); 05266 error = 1; 05267 break; 05268 } /* end while - from here on we can use 'break' to go out */ 05269 if (found && res) { 05270 /* Something bad happened, or a hangup has been requested. */ 05271 if (strchr("0123456789ABCDEF*#", res)) { 05272 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res); 05273 pos = 0; 05274 dst_exten[pos++] = digit = res; 05275 dst_exten[pos] = '\0'; 05276 } else if (res == AST_PBX_INCOMPLETE) { 05277 ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 05278 ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 05279 05280 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */ 05281 if (!ast_matchmore_extension(c, c->context, c->exten, 1, 05282 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05283 invalid = 1; 05284 } else { 05285 ast_copy_string(dst_exten, c->exten, sizeof(dst_exten)); 05286 digit = 1; 05287 pos = strlen(dst_exten); 05288 } 05289 } else { 05290 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05291 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05292 05293 if ((res == AST_PBX_ERROR) 05294 && ast_exists_extension(c, c->context, "e", 1, 05295 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05296 /* if we are already on the 'e' exten, don't jump to it again */ 05297 if (!strcmp(c->exten, "e")) { 05298 ast_verb(2, "Spawn extension (%s, %s, %d) exited ERROR while already on 'e' exten on '%s'\n", c->context, c->exten, c->priority, c->name); 05299 error = 1; 05300 } else { 05301 raise_exception(c, "ERROR", 1); 05302 continue; 05303 } 05304 } 05305 05306 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05307 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05308 continue; 05309 } 05310 if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05311 if (ast_exists_extension(c, c->context, "T", 1, 05312 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05313 set_ext_pri(c, "T", 1); 05314 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05315 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05316 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05317 continue; 05318 } else if (ast_exists_extension(c, c->context, "e", 1, 05319 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05320 raise_exception(c, "ABSOLUTETIMEOUT", 1); 05321 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05322 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05323 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05324 continue; 05325 } 05326 /* Call timed out with no special extension to jump to. */ 05327 } 05328 ast_channel_lock(c); 05329 if (c->cdr) { 05330 ast_cdr_update(c); 05331 } 05332 ast_channel_unlock(c); 05333 error = 1; 05334 break; 05335 } 05336 } 05337 if (error) 05338 break; 05339 05340 /*!\note 05341 * We get here on a failure of some kind: non-existing extension or 05342 * hangup. We have options, here. We can either catch the failure 05343 * and continue, or we can drop out entirely. */ 05344 05345 if (invalid 05346 || (ast_strlen_zero(dst_exten) && 05347 !ast_exists_extension(c, c->context, c->exten, 1, 05348 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL)))) { 05349 /*!\note 05350 * If there is no match at priority 1, it is not a valid extension anymore. 05351 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if 05352 * neither exist. 05353 */ 05354 if (ast_exists_extension(c, c->context, "i", 1, 05355 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05356 ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 05357 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 05358 set_ext_pri(c, "i", 1); 05359 } else if (ast_exists_extension(c, c->context, "e", 1, 05360 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05361 raise_exception(c, "INVALID", 1); 05362 } else { 05363 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 05364 c->name, c->exten, c->context); 05365 error = 1; /* we know what to do with it */ 05366 break; 05367 } 05368 } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05369 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 05370 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05371 } else { /* keypress received, get more digits for a full extension */ 05372 int waittime = 0; 05373 if (digit) 05374 waittime = c->pbx->dtimeoutms; 05375 else if (!autofallthrough) 05376 waittime = c->pbx->rtimeoutms; 05377 if (!waittime) { 05378 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 05379 if (!status) 05380 status = "UNKNOWN"; 05381 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 05382 if (!strcasecmp(status, "CONGESTION")) 05383 res = pbx_builtin_congestion(c, "10"); 05384 else if (!strcasecmp(status, "CHANUNAVAIL")) 05385 res = pbx_builtin_congestion(c, "10"); 05386 else if (!strcasecmp(status, "BUSY")) 05387 res = pbx_builtin_busy(c, "10"); 05388 error = 1; /* XXX disable message */ 05389 break; /* exit from the 'for' loop */ 05390 } 05391 05392 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 05393 break; 05394 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos])) 05395 timeout = 1; 05396 if (!timeout 05397 && ast_exists_extension(c, c->context, dst_exten, 1, 05398 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */ 05399 set_ext_pri(c, dst_exten, 1); 05400 } else { 05401 /* No such extension */ 05402 if (!timeout && !ast_strlen_zero(dst_exten)) { 05403 /* An invalid extension */ 05404 if (ast_exists_extension(c, c->context, "i", 1, 05405 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05406 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 05407 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 05408 set_ext_pri(c, "i", 1); 05409 } else if (ast_exists_extension(c, c->context, "e", 1, 05410 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05411 raise_exception(c, "INVALID", 1); 05412 } else { 05413 ast_log(LOG_WARNING, 05414 "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n", 05415 dst_exten, c->context); 05416 found = 1; /* XXX disable message */ 05417 break; 05418 } 05419 } else { 05420 /* A simple timeout */ 05421 if (ast_exists_extension(c, c->context, "t", 1, 05422 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05423 ast_verb(3, "Timeout on %s\n", c->name); 05424 set_ext_pri(c, "t", 1); 05425 } else if (ast_exists_extension(c, c->context, "e", 1, 05426 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05427 raise_exception(c, "RESPONSETIMEOUT", 1); 05428 } else { 05429 ast_log(LOG_WARNING, 05430 "Timeout, but no rule 't' or 'e' in context '%s'\n", 05431 c->context); 05432 found = 1; /* XXX disable message */ 05433 break; 05434 } 05435 } 05436 } 05437 ast_channel_lock(c); 05438 if (c->cdr) { 05439 ast_verb(2, "CDR updated on %s\n",c->name); 05440 ast_cdr_update(c); 05441 } 05442 ast_channel_unlock(c); 05443 } 05444 } 05445 05446 if (!found && !error) { 05447 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 05448 } 05449 05450 if (!args || !args->no_hangup_chan) { 05451 ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD); 05452 } 05453 05454 if ((!args || !args->no_hangup_chan) 05455 && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) 05456 && ast_exists_extension(c, c->context, "h", 1, 05457 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05458 set_ext_pri(c, "h", 1); 05459 if (c->cdr && ast_opt_end_cdr_before_h_exten) { 05460 ast_cdr_end(c->cdr); 05461 } 05462 while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, 05463 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 05464 &found, 1)) == 0) { 05465 c->priority++; 05466 } 05467 if (found && res) { 05468 /* Something bad happened, or a hangup has been requested. */ 05469 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05470 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 05471 } 05472 } 05473 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 05474 ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */ 05475 pbx_destroy(c->pbx); 05476 c->pbx = NULL; 05477 05478 if (!args || !args->no_hangup_chan) { 05479 ast_hangup(c); 05480 } 05481 05482 return 0; 05483 }
static void __init_extensionstate_buf | ( | void | ) | [static] |
static void __init_switch_data | ( | void | ) | [static] |
static int _extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 2664 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, ext_cmp_exten(), ext_cmp_exten_partial(), ext_cmp_exten_strlen(), ext_cmp_pattern(), LOG_NOTICE, and LOG_WARNING.
Referenced by extension_match_core().
02665 { 02666 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 02667 02668 #ifdef NEED_DEBUG_HERE 02669 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode); 02670 #endif 02671 02672 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 02673 int lp = ext_cmp_exten_strlen(pattern); 02674 int ld = ext_cmp_exten_strlen(data); 02675 02676 if (lp < ld) { /* pattern too short, cannot match */ 02677 #ifdef NEED_DEBUG_HERE 02678 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n"); 02679 #endif 02680 return 0; 02681 } 02682 /* depending on the mode, accept full or partial match or both */ 02683 if (mode == E_MATCH) { 02684 #ifdef NEED_DEBUG_HERE 02685 ast_log(LOG_NOTICE,"return (!ext_cmp_exten(%s,%s) when mode== E_MATCH)\n", pattern, data); 02686 #endif 02687 return !ext_cmp_exten(pattern, data); /* 1 on match, 0 on fail */ 02688 } 02689 if (ld == 0 || !ext_cmp_exten_partial(pattern, data)) { /* partial or full match */ 02690 #ifdef NEED_DEBUG_HERE 02691 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld); 02692 #endif 02693 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 02694 } else { 02695 #ifdef NEED_DEBUG_HERE 02696 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data); 02697 #endif 02698 return 0; 02699 } 02700 } 02701 if (mode == E_MATCH && data[0] == '_') { 02702 /* 02703 * XXX It is bad design that we don't know if we should be 02704 * comparing data and pattern as patterns or comparing data if 02705 * it conforms to pattern when the function is called. First, 02706 * assume they are both patterns. If they don't match then try 02707 * to see if data conforms to the given pattern. 02708 * 02709 * note: if this test is left out, then _x. will not match _x. !!! 02710 */ 02711 #ifdef NEED_DEBUG_HERE 02712 ast_log(LOG_NOTICE, "Comparing as patterns first. pattern:%s data:%s\n", pattern, data); 02713 #endif 02714 if (!ext_cmp_pattern(pattern + 1, data + 1)) { 02715 #ifdef NEED_DEBUG_HERE 02716 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n"); 02717 #endif 02718 return 1; 02719 } 02720 } 02721 02722 ++pattern; /* skip leading _ */ 02723 /* 02724 * XXX below we stop at '/' which is a separator for the CID info. However we should 02725 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 02726 */ 02727 for (;;) { 02728 const char *end; 02729 02730 /* Ignore '-' chars as eye candy fluff. */ 02731 while (*data == '-') { 02732 ++data; 02733 } 02734 while (*pattern == '-') { 02735 ++pattern; 02736 } 02737 if (!*data || !*pattern || *pattern == '/') { 02738 break; 02739 } 02740 02741 switch (*pattern) { 02742 case '[': /* a range */ 02743 ++pattern; 02744 end = strchr(pattern, ']'); /* XXX should deal with escapes ? */ 02745 if (!end) { 02746 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02747 return 0; /* unconditional failure */ 02748 } 02749 if (pattern == end) { 02750 /* Ignore empty character sets. */ 02751 ++pattern; 02752 continue; 02753 } 02754 for (; pattern < end; ++pattern) { 02755 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 02756 if (*data >= pattern[0] && *data <= pattern[2]) 02757 break; /* match found */ 02758 else { 02759 pattern += 2; /* skip a total of 3 chars */ 02760 continue; 02761 } 02762 } else if (*data == pattern[0]) 02763 break; /* match found */ 02764 } 02765 if (pattern >= end) { 02766 #ifdef NEED_DEBUG_HERE 02767 ast_log(LOG_NOTICE,"return (0) when pattern>=end\n"); 02768 #endif 02769 return 0; 02770 } 02771 pattern = end; /* skip and continue */ 02772 break; 02773 case 'n': 02774 case 'N': 02775 if (*data < '2' || *data > '9') { 02776 #ifdef NEED_DEBUG_HERE 02777 ast_log(LOG_NOTICE,"return (0) N is not matched\n"); 02778 #endif 02779 return 0; 02780 } 02781 break; 02782 case 'x': 02783 case 'X': 02784 if (*data < '0' || *data > '9') { 02785 #ifdef NEED_DEBUG_HERE 02786 ast_log(LOG_NOTICE,"return (0) X is not matched\n"); 02787 #endif 02788 return 0; 02789 } 02790 break; 02791 case 'z': 02792 case 'Z': 02793 if (*data < '1' || *data > '9') { 02794 #ifdef NEED_DEBUG_HERE 02795 ast_log(LOG_NOTICE,"return (0) Z is not matched\n"); 02796 #endif 02797 return 0; 02798 } 02799 break; 02800 case '.': /* Must match, even with more digits */ 02801 #ifdef NEED_DEBUG_HERE 02802 ast_log(LOG_NOTICE, "return (1) when '.' is matched\n"); 02803 #endif 02804 return 1; 02805 case '!': /* Early match */ 02806 #ifdef NEED_DEBUG_HERE 02807 ast_log(LOG_NOTICE, "return (2) when '!' is matched\n"); 02808 #endif 02809 return 2; 02810 default: 02811 if (*data != *pattern) { 02812 #ifdef NEED_DEBUG_HERE 02813 ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern); 02814 #endif 02815 return 0; 02816 } 02817 break; 02818 } 02819 ++data; 02820 ++pattern; 02821 } 02822 if (*data) /* data longer than pattern, no match */ { 02823 #ifdef NEED_DEBUG_HERE 02824 ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n"); 02825 #endif 02826 return 0; 02827 } 02828 02829 /* 02830 * match so far, but ran off the end of data. 02831 * Depending on what is next, determine match or not. 02832 */ 02833 if (*pattern == '\0' || *pattern == '/') { /* exact match */ 02834 #ifdef NEED_DEBUG_HERE 02835 ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1); 02836 #endif 02837 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 02838 } else if (*pattern == '!') { /* early match */ 02839 #ifdef NEED_DEBUG_HERE 02840 ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n"); 02841 #endif 02842 return 2; 02843 } else { /* partial match */ 02844 #ifdef NEED_DEBUG_HERE 02845 ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1); 02846 #endif 02847 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 02848 } 02849 }
static int acf_exception_read | ( | struct ast_channel * | chan, | |
const char * | name, | |||
char * | data, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 3551 of file pbx.c.
References ast_channel_datastore_find(), ast_copy_string(), pbx_exception::context, ast_datastore::data, exception_store_info, pbx_exception::exten, pbx_exception::priority, and pbx_exception::reason.
03552 { 03553 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03554 struct pbx_exception *exception = NULL; 03555 if (!ds || !ds->data) 03556 return -1; 03557 exception = ds->data; 03558 if (!strcasecmp(data, "REASON")) 03559 ast_copy_string(buf, exception->reason, buflen); 03560 else if (!strcasecmp(data, "CONTEXT")) 03561 ast_copy_string(buf, exception->context, buflen); 03562 else if (!strncasecmp(data, "EXTEN", 5)) 03563 ast_copy_string(buf, exception->exten, buflen); 03564 else if (!strcasecmp(data, "PRIORITY")) 03565 snprintf(buf, buflen, "%d", exception->priority); 03566 else 03567 return -1; 03568 return 0; 03569 }
static int acf_retrieve_docs | ( | struct ast_custom_function * | acf | ) | [static] |
Definition at line 3769 of file pbx.c.
References ast_free, ast_module_name(), ast_string_field_init, ast_string_field_set, ast_strlen_zero(), AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), desc, ast_custom_function::docsrc, ast_custom_function::mod, ast_custom_function::name, and synopsis.
Referenced by __ast_custom_function_register().
03770 { 03771 #ifdef AST_XML_DOCS 03772 char *tmpxml; 03773 03774 /* Let's try to find it in the Documentation XML */ 03775 if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) { 03776 return 0; 03777 } 03778 03779 if (ast_string_field_init(acf, 128)) { 03780 return -1; 03781 } 03782 03783 /* load synopsis */ 03784 tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod)); 03785 ast_string_field_set(acf, synopsis, tmpxml); 03786 ast_free(tmpxml); 03787 03788 /* load description */ 03789 tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod)); 03790 ast_string_field_set(acf, desc, tmpxml); 03791 ast_free(tmpxml); 03792 03793 /* load syntax */ 03794 tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod)); 03795 ast_string_field_set(acf, syntax, tmpxml); 03796 ast_free(tmpxml); 03797 03798 /* load arguments */ 03799 tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod)); 03800 ast_string_field_set(acf, arguments, tmpxml); 03801 ast_free(tmpxml); 03802 03803 /* load seealso */ 03804 tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod)); 03805 ast_string_field_set(acf, seealso, tmpxml); 03806 ast_free(tmpxml); 03807 03808 acf->docsrc = AST_XML_DOC; 03809 #endif 03810 03811 return 0; 03812 }
static struct match_char * add_exten_to_pattern_tree | ( | struct ast_context * | con, | |
struct ast_exten * | e1, | |||
int | findonly | |||
) | [static, read] |
Definition at line 2147 of file pbx.c.
References add_pattern_node(), already_in_tree(), ARRAY_LEN, ast_copy_string(), ast_log(), pattern_node::buf, ast_exten::cidmatch, match_char::deleted, match_char::exten, ast_exten::exten, get_pattern_node(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, ast_exten::matchcid, match_char::next_char, and ast_context::pattern_tree.
Referenced by add_priority(), ast_add_extension2_lockopt(), ast_context_remove_extension_callerid2(), and create_match_char_tree().
02148 { 02149 struct match_char *m1 = NULL; 02150 struct match_char *m2 = NULL; 02151 struct match_char **m0; 02152 const char *pos; 02153 int already; 02154 int pattern = 0; 02155 int idx_cur; 02156 int idx_next; 02157 char extenbuf[512]; 02158 struct pattern_node pat_node[2]; 02159 02160 if (e1->matchcid) { 02161 if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) { 02162 ast_log(LOG_ERROR, 02163 "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", 02164 e1->exten, e1->cidmatch); 02165 return NULL; 02166 } 02167 sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe. We just checked. */ 02168 } else { 02169 ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf)); 02170 } 02171 02172 #ifdef NEED_DEBUG 02173 ast_log(LOG_DEBUG, "Adding exten %s to tree\n", extenbuf); 02174 #endif 02175 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */ 02176 m0 = &con->pattern_tree; 02177 already = 1; 02178 02179 pos = extenbuf; 02180 if (*pos == '_') { 02181 pattern = 1; 02182 ++pos; 02183 } 02184 idx_cur = 0; 02185 pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf); 02186 for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) { 02187 idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node); 02188 pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf); 02189 02190 /* See about adding node to tree. */ 02191 m2 = NULL; 02192 if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern)) 02193 && m2->next_char) { 02194 if (!pat_node[idx_next].buf[0]) { 02195 /* 02196 * This is the end of the pattern, but not the end of the tree. 02197 * Mark this node with the exten... a shorter pattern might win 02198 * if the longer one doesn't match. 02199 */ 02200 if (findonly) { 02201 return m2; 02202 } 02203 if (m2->exten) { 02204 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", 02205 m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten); 02206 } 02207 m2->exten = e1; 02208 m2->deleted = 0; 02209 } 02210 m1 = m2->next_char; /* m1 points to the node to compare against */ 02211 m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */ 02212 } else { /* not already OR not m2 OR nor m2->next_char */ 02213 if (m2) { 02214 if (findonly) { 02215 return m2; 02216 } 02217 m1 = m2; /* while m0 stays the same */ 02218 } else { 02219 if (findonly) { 02220 return m1; 02221 } 02222 m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0); 02223 if (!m1) { /* m1 is the node just added */ 02224 return NULL; 02225 } 02226 m0 = &m1->next_char; 02227 } 02228 if (!pat_node[idx_next].buf[0]) { 02229 if (m2 && m2->exten) { 02230 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", 02231 m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten); 02232 } 02233 m1->deleted = 0; 02234 m1->exten = e1; 02235 } 02236 02237 /* The 'already' variable is a mini-optimization designed to make it so that we 02238 * don't have to call already_in_tree when we know it will return false. 02239 */ 02240 already = 0; 02241 } 02242 } 02243 return m1; 02244 }
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, read] |
Definition at line 1949 of file pbx.c.
References ast_calloc, pattern_node::buf, insert_in_next_chars_alt_char_list(), match_char::is_pattern, match_char::next_char, ast_context::pattern_tree, pattern_node::specif, match_char::specificity, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01950 { 01951 struct match_char *m; 01952 01953 if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) { 01954 return NULL; 01955 } 01956 01957 /* strcpy is safe here since we know its size and have allocated 01958 * just enough space for when we allocated m 01959 */ 01960 strcpy(m->x, pattern->buf); 01961 01962 /* the specificity scores are the same as used in the old 01963 pattern matcher. */ 01964 m->is_pattern = is_pattern; 01965 if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') { 01966 m->specificity = 0x0832; 01967 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') { 01968 m->specificity = 0x0931; 01969 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') { 01970 m->specificity = 0x0a30; 01971 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') { 01972 m->specificity = 0x18000; 01973 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') { 01974 m->specificity = 0x28000; 01975 } else { 01976 m->specificity = pattern->specif; 01977 } 01978 01979 if (!con->pattern_tree) { 01980 insert_in_next_chars_alt_char_list(&con->pattern_tree, m); 01981 } else { 01982 if (already) { /* switch to the new regime (traversing vs appending)*/ 01983 insert_in_next_chars_alt_char_list(nextcharptr, m); 01984 } else { 01985 insert_in_next_chars_alt_char_list(¤t->next_char, m); 01986 } 01987 } 01988 01989 return m; 01990 }
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.
0 | on success. | |
-1 | on failure. |
Definition at line 8529 of file pbx.c.
References add_exten_to_pattern_tree(), ast_add_hint(), ast_change_hint(), ast_free, ast_hashtab_insert_safe(), ast_hashtab_remove_object_via_lookup(), ast_log(), ast_exten::data, ast_exten::datad, match_char::exten, ast_exten::exten, ast_exten::label, LOG_ERROR, LOG_WARNING, ast_context::name, ast_exten::next, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, PRIORITY_HINT, ast_context::root, ast_context::root_table, and match_char::x.
Referenced by ast_add_extension2_lockopt().
08531 { 08532 struct ast_exten *ep; 08533 struct ast_exten *eh=e; 08534 int repeated_label = 0; /* Track if this label is a repeat, assume no. */ 08535 08536 for (ep = NULL; e ; ep = e, e = e->peer) { 08537 if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) { 08538 if (strcmp(e->exten, tmp->exten)) { 08539 ast_log(LOG_WARNING, 08540 "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n", 08541 tmp->exten, tmp->priority, con->name, tmp->label, e->exten, e->priority); 08542 } else { 08543 ast_log(LOG_WARNING, 08544 "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n", 08545 tmp->exten, tmp->priority, con->name, tmp->label, e->priority); 08546 } 08547 repeated_label = 1; 08548 } 08549 if (e->priority >= tmp->priority) { 08550 break; 08551 } 08552 } 08553 08554 if (repeated_label) { /* Discard the label since it's a repeat. */ 08555 tmp->label = NULL; 08556 } 08557 08558 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 08559 ast_hashtab_insert_safe(eh->peer_table, tmp); 08560 08561 if (tmp->label) { 08562 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08563 } 08564 ep->peer = tmp; 08565 return 0; /* success */ 08566 } 08567 if (e->priority == tmp->priority) { 08568 /* Can't have something exactly the same. Is this a 08569 replacement? If so, replace, otherwise, bonk. */ 08570 if (!replace) { 08571 if (strcmp(e->exten, tmp->exten)) { 08572 ast_log(LOG_WARNING, 08573 "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n", 08574 tmp->exten, tmp->priority, con->name, e->exten); 08575 } else { 08576 ast_log(LOG_WARNING, 08577 "Unable to register extension '%s' priority %d in '%s', already in use\n", 08578 tmp->exten, tmp->priority, con->name); 08579 } 08580 if (tmp->datad) { 08581 tmp->datad(tmp->data); 08582 /* if you free this, null it out */ 08583 tmp->data = NULL; 08584 } 08585 08586 ast_free(tmp); 08587 return -1; 08588 } 08589 /* we are replacing e, so copy the link fields and then update 08590 * whoever pointed to e to point to us 08591 */ 08592 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 08593 tmp->peer = e->peer; /* always meaningful */ 08594 if (ep) { /* We're in the peer list, just insert ourselves */ 08595 ast_hashtab_remove_object_via_lookup(eh->peer_table,e); 08596 08597 if (e->label) { 08598 ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e); 08599 } 08600 08601 ast_hashtab_insert_safe(eh->peer_table,tmp); 08602 if (tmp->label) { 08603 ast_hashtab_insert_safe(eh->peer_label_table,tmp); 08604 } 08605 08606 ep->peer = tmp; 08607 } else if (el) { /* We're the first extension. Take over e's functions */ 08608 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 08609 tmp->peer_table = e->peer_table; 08610 tmp->peer_label_table = e->peer_label_table; 08611 ast_hashtab_remove_object_via_lookup(tmp->peer_table,e); 08612 ast_hashtab_insert_safe(tmp->peer_table,tmp); 08613 if (e->label) { 08614 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 08615 } 08616 if (tmp->label) { 08617 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08618 } 08619 08620 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08621 ast_hashtab_insert_safe(con->root_table, tmp); 08622 el->next = tmp; 08623 /* The pattern trie points to this exten; replace the pointer, 08624 and all will be well */ 08625 if (x) { /* if the trie isn't formed yet, don't sweat this */ 08626 if (x->exten) { /* this test for safety purposes */ 08627 x->exten = tmp; /* replace what would become a bad pointer */ 08628 } else { 08629 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 08630 } 08631 } 08632 } else { /* We're the very first extension. */ 08633 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 08634 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08635 ast_hashtab_insert_safe(con->root_table, tmp); 08636 tmp->peer_table = e->peer_table; 08637 tmp->peer_label_table = e->peer_label_table; 08638 ast_hashtab_remove_object_via_lookup(tmp->peer_table, e); 08639 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08640 if (e->label) { 08641 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 08642 } 08643 if (tmp->label) { 08644 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08645 } 08646 08647 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08648 ast_hashtab_insert_safe(con->root_table, tmp); 08649 con->root = tmp; 08650 /* The pattern trie points to this exten; replace the pointer, 08651 and all will be well */ 08652 if (x) { /* if the trie isn't formed yet; no problem */ 08653 if (x->exten) { /* this test for safety purposes */ 08654 x->exten = tmp; /* replace what would become a bad pointer */ 08655 } else { 08656 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 08657 } 08658 } 08659 } 08660 if (tmp->priority == PRIORITY_HINT) 08661 ast_change_hint(e,tmp); 08662 /* Destroy the old one */ 08663 if (e->datad) 08664 e->datad(e->data); 08665 ast_free(e); 08666 } else { /* Slip ourselves in just before e */ 08667 tmp->peer = e; 08668 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 08669 if (ep) { /* Easy enough, we're just in the peer list */ 08670 if (tmp->label) { 08671 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08672 } 08673 ast_hashtab_insert_safe(eh->peer_table, tmp); 08674 ep->peer = tmp; 08675 } else { /* we are the first in some peer list, so link in the ext list */ 08676 tmp->peer_table = e->peer_table; 08677 tmp->peer_label_table = e->peer_label_table; 08678 e->peer_table = 0; 08679 e->peer_label_table = 0; 08680 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08681 if (tmp->label) { 08682 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08683 } 08684 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08685 ast_hashtab_insert_safe(con->root_table, tmp); 08686 if (el) 08687 el->next = tmp; /* in the middle... */ 08688 else 08689 con->root = tmp; /* ... or at the head */ 08690 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 08691 } 08692 /* And immediately return success. */ 08693 if (tmp->priority == PRIORITY_HINT) { 08694 ast_add_hint(tmp); 08695 } 08696 } 08697 return 0; 08698 }
static struct match_char * already_in_tree | ( | struct match_char * | current, | |
char * | pat, | |||
int | is_pattern | |||
) | [static, read] |
Definition at line 1887 of file pbx.c.
References match_char::alt_char, match_char::is_pattern, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01888 { 01889 struct match_char *t; 01890 01891 if (!current) { 01892 return 0; 01893 } 01894 01895 for (t = current; t; t = t->alt_char) { 01896 if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */ 01897 return t; 01898 } 01899 } 01900 01901 return 0; 01902 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5631 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05632 { 05633 return countcalls; 05634 }
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.
context | context to add the extension to | |
replace | ||
extension | extension to add | |
priority | priority level of extension addition | |
label | extension label | |
callerid | pattern to match CallerID, or NULL to match any CallerID | |
application | application to run on the extension with that priority level | |
data | data to pass to the application | |
datad | ||
registrar | who registered the extension |
0 | success | |
-1 | failure |
Definition at line 8364 of file pbx.c.
References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_extension_state(), ast_extension_state_add_destroy(), handle_cli_dialplan_add_extension(), manage_parked_call(), park_add_hints(), park_call_full(), parkinglot_activate(), register_exten(), register_peer_exten(), and RegisterExtension().
08367 { 08368 int ret = -1; 08369 struct ast_context *c; 08370 08371 c = find_context_locked(context); 08372 if (c) { 08373 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 08374 application, data, datad, registrar); 08375 ast_unlock_contexts(); 08376 } 08377 08378 return ret; 08379 }
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 | |||
) |
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 8725 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by add_extensions(), ast_add_extension(), context_merge(), load_module(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().
08729 { 08730 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, 08731 application, data, datad, registrar, 1); 08732 }
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, | |||
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 8741 of file pbx.c.
References add_exten_to_pattern_tree(), add_priority(), ast_exten::app, ast_add_hint(), ast_calloc, ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, ast_hashtab_create(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, ast_channel::context, ast_exten::data, ast_exten::datad, el, errno, ext_cmp(), ext_strncpy(), ast_exten::exten, ast_channel::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_ERROR, ast_exten::matchcid, ast_context::name, ast_exten::next, option_debug, ast_exten::parent, ast_context::pattern_tree, pbx_substitute_variables_helper(), ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, ast_context::root, ast_context::root_table, ast_exten::stuff, and VAR_BUF_SIZE.
Referenced by ast_add_extension2(), and ast_add_extension_nolock().
08745 { 08746 /* 08747 * Sort extensions (or patterns) according to the rules indicated above. 08748 * These are implemented by the function ext_cmp()). 08749 * All priorities for the same ext/pattern/cid are kept in a list, 08750 * using the 'peer' field as a link field.. 08751 */ 08752 struct ast_exten *tmp, *tmp2, *e, *el = NULL; 08753 int res; 08754 int length; 08755 char *p; 08756 char expand_buf[VAR_BUF_SIZE]; 08757 struct ast_exten dummy_exten = {0}; 08758 char dummy_name[1024]; 08759 08760 if (ast_strlen_zero(extension)) { 08761 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", 08762 con->name); 08763 return -1; 08764 } 08765 08766 /* If we are adding a hint evalulate in variables and global variables */ 08767 if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') { 08768 struct ast_channel *c = ast_dummy_channel_alloc(); 08769 08770 if (c) { 08771 ast_copy_string(c->exten, extension, sizeof(c->exten)); 08772 ast_copy_string(c->context, con->name, sizeof(c->context)); 08773 } 08774 pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf)); 08775 application = expand_buf; 08776 if (c) { 08777 ast_channel_unref(c); 08778 } 08779 } 08780 08781 length = sizeof(struct ast_exten); 08782 length += strlen(extension) + 1; 08783 length += strlen(application) + 1; 08784 if (label) 08785 length += strlen(label) + 1; 08786 if (callerid) 08787 length += strlen(callerid) + 1; 08788 else 08789 length ++; /* just the '\0' */ 08790 08791 /* Be optimistic: Build the extension structure first */ 08792 if (!(tmp = ast_calloc(1, length))) 08793 return -1; 08794 08795 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */ 08796 label = 0; 08797 08798 /* use p as dst in assignments, as the fields are const char * */ 08799 p = tmp->stuff; 08800 if (label) { 08801 tmp->label = p; 08802 strcpy(p, label); 08803 p += strlen(label) + 1; 08804 } 08805 tmp->exten = p; 08806 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 08807 tmp->priority = priority; 08808 tmp->cidmatch = p; /* but use p for assignments below */ 08809 08810 /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */ 08811 if (callerid) { 08812 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 08813 tmp->matchcid = 1; 08814 } else { 08815 *p++ = '\0'; 08816 tmp->matchcid = 0; 08817 } 08818 tmp->app = p; 08819 strcpy(p, application); 08820 tmp->parent = con; 08821 tmp->data = data; 08822 tmp->datad = datad; 08823 tmp->registrar = registrar; 08824 08825 if (lock_context) { 08826 ast_wrlock_context(con); 08827 } 08828 08829 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding 08830 an extension, and the trie exists, then we need to incrementally add this pattern to it. */ 08831 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 08832 dummy_exten.exten = dummy_name; 08833 dummy_exten.matchcid = 0; 08834 dummy_exten.cidmatch = 0; 08835 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten); 08836 if (!tmp2) { 08837 /* hmmm, not in the trie; */ 08838 add_exten_to_pattern_tree(con, tmp, 0); 08839 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */ 08840 } 08841 } 08842 res = 0; /* some compilers will think it is uninitialized otherwise */ 08843 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 08844 res = ext_cmp(e->exten, tmp->exten); 08845 if (res == 0) { /* extension match, now look at cidmatch */ 08846 if (!e->matchcid && !tmp->matchcid) 08847 res = 0; 08848 else if (tmp->matchcid && !e->matchcid) 08849 res = 1; 08850 else if (e->matchcid && !tmp->matchcid) 08851 res = -1; 08852 else 08853 res = ext_cmp(e->cidmatch, tmp->cidmatch); 08854 } 08855 if (res >= 0) 08856 break; 08857 } 08858 if (e && res == 0) { /* exact match, insert in the priority chain */ 08859 res = add_priority(con, tmp, el, e, replace); 08860 if (lock_context) { 08861 ast_unlock_context(con); 08862 } 08863 if (res < 0) { 08864 errno = EEXIST; /* XXX do we care ? */ 08865 return 0; /* XXX should we return -1 maybe ? */ 08866 } 08867 } else { 08868 /* 08869 * not an exact match, this is the first entry with this pattern, 08870 * so insert in the main list right before 'e' (if any) 08871 */ 08872 tmp->next = e; 08873 if (el) { /* there is another exten already in this context */ 08874 el->next = tmp; 08875 tmp->peer_table = ast_hashtab_create(13, 08876 hashtab_compare_exten_numbers, 08877 ast_hashtab_resize_java, 08878 ast_hashtab_newsize_java, 08879 hashtab_hash_priority, 08880 0); 08881 tmp->peer_label_table = ast_hashtab_create(7, 08882 hashtab_compare_exten_labels, 08883 ast_hashtab_resize_java, 08884 ast_hashtab_newsize_java, 08885 hashtab_hash_labels, 08886 0); 08887 if (label) { 08888 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08889 } 08890 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08891 } else { /* this is the first exten in this context */ 08892 if (!con->root_table) 08893 con->root_table = ast_hashtab_create(27, 08894 hashtab_compare_extens, 08895 ast_hashtab_resize_java, 08896 ast_hashtab_newsize_java, 08897 hashtab_hash_extens, 08898 0); 08899 con->root = tmp; 08900 con->root->peer_table = ast_hashtab_create(13, 08901 hashtab_compare_exten_numbers, 08902 ast_hashtab_resize_java, 08903 ast_hashtab_newsize_java, 08904 hashtab_hash_priority, 08905 0); 08906 con->root->peer_label_table = ast_hashtab_create(7, 08907 hashtab_compare_exten_labels, 08908 ast_hashtab_resize_java, 08909 ast_hashtab_newsize_java, 08910 hashtab_hash_labels, 08911 0); 08912 if (label) { 08913 ast_hashtab_insert_safe(con->root->peer_label_table, tmp); 08914 } 08915 ast_hashtab_insert_safe(con->root->peer_table, tmp); 08916 08917 } 08918 ast_hashtab_insert_safe(con->root_table, tmp); 08919 if (lock_context) { 08920 ast_unlock_context(con); 08921 } 08922 if (tmp->priority == PRIORITY_HINT) { 08923 ast_add_hint(tmp); 08924 } 08925 } 08926 if (option_debug) { 08927 if (tmp->matchcid) { 08928 ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 08929 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 08930 } else { 08931 ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n", 08932 tmp->exten, tmp->priority, con->name, con); 08933 } 08934 } 08935 08936 if (tmp->matchcid) { 08937 ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n", 08938 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 08939 } else { 08940 ast_verb(3, "Added extension '%s' priority %d to %s\n", 08941 tmp->exten, tmp->priority, con->name); 08942 } 08943 08944 return 0; 08945 }
static int ast_add_extension_nolock | ( | const char * | context, | |
int | replace, | |||
const char * | extension, | |||
int | priority, | |||
const char * | label, | |||
const char * | callerid, | |||
const char * | application, | |||
void * | data, | |||
void(*)(void *) | datad, | |||
const char * | registrar | |||
) | [static] |
Definition at line 8344 of file pbx.c.
References ast_add_extension2_lockopt(), and find_context().
Referenced by ast_merge_contexts_and_delete().
08347 { 08348 int ret = -1; 08349 struct ast_context *c; 08350 08351 c = find_context(context); 08352 if (c) { 08353 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid, 08354 application, data, datad, registrar, 1); 08355 } 08356 08357 return ret; 08358 }
static int ast_add_hint | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state.
Definition at line 4974 of file pbx.c.
References ao2_alloc, ao2_container_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_debug, ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), ast_hint::callbacks, destroy_hint(), ast_hint::exten, hint_id_cmp(), hints, and ast_hint::laststate.
Referenced by add_priority(), and ast_add_extension2_lockopt().
04975 { 04976 struct ast_hint *hint_new; 04977 struct ast_hint *hint_found; 04978 04979 if (!e) { 04980 return -1; 04981 } 04982 04983 /* 04984 * We must create the hint we wish to add before determining if 04985 * it is already in the hints container to avoid possible 04986 * deadlock when getting the current extension state. 04987 */ 04988 hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint); 04989 if (!hint_new) { 04990 return -1; 04991 } 04992 04993 /* Initialize new hint. */ 04994 hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp); 04995 if (!hint_new->callbacks) { 04996 ao2_ref(hint_new, -1); 04997 return -1; 04998 } 04999 hint_new->exten = e; 05000 hint_new->laststate = ast_extension_state2(e); 05001 05002 /* Prevent multiple add hints from adding the same hint at the same time. */ 05003 ao2_lock(hints); 05004 05005 /* Search if hint exists, do nothing */ 05006 hint_found = ao2_find(hints, e, 0); 05007 if (hint_found) { 05008 ao2_ref(hint_found, -1); 05009 ao2_unlock(hints); 05010 ao2_ref(hint_new, -1); 05011 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", 05012 ast_get_extension_name(e), ast_get_extension_app(e)); 05013 return -1; 05014 } 05015 05016 /* Add new hint to the hints container */ 05017 ast_debug(2, "HINTS: Adding hint %s: %s\n", 05018 ast_get_extension_name(e), ast_get_extension_app(e)); 05019 ao2_link(hints, hint_new); 05020 05021 ao2_unlock(hints); 05022 ao2_ref(hint_new, -1); 05023 05024 return 0; 05025 }
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 at line 8404 of file pbx.c.
References ast_channel::_state, accountcode, ast_channel::amaflags, amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_alloc, ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_strdupa, ast_channel::cdr, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.
Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), dahdi_handle_dtmf(), handle_request_bye(), handle_request_refer(), my_handle_dtmf(), pbx_parseable_goto(), process_ast_dsp(), process_sdp(), sip_read(), and socket_process().
08405 { 08406 int res = 0; 08407 struct ast_channel *tmpchan; 08408 struct { 08409 char *accountcode; 08410 char *exten; 08411 char *context; 08412 char *linkedid; 08413 char *name; 08414 struct ast_cdr *cdr; 08415 int amaflags; 08416 int state; 08417 format_t readformat; 08418 format_t writeformat; 08419 } tmpvars = { 0, }; 08420 08421 ast_channel_lock(chan); 08422 if (chan->pbx) { /* This channel is currently in the PBX */ 08423 ast_explicit_goto(chan, context, exten, priority + 1); 08424 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 08425 ast_channel_unlock(chan); 08426 return res; 08427 } 08428 08429 /* In order to do it when the channel doesn't really exist within 08430 * the PBX, we have to make a new channel, masquerade, and start the PBX 08431 * at the new location */ 08432 tmpvars.accountcode = ast_strdupa(chan->accountcode); 08433 tmpvars.exten = ast_strdupa(chan->exten); 08434 tmpvars.context = ast_strdupa(chan->context); 08435 tmpvars.linkedid = ast_strdupa(chan->linkedid); 08436 tmpvars.name = ast_strdupa(chan->name); 08437 tmpvars.amaflags = chan->amaflags; 08438 tmpvars.state = chan->_state; 08439 tmpvars.writeformat = chan->writeformat; 08440 tmpvars.readformat = chan->readformat; 08441 tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL; 08442 08443 ast_channel_unlock(chan); 08444 08445 /* Do not hold any channel locks while calling channel_alloc() since the function 08446 * locks the channel container when linking the new channel in. */ 08447 if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) { 08448 ast_cdr_discard(tmpvars.cdr); 08449 return -1; 08450 } 08451 08452 /* copy the cdr info over */ 08453 if (tmpvars.cdr) { 08454 ast_cdr_discard(tmpchan->cdr); 08455 tmpchan->cdr = tmpvars.cdr; 08456 tmpvars.cdr = NULL; 08457 } 08458 08459 /* Make formats okay */ 08460 tmpchan->readformat = tmpvars.readformat; 08461 tmpchan->writeformat = tmpvars.writeformat; 08462 08463 /* Setup proper location. Never hold another channel lock while calling this function. */ 08464 ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority); 08465 08466 /* Masquerade into tmp channel */ 08467 if (ast_channel_masquerade(tmpchan, chan)) { 08468 /* Failed to set up the masquerade. It's probably chan_local 08469 * in the middle of optimizing itself out. Sad. :( */ 08470 ast_hangup(tmpchan); 08471 tmpchan = NULL; 08472 res = -1; 08473 } else { 08474 ast_do_masquerade(tmpchan); 08475 /* Start the PBX going on our stolen channel */ 08476 if (ast_pbx_start(tmpchan)) { 08477 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 08478 ast_hangup(tmpchan); 08479 res = -1; 08480 } 08481 } 08482 08483 return res; 08484 }
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 8486 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
08487 { 08488 struct ast_channel *chan; 08489 int res = -1; 08490 08491 if ((chan = ast_channel_get_by_name(channame))) { 08492 res = ast_async_goto(chan, context, exten, priority); 08493 chan = ast_channel_unref(chan); 08494 } 08495 08496 return res; 08497 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10846 of file pbx.c.
References __ast_goto_if_exists().
10847 { 10848 return __ast_goto_if_exists(chan, context, exten, priority, 1); 10849 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10911 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
10912 { 10913 return pbx_parseable_goto(chan, goto_string, 1); 10914 }
int ast_build_timing | ( | struct ast_timing * | i, | |
const char * | info | |||
) |
Construct a timing bitmap, for use in time-based conditionals.
i | Pointer to an ast_timing structure. | |
info | Standard string containing a timerange, weekday range, monthday range, and month range, as well as an optional timezone. |
Returns | 1 on success or 0 on failure. |
Definition at line 7987 of file pbx.c.
References ast_strdup, ast_strdupa, ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, and ast_timing::timezone.
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
07988 { 07989 char *info; 07990 int j, num_fields, last_sep = -1; 07991 07992 /* Check for empty just in case */ 07993 if (ast_strlen_zero(info_in)) { 07994 return 0; 07995 } 07996 07997 /* make a copy just in case we were passed a static string */ 07998 info = ast_strdupa(info_in); 07999 08000 /* count the number of fields in the timespec */ 08001 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 08002 if (info[j] == ',') { 08003 last_sep = j; 08004 num_fields++; 08005 } 08006 } 08007 08008 /* save the timezone, if it is specified */ 08009 if (num_fields == 5) { 08010 i->timezone = ast_strdup(info + last_sep + 1); 08011 } else { 08012 i->timezone = NULL; 08013 } 08014 08015 /* Assume everything except time */ 08016 i->monthmask = 0xfff; /* 12 bits */ 08017 i->daymask = 0x7fffffffU; /* 31 bits */ 08018 i->dowmask = 0x7f; /* 7 bits */ 08019 /* on each call, use strsep() to move info to the next argument */ 08020 get_timerange(i, strsep(&info, "|,")); 08021 if (info) 08022 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 08023 if (info) 08024 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 08025 if (info) 08026 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 08027 return 1; 08028 }
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.
c | not really important | |
context | context to serach within | |
exten | extension to check | |
priority | priority of extension path | |
callerid | callerid of extension being searched for |
Definition at line 5115 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), analog_ss_thread(), background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), leave_voicemail(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), skinny_ss(), and valid_exit().
05116 { 05117 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 05118 }
Change hint for an extension.
Definition at line 5028 of file pbx.c.
References ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_hint::exten, hints, and OBJ_UNLINK.
Referenced by add_priority().
05029 { 05030 struct ast_hint *hint; 05031 05032 if (!oe || !ne) { 05033 return -1; 05034 } 05035 05036 ao2_lock(hints);/* Locked to hold off others while we move the hint around. */ 05037 05038 /* 05039 * Unlink the hint from the hints container as the extension 05040 * name (which is the hash value) could change. 05041 */ 05042 hint = ao2_find(hints, oe, OBJ_UNLINK); 05043 if (!hint) { 05044 ao2_unlock(hints); 05045 return -1; 05046 } 05047 05048 /* Update the hint and put it back in the hints container. */ 05049 ao2_lock(hint); 05050 hint->exten = ne; 05051 ao2_unlock(hint); 05052 ao2_link(hints, hint); 05053 05054 ao2_unlock(hints); 05055 ao2_ref(hint, -1); 05056 05057 return 0; 05058 }
int ast_check_timing | ( | const struct ast_timing * | i | ) |
Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified.
i | Pointer to an ast_timing structure. |
Returns | 1, if the time matches or 0, if the current time falls outside of the specified range. |
Definition at line 8030 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
08031 { 08032 return ast_check_timing2(i, ast_tvnow()); 08033 }
int ast_check_timing2 | ( | const struct ast_timing * | i, | |
const struct timeval | tv | |||
) |
Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified.
i | Pointer to an ast_timing structure. | |
tv | Specified time |
Returns | 1, if the time matches or 0, if the time falls outside of the specified range. |
Definition at line 8035 of file pbx.c.
References ast_localtime(), ast_log(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, ast_timing::monthmask, ast_timing::timezone, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and ast_tm::tm_wday.
Referenced by ast_check_timing(), and pbx_builtin_gotoiftime().
08036 { 08037 struct ast_tm tm; 08038 08039 ast_localtime(&tv, &tm, i->timezone); 08040 08041 /* If it's not the right month, return */ 08042 if (!(i->monthmask & (1 << tm.tm_mon))) 08043 return 0; 08044 08045 /* If it's not that time of the month.... */ 08046 /* Warning, tm_mday has range 1..31! */ 08047 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 08048 return 0; 08049 08050 /* If it's not the right day of the week */ 08051 if (!(i->dowmask & (1 << tm.tm_wday))) 08052 return 0; 08053 08054 /* Sanity check the hour just to be safe */ 08055 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 08056 ast_log(LOG_WARNING, "Insane time...\n"); 08057 return 0; 08058 } 08059 08060 /* Now the tough part, we calculate if it fits 08061 in the right time based on min/hour */ 08062 if (!(i->minmask[tm.tm_hour * 2 + (tm.tm_min >= 30 ? 1 : 0)] & (1 << (tm.tm_min >= 30 ? tm.tm_min - 30 : tm.tm_min)))) 08063 return 0; 08064 08065 /* If we got this far, then we're good */ 08066 return 1; 08067 }
char* ast_complete_applications | ( | const char * | line, | |
const char * | word, | |||
int | state | |||
) |
Command completion for the list of installed applications.
This can be called from a CLI command completion function that wants to complete from the list of available applications.
Definition at line 10916 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, and ast_app::name.
Referenced by handle_orig(), and handle_show_application().
10917 { 10918 struct ast_app *app = NULL; 10919 int which = 0; 10920 char *ret = NULL; 10921 size_t wordlen = strlen(word); 10922 10923 AST_RWLIST_RDLOCK(&apps); 10924 AST_RWLIST_TRAVERSE(&apps, app, list) { 10925 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 10926 ret = ast_strdup(app->name); 10927 break; 10928 } 10929 } 10930 AST_RWLIST_UNLOCK(&apps); 10931 10932 return ret; 10933 }
int ast_context_add_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Add an ignorepat.
context | which context to add the ignorpattern to | |
ignorepat | ignorepattern to set up for the extension | |
registrar | registrar of the ignore pattern |
Adds an ignore pattern to a particular context.
0 | on success | |
-1 | on failure |
Definition at line 8271 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
08272 { 08273 int ret = -1; 08274 struct ast_context *c; 08275 08276 c = find_context_locked(context); 08277 if (c) { 08278 ret = ast_context_add_ignorepat2(c, value, registrar); 08279 ast_unlock_contexts(); 08280 } 08281 return ret; 08282 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 8284 of file pbx.c.
References ast_calloc, ast_free, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_compile_ael2(), ast_context_add_ignorepat(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
08285 { 08286 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 08287 int length; 08288 char *pattern; 08289 length = sizeof(struct ast_ignorepat); 08290 length += strlen(value) + 1; 08291 if (!(ignorepat = ast_calloc(1, length))) 08292 return -1; 08293 /* The cast to char * is because we need to write the initial value. 08294 * The field is not supposed to be modified otherwise. Also, gcc 4.2 08295 * sees the cast as dereferencing a type-punned pointer and warns about 08296 * it. This is the workaround (we're telling gcc, yes, that's really 08297 * what we wanted to do). 08298 */ 08299 pattern = (char *) ignorepat->pattern; 08300 strcpy(pattern, value); 08301 ignorepat->next = NULL; 08302 ignorepat->registrar = registrar; 08303 ast_wrlock_context(con); 08304 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 08305 ignorepatl = ignorepatc; 08306 if (!strcasecmp(ignorepatc->pattern, value)) { 08307 /* Already there */ 08308 ast_unlock_context(con); 08309 ast_free(ignorepat); 08310 errno = EEXIST; 08311 return -1; 08312 } 08313 } 08314 if (ignorepatl) 08315 ignorepatl->next = ignorepat; 08316 else 08317 con->ignorepats = ignorepat; 08318 ast_unlock_context(con); 08319 return 0; 08320 08321 }
int ast_context_add_include | ( | const char * | context, | |
const char * | include, | |||
const char * | registrar | |||
) |
Add a context include.
context | context to add include to | |
include | new include to add | |
registrar | who's registering it |
Adds an include taking a char * string as the context parameter
0 | on success | |
-1 | on error |
Definition at line 7815 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
07816 { 07817 int ret = -1; 07818 struct ast_context *c; 07819 07820 c = find_context_locked(context); 07821 if (c) { 07822 ret = ast_context_add_include2(c, include, registrar); 07823 ast_unlock_contexts(); 07824 } 07825 return ret; 07826 }
int ast_context_add_include2 | ( | struct ast_context * | con, | |
const char * | include, | |||
const char * | registrar | |||
) |
Add a context include.
con | context to add the include to | |
include | include to add | |
registrar | who registered the context |
Adds an include taking a struct ast_context as the first parameter
0 | on success | |
-1 | on failure |
Definition at line 8084 of file pbx.c.
References ast_build_timing(), ast_calloc, ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), errno, ast_include::hastime, ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, ast_include::rname, ast_include::stuff, and ast_include::timing.
Referenced by ast_compile_ael2(), ast_context_add_include(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
08086 { 08087 struct ast_include *new_include; 08088 char *c; 08089 struct ast_include *i, *il = NULL; /* include, include_last */ 08090 int length; 08091 char *p; 08092 08093 length = sizeof(struct ast_include); 08094 length += 2 * (strlen(value) + 1); 08095 08096 /* allocate new include structure ... */ 08097 if (!(new_include = ast_calloc(1, length))) 08098 return -1; 08099 /* Fill in this structure. Use 'p' for assignments, as the fields 08100 * in the structure are 'const char *' 08101 */ 08102 p = new_include->stuff; 08103 new_include->name = p; 08104 strcpy(p, value); 08105 p += strlen(value) + 1; 08106 new_include->rname = p; 08107 strcpy(p, value); 08108 /* Strip off timing info, and process if it is there */ 08109 if ( (c = strchr(p, ',')) ) { 08110 *c++ = '\0'; 08111 new_include->hastime = ast_build_timing(&(new_include->timing), c); 08112 } 08113 new_include->next = NULL; 08114 new_include->registrar = registrar; 08115 08116 ast_wrlock_context(con); 08117 08118 /* ... go to last include and check if context is already included too... */ 08119 for (i = con->includes; i; i = i->next) { 08120 if (!strcasecmp(i->name, new_include->name)) { 08121 ast_destroy_timing(&(new_include->timing)); 08122 ast_free(new_include); 08123 ast_unlock_context(con); 08124 errno = EEXIST; 08125 return -1; 08126 } 08127 il = i; 08128 } 08129 08130 /* ... include new context into context list, unlock, return */ 08131 if (il) 08132 il->next = new_include; 08133 else 08134 con->includes = new_include; 08135 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 08136 08137 ast_unlock_context(con); 08138 08139 return 0; 08140 }
int ast_context_add_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
int | eval, | |||
const char * | registrar | |||
) |
Add a switch.
context | context to which to add the switch | |
sw | switch to add | |
data | data to pass to switch | |
eval | whether to evaluate variables when running switch | |
registrar | whoever registered the switch |
This function registers a switch with the asterisk switch architecture
0 | on success | |
-1 | on failure |
Definition at line 8147 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
08148 { 08149 int ret = -1; 08150 struct ast_context *c; 08151 08152 c = find_context_locked(context); 08153 if (c) { /* found, add switch to this context */ 08154 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 08155 ast_unlock_contexts(); 08156 } 08157 return ret; 08158 }
int ast_context_add_switch2 | ( | struct ast_context * | con, | |
const char * | sw, | |||
const char * | data, | |||
int | eval, | |||
const char * | registrar | |||
) |
Adds a switch (first param is a ast_context).
Definition at line 8167 of file pbx.c.
References ast_context::alts, ast_calloc, ast_free, ast_get_context_name(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, errno, ast_sw::eval, ast_sw::name, ast_sw::registrar, and ast_sw::stuff.
Referenced by ast_compile_ael2(), ast_context_add_switch(), context_merge_incls_swits_igps_other_registrars(), lua_register_switches(), and pbx_load_config().
08169 { 08170 struct ast_sw *new_sw; 08171 struct ast_sw *i; 08172 int length; 08173 char *p; 08174 08175 length = sizeof(struct ast_sw); 08176 length += strlen(value) + 1; 08177 if (data) 08178 length += strlen(data); 08179 length++; 08180 08181 /* allocate new sw structure ... */ 08182 if (!(new_sw = ast_calloc(1, length))) 08183 return -1; 08184 /* ... fill in this structure ... */ 08185 p = new_sw->stuff; 08186 new_sw->name = p; 08187 strcpy(new_sw->name, value); 08188 p += strlen(value) + 1; 08189 new_sw->data = p; 08190 if (data) { 08191 strcpy(new_sw->data, data); 08192 p += strlen(data) + 1; 08193 } else { 08194 strcpy(new_sw->data, ""); 08195 p++; 08196 } 08197 new_sw->eval = eval; 08198 new_sw->registrar = registrar; 08199 08200 /* ... try to lock this context ... */ 08201 ast_wrlock_context(con); 08202 08203 /* ... go to last sw and check if context is already swd too... */ 08204 AST_LIST_TRAVERSE(&con->alts, i, list) { 08205 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 08206 ast_free(new_sw); 08207 ast_unlock_context(con); 08208 errno = EEXIST; 08209 return -1; 08210 } 08211 } 08212 08213 /* ... sw new context into context list, unlock, return */ 08214 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 08215 08216 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 08217 08218 ast_unlock_context(con); 08219 08220 return 0; 08221 }
void ast_context_destroy | ( | struct ast_context * | con, | |
const char * | registrar | |||
) |
Destroy a context (matches the specified context (or ANY context if NULL).
con | context to destroy | |
registrar | who 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 9548 of file pbx.c.
References __ast_context_destroy(), ast_unlock_contexts(), ast_wrlock_contexts(), contexts, and contexts_table.
Referenced by __unload_module(), ast_features_reload(), cleanup_stale_contexts(), remove_dead_dialplan_useage(), sla_destroy(), and unload_module().
09549 { 09550 ast_wrlock_contexts(); 09551 __ast_context_destroy(contexts, contexts_table, con,registrar); 09552 ast_unlock_contexts(); 09553 }
struct ast_context* ast_context_find | ( | const char * | name | ) | [read] |
Find a context.
name | name of the context to find |
Will search for the context with the given name.
Definition at line 2896 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::name, and fake_context::name.
Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_features_reload(), ast_ignore_pattern(), cleanup_stale_contexts(), isexten_function_read(), manage_parkinglot(), parked_call_exec(), register_exten(), register_peer_exten(), remove_dead_dialplan_useage(), unload_module(), and unregister_exten().
02897 { 02898 struct ast_context *tmp; 02899 struct fake_context item; 02900 02901 if (!name) { 02902 return NULL; 02903 } 02904 ast_rdlock_contexts(); 02905 if (contexts_table) { 02906 ast_copy_string(item.name, name, sizeof(item.name)); 02907 tmp = ast_hashtab_lookup(contexts_table, &item); 02908 } else { 02909 tmp = NULL; 02910 while ((tmp = ast_walk_contexts(tmp))) { 02911 if (!strcasecmp(name, tmp->name)) { 02912 break; 02913 } 02914 } 02915 } 02916 ast_unlock_contexts(); 02917 return tmp; 02918 }
struct ast_context* ast_context_find_or_create | ( | struct ast_context ** | extcontexts, | |
struct ast_hashtab * | exttable, | |||
const char * | name, | |||
const char * | registrar | |||
) | [read] |
Register a new context or find an existing one.
extcontexts | pointer to the ast_context structure pointer | |
exttable | pointer to the hashtable that contains all the elements in extcontexts | |
name | name of the new context | |
registrar | registrar 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.
Definition at line 7414 of file pbx.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_insert_immediate(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_mutex_init, ast_rdlock_contexts(), ast_rwlock_init, ast_strdup, ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), contexts, contexts_table, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, ast_context::macrolock, ast_context::name, fake_context::name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by ast_compile_ael2(), config_parse_variables(), context_merge(), load_module(), lua_register_switches(), manage_parked_call(), parkinglot_activate(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().
07415 { 07416 struct ast_context *tmp, **local_contexts; 07417 struct fake_context search; 07418 int length = sizeof(struct ast_context) + strlen(name) + 1; 07419 07420 if (!contexts_table) { 07421 /* Protect creation of contexts_table from reentrancy. */ 07422 ast_wrlock_contexts(); 07423 if (!contexts_table) { 07424 contexts_table = ast_hashtab_create(17, 07425 ast_hashtab_compare_contexts, 07426 ast_hashtab_resize_java, 07427 ast_hashtab_newsize_java, 07428 ast_hashtab_hash_contexts, 07429 0); 07430 } 07431 ast_unlock_contexts(); 07432 } 07433 07434 ast_copy_string(search.name, name, sizeof(search.name)); 07435 if (!extcontexts) { 07436 ast_rdlock_contexts(); 07437 local_contexts = &contexts; 07438 tmp = ast_hashtab_lookup(contexts_table, &search); 07439 ast_unlock_contexts(); 07440 if (tmp) { 07441 tmp->refcount++; 07442 return tmp; 07443 } 07444 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 07445 local_contexts = extcontexts; 07446 tmp = ast_hashtab_lookup(exttable, &search); 07447 if (tmp) { 07448 tmp->refcount++; 07449 return tmp; 07450 } 07451 } 07452 07453 if ((tmp = ast_calloc(1, length))) { 07454 ast_rwlock_init(&tmp->lock); 07455 ast_mutex_init(&tmp->macrolock); 07456 strcpy(tmp->name, name); 07457 tmp->root = NULL; 07458 tmp->root_table = NULL; 07459 tmp->registrar = ast_strdup(registrar); 07460 tmp->includes = NULL; 07461 tmp->ignorepats = NULL; 07462 tmp->refcount = 1; 07463 } else { 07464 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 07465 return NULL; 07466 } 07467 07468 if (!extcontexts) { 07469 ast_wrlock_contexts(); 07470 tmp->next = *local_contexts; 07471 *local_contexts = tmp; 07472 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 07473 ast_unlock_contexts(); 07474 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 07475 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07476 } else { 07477 tmp->next = *local_contexts; 07478 if (exttable) 07479 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 07480 07481 *local_contexts = tmp; 07482 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 07483 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07484 } 07485 return tmp; 07486 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 6009 of file pbx.c.
References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06010 { 06011 struct ast_context *c; 06012 int ret = -1; 06013 06014 c = find_context_locked(context); 06015 if (c) { 06016 ast_unlock_contexts(); 06017 06018 /* if we found context, lock macrolock */ 06019 ret = ast_mutex_lock(&c->macrolock); 06020 } 06021 06022 return ret; 06023 }
int ast_context_remove_extension | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar | |||
) |
Simply remove extension from context.
Definition at line 5814 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), remove_exten_if_exist(), unregister_exten(), and UnregisterExtension().
05815 { 05816 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 05817 }
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.
Definition at line 5844 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by manage_parkinglot(), parked_call_exec(), and unload_module().
05845 { 05846 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 05847 }
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 5819 of file pbx.c.
References ast_context_remove_extension_callerid2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_context_remove_extension(), and handle_cli_dialplan_remove_extension().
05820 { 05821 int ret = -1; /* default error return */ 05822 struct ast_context *c; 05823 05824 c = find_context_locked(context); 05825 if (c) { /* ... remove extension ... */ 05826 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, 05827 matchcallerid, registrar, 0); 05828 ast_unlock_contexts(); 05829 } 05830 05831 return ret; 05832 }
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 5849 of file pbx.c.
References add_exten_to_pattern_tree(), ast_copy_string(), ast_hashtab_insert_immediate(), ast_hashtab_lookup(), ast_hashtab_remove_this_object(), ast_hashtab_size(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, match_char::deleted, destroy_exten(), match_char::exten, ast_exten::exten, exten, ast_exten::label, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_context::pattern_tree, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, ast_context::root, ast_context::root_table, and match_char::x.
Referenced by __ast_context_destroy(), ast_context_remove_extension2(), and ast_context_remove_extension_callerid().
05850 { 05851 struct ast_exten *exten, *prev_exten = NULL; 05852 struct ast_exten *peer; 05853 struct ast_exten ex, *exten2, *exten3; 05854 char dummy_name[1024]; 05855 struct ast_exten *previous_peer = NULL; 05856 struct ast_exten *next_peer = NULL; 05857 int found = 0; 05858 05859 if (!already_locked) 05860 ast_wrlock_context(con); 05861 05862 /* Handle this is in the new world */ 05863 05864 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 05865 * peers, not just those matching the callerid. */ 05866 #ifdef NEED_DEBUG 05867 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 05868 #endif 05869 #ifdef CONTEXT_DEBUG 05870 check_contexts(__FILE__, __LINE__); 05871 #endif 05872 /* find this particular extension */ 05873 ex.exten = dummy_name; 05874 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 05875 ex.cidmatch = callerid; 05876 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 05877 exten = ast_hashtab_lookup(con->root_table, &ex); 05878 if (exten) { 05879 if (priority == 0) { 05880 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05881 if (!exten2) 05882 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); 05883 if (con->pattern_tree) { 05884 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05885 05886 if (x->exten) { /* this test for safety purposes */ 05887 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05888 x->exten = 0; /* get rid of what will become a bad pointer */ 05889 } else { 05890 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 05891 } 05892 } 05893 } else { 05894 ex.priority = priority; 05895 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 05896 if (exten2) { 05897 05898 if (exten2->label) { /* if this exten has a label, remove that, too */ 05899 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 05900 if (!exten3) 05901 ast_log(LOG_ERROR,"Did not remove this priority label (%d/%s) from the peer_label_table of context %s, extension %s!\n", priority, exten2->label, con->name, exten2->exten); 05902 } 05903 05904 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 05905 if (!exten3) 05906 ast_log(LOG_ERROR,"Did not remove this priority (%d) from the peer_table of context %s, extension %s!\n", priority, con->name, exten2->exten); 05907 if (exten2 == exten && exten2->peer) { 05908 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05909 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 05910 } 05911 if (ast_hashtab_size(exten->peer_table) == 0) { 05912 /* well, if the last priority of an exten is to be removed, 05913 then, the extension is removed, too! */ 05914 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 05915 if (!exten3) 05916 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 05917 if (con->pattern_tree) { 05918 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05919 if (x->exten) { /* this test for safety purposes */ 05920 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05921 x->exten = 0; /* get rid of what will become a bad pointer */ 05922 } 05923 } 05924 } 05925 } else { 05926 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 05927 priority, exten->exten, con->name); 05928 } 05929 } 05930 } else { 05931 /* hmmm? this exten is not in this pattern tree? */ 05932 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 05933 extension, con->name); 05934 } 05935 #ifdef NEED_DEBUG 05936 if (con->pattern_tree) { 05937 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 05938 log_match_char_tree(con->pattern_tree, " "); 05939 } 05940 #endif 05941 05942 /* scan the extension list to find first matching extension-registrar */ 05943 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 05944 if (!strcmp(exten->exten, extension) && 05945 (!registrar || !strcmp(exten->registrar, registrar)) && 05946 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 05947 break; 05948 } 05949 if (!exten) { 05950 /* we can't find right extension */ 05951 if (!already_locked) 05952 ast_unlock_context(con); 05953 return -1; 05954 } 05955 05956 /* scan the priority list to remove extension with exten->priority == priority */ 05957 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 05958 peer && !strcmp(peer->exten, extension) && (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(peer->cidmatch) && !strcmp(peer->cidmatch,callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(peer->cidmatch))); 05959 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 05960 if ((priority == 0 || peer->priority == priority) && 05961 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 05962 (!registrar || !strcmp(peer->registrar, registrar) )) { 05963 found = 1; 05964 05965 /* we are first priority extension? */ 05966 if (!previous_peer) { 05967 /* 05968 * We are first in the priority chain, so must update the extension chain. 05969 * The next node is either the next priority or the next extension 05970 */ 05971 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 05972 if (peer->peer) { 05973 /* move the peer_table and peer_label_table down to the next peer, if 05974 it is there */ 05975 peer->peer->peer_table = peer->peer_table; 05976 peer->peer->peer_label_table = peer->peer_label_table; 05977 peer->peer_table = NULL; 05978 peer->peer_label_table = NULL; 05979 } 05980 if (!prev_exten) { /* change the root... */ 05981 con->root = next_node; 05982 } else { 05983 prev_exten->next = next_node; /* unlink */ 05984 } 05985 if (peer->peer) { /* update the new head of the pri list */ 05986 peer->peer->next = peer->next; 05987 } 05988 } else { /* easy, we are not first priority in extension */ 05989 previous_peer->peer = peer->peer; 05990 } 05991 05992 /* now, free whole priority extension */ 05993 destroy_exten(peer); 05994 } else { 05995 previous_peer = peer; 05996 } 05997 } 05998 if (!already_locked) 05999 ast_unlock_context(con); 06000 return found ? 0 : -1; 06001 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8227 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
08228 { 08229 int ret = -1; 08230 struct ast_context *c; 08231 08232 c = find_context_locked(context); 08233 if (c) { 08234 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 08235 ast_unlock_contexts(); 08236 } 08237 return ret; 08238 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8240 of file pbx.c.
References ast_free, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_remove_ignorepat().
08241 { 08242 struct ast_ignorepat *ip, *ipl = NULL; 08243 08244 ast_wrlock_context(con); 08245 08246 for (ip = con->ignorepats; ip; ip = ip->next) { 08247 if (!strcmp(ip->pattern, ignorepat) && 08248 (!registrar || (registrar == ip->registrar))) { 08249 if (ipl) { 08250 ipl->next = ip->next; 08251 ast_free(ip); 08252 } else { 08253 con->ignorepats = ip->next; 08254 ast_free(ip); 08255 } 08256 ast_unlock_context(con); 08257 return 0; 08258 } 08259 ipl = ip; 08260 } 08261 08262 ast_unlock_context(con); 08263 errno = EINVAL; 08264 return -1; 08265 }
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 5707 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
05708 { 05709 int ret = -1; 05710 struct ast_context *c; 05711 05712 c = find_context_locked(context); 05713 if (c) { 05714 /* found, remove include from this context ... */ 05715 ret = ast_context_remove_include2(c, include, registrar); 05716 ast_unlock_contexts(); 05717 } 05718 return ret; 05719 }
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.
0 | on success. | |
-1 | on failure. |
Definition at line 5730 of file pbx.c.
References ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, and ast_include::timing.
Referenced by ast_context_remove_include().
05731 { 05732 struct ast_include *i, *pi = NULL; 05733 int ret = -1; 05734 05735 ast_wrlock_context(con); 05736 05737 /* find our include */ 05738 for (i = con->includes; i; pi = i, i = i->next) { 05739 if (!strcmp(i->name, include) && 05740 (!registrar || !strcmp(i->registrar, registrar))) { 05741 /* remove from list */ 05742 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 05743 if (pi) 05744 pi->next = i->next; 05745 else 05746 con->includes = i->next; 05747 /* free include and return */ 05748 ast_destroy_timing(&(i->timing)); 05749 ast_free(i); 05750 ret = 0; 05751 break; 05752 } 05753 } 05754 05755 ast_unlock_context(con); 05756 05757 return ret; 05758 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 5765 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
05766 { 05767 int ret = -1; /* default error return */ 05768 struct ast_context *c; 05769 05770 c = find_context_locked(context); 05771 if (c) { 05772 /* remove switch from this context ... */ 05773 ret = ast_context_remove_switch2(c, sw, data, registrar); 05774 ast_unlock_contexts(); 05775 } 05776 return ret; 05777 }
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 at line 5787 of file pbx.c.
References ast_context::alts, ast_free, ast_get_context_name(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, ast_sw::name, and ast_sw::registrar.
Referenced by ast_context_remove_switch().
05788 { 05789 struct ast_sw *i; 05790 int ret = -1; 05791 05792 ast_wrlock_context(con); 05793 05794 /* walk switches */ 05795 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 05796 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 05797 (!registrar || !strcmp(i->registrar, registrar))) { 05798 /* found, remove from list */ 05799 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 05800 AST_LIST_REMOVE_CURRENT(list); 05801 ast_free(i); /* free switch and return */ 05802 ret = 0; 05803 break; 05804 } 05805 } 05806 AST_LIST_TRAVERSE_SAFE_END; 05807 05808 ast_unlock_context(con); 05809 05810 return ret; 05811 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 6030 of file pbx.c.
References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06031 { 06032 struct ast_context *c; 06033 int ret = -1; 06034 06035 c = find_context_locked(context); 06036 if (c) { 06037 ast_unlock_contexts(); 06038 06039 /* if we found context, unlock macrolock */ 06040 ret = ast_mutex_unlock(&c->macrolock); 06041 } 06042 06043 return ret; 06044 }
int ast_context_verify_includes | ( | struct ast_context * | con | ) |
Verifies includes in an ast_contect structure.
con | context in which to verify the includes |
0 | if no problems found | |
-1 | if there were any missing context |
Definition at line 10801 of file pbx.c.
References ast_context_find(), ast_get_context_name(), ast_log(), ast_walk_context_includes(), LOG_WARNING, and ast_include::rname.
Referenced by pbx_load_module().
10802 { 10803 struct ast_include *inc = NULL; 10804 int res = 0; 10805 10806 while ( (inc = ast_walk_context_includes(con, inc)) ) { 10807 if (ast_context_find(inc->rname)) 10808 continue; 10809 10810 res = -1; 10811 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 10812 ast_get_context_name(con), inc->rname); 10813 break; 10814 } 10815 10816 return res; 10817 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 3725 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_function::name.
Referenced by ast_compile_ael2(), ast_func_read(), ast_func_read2(), ast_func_write(), config_curl(), destroy_curl(), handle_show_function(), op_func(), realtime_curl(), realtime_multi_curl(), require_curl(), store_curl(), update2_curl(), and update_curl().
03726 { 03727 struct ast_custom_function *acf = NULL; 03728 03729 AST_RWLIST_RDLOCK(&acf_root); 03730 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03731 if (!strcmp(name, acf->name)) 03732 break; 03733 } 03734 AST_RWLIST_UNLOCK(&acf_root); 03735 03736 return acf; 03737 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3739 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, AST_XML_DOC, ast_custom_function::docsrc, and ast_custom_function::name.
Referenced by _unload_module(), load_module(), reload(), unload_module(), and unload_pbx().
03740 { 03741 struct ast_custom_function *cur; 03742 03743 if (!acf) { 03744 return -1; 03745 } 03746 03747 AST_RWLIST_WRLOCK(&acf_root); 03748 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03749 #ifdef AST_XML_DOCS 03750 if (cur->docsrc == AST_XML_DOC) { 03751 ast_string_field_free_memory(acf); 03752 } 03753 #endif 03754 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03755 } 03756 AST_RWLIST_UNLOCK(&acf_root); 03757 03758 return cur ? 0 : -1; 03759 }
int ast_destroy_timing | ( | struct ast_timing * | i | ) |
Deallocates memory structures associated with a timing bitmap.
i | Pointer to an ast_timing structure. |
0 | success | |
non-zero | failure (number suitable to pass to |
Definition at line 8069 of file pbx.c.
References ast_free, and ast_timing::timezone.
Referenced by ast_context_add_include2(), ast_context_remove_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
enum ast_extension_states ast_devstate_to_extenstate | ( | enum ast_device_state | devstate | ) |
Map devstate to an extension state.
[in] | devstate | device state |
Definition at line 4548 of file pbx.c.
References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_TOTAL, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, and AST_EXTENSION_UNAVAILABLE.
Referenced by ast_extension_state3().
04549 { 04550 switch (devstate) { 04551 case AST_DEVICE_ONHOLD: 04552 return AST_EXTENSION_ONHOLD; 04553 case AST_DEVICE_BUSY: 04554 return AST_EXTENSION_BUSY; 04555 case AST_DEVICE_UNKNOWN: 04556 return AST_EXTENSION_NOT_INUSE; 04557 case AST_DEVICE_UNAVAILABLE: 04558 case AST_DEVICE_INVALID: 04559 return AST_EXTENSION_UNAVAILABLE; 04560 case AST_DEVICE_RINGINUSE: 04561 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04562 case AST_DEVICE_RINGING: 04563 return AST_EXTENSION_RINGING; 04564 case AST_DEVICE_INUSE: 04565 return AST_EXTENSION_INUSE; 04566 case AST_DEVICE_NOT_INUSE: 04567 return AST_EXTENSION_NOT_INUSE; 04568 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04569 break; 04570 } 04571 04572 return AST_EXTENSION_NOT_INUSE; 04573 }
int ast_exists_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | callerid | |||
) |
Determine whether an extension exists.
c | this is not important | |
context | which context to look in | |
exten | which extension to search for | |
priority | priority of the action within the extension | |
callerid | callerid to search for |
Definition at line 5100 of file pbx.c.
References E_MATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), analog_ss_thread(), answer_call(), ast_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmf(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), try_calling(), vm_authenticate(), and waitstream_core().
05101 { 05102 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 05103 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8381 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_FLAG_IN_AUTOLOOP, ast_strlen_zero(), ast_test_flag, ast_channel::context, ast_channel::exten, and ast_channel::priority.
Referenced by __ast_goto_if_exists(), ast_async_goto(), builtin_atxfer(), disa_exec(), do_bridge_masquerade(), handle_setpriority(), pbx_parseable_goto(), and return_exec().
08382 { 08383 if (!chan) 08384 return -1; 08385 08386 ast_channel_lock(chan); 08387 08388 if (!ast_strlen_zero(context)) 08389 ast_copy_string(chan->context, context, sizeof(chan->context)); 08390 if (!ast_strlen_zero(exten)) 08391 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08392 if (priority > -1) { 08393 chan->priority = priority; 08394 /* see flag description in channel.h for explanation */ 08395 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 08396 chan->priority--; 08397 } 08398 08399 ast_channel_unlock(chan); 08400 08401 return 0; 08402 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 2873 of file pbx.c.
References ast_log(), E_CANMATCH, E_MATCHMORE, extension_match_core(), and LOG_WARNING.
Referenced by lua_find_extension(), and realtime_switch_common().
02874 { 02875 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02876 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02877 return extension_match_core(pattern, data, needmore); 02878 }
int ast_extension_cmp | ( | const char * | a, | |
const char * | b | |||
) |
Determine if one extension should match before another.
Checks whether or extension a should match before extension b
0 | if the two extensions have equal matching priority | |
1 | on a > b | |
-1 | on a < b |
Definition at line 2638 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02639 { 02640 int cmp; 02641 02642 cmp = ext_cmp(a, b); 02643 if (cmp < 0) { 02644 return -1; 02645 } 02646 if (cmp > 0) { 02647 return 1; 02648 } 02649 return 0; 02650 }
int ast_extension_match | ( | const char * | pattern, | |
const char * | extension | |||
) |
Determine if a given extension matches a given pattern (in NXX format).
Checks whether or not the given extension matches the given pattern.
1 | on match | |
0 | on failure |
Definition at line 2868 of file pbx.c.
References E_MATCH, and extension_match_core().
Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), load_module(), loopback_canmatch(), loopback_exists(), loopback_matchmore(), lua_find_extension(), manager_show_dialplan_helper(), matchcid(), misdn_cfg_is_msn_valid(), realtime_switch_common(), reload(), and show_dialplan_helper().
02869 { 02870 return extension_match_core(pattern, data, E_MATCH); 02871 }
int ast_extension_state | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) |
Check extension state for an extension by using hint.
Uses hint and devicestate callback to get the state of an extension.
Definition at line 4618 of file pbx.c.
References ast_exten::app, ast_add_extension(), ast_extension_state2(), ast_free_ptr(), ast_hint_extension(), ast_strdup, ast_exten::cidmatch, ast_exten::data, ast_exten::exten, ast_exten::label, ast_exten::matchcid, ast_context::name, ast_exten::parent, ast_exten::priority, and ast_exten::registrar.
Referenced by action_extensionstate(), extstate_read(), get_queue_member_status(), and handle_request_subscribe().
04619 { 04620 struct ast_exten *e; 04621 04622 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04623 return -1; /* No hint, return -1 */ 04624 } 04625 04626 if (e->exten[0] == '_') { 04627 /* Create this hint on-the-fly */ 04628 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04629 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04630 e->registrar); 04631 if (!(e = ast_hint_extension(c, context, exten))) { 04632 /* Improbable, but not impossible */ 04633 return -1; 04634 } 04635 } 04636 04637 return ast_extension_state2(e); /* Check all devices in the hint */ 04638 }
static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
Check state of extension by using hints.
Definition at line 4593 of file pbx.c.
References ast_extension_state3(), ast_get_extension_app(), ast_str_set(), ast_str_thread_get(), and extensionstate_buf.
Referenced by ast_add_hint(), and ast_extension_state().
04594 { 04595 struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32); 04596 04597 if (!e || !hint_app) { 04598 return -1; 04599 } 04600 04601 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e)); 04602 return ast_extension_state3(hint_app); 04603 }
const char* ast_extension_state2str | ( | int | extension_state | ) |
Return extension_state as string.
Return string representation of the state of an extension.
Definition at line 4606 of file pbx.c.
References ARRAY_LEN, extension_states, and cfextension_states::text.
Referenced by cb_extensionstate(), handle_request_subscribe(), handle_show_hint(), handle_show_hints(), hints_data_provider_get(), and show_channels_cb().
04607 { 04608 int i; 04609 04610 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04611 if (extension_states[i].extension_state == extension_state) 04612 return extension_states[i].text; 04613 } 04614 return "Unknown"; 04615 }
static int ast_extension_state3 | ( | struct ast_str * | hint_app | ) | [static] |
Definition at line 4575 of file pbx.c.
References ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_devstate_to_extenstate(), and ast_str_buffer().
Referenced by ast_extension_state2(), and handle_statechange().
04576 { 04577 char *cur; 04578 char *rest; 04579 struct ast_devstate_aggregate agg; 04580 04581 /* One or more devices separated with a & character */ 04582 rest = ast_str_buffer(hint_app); 04583 04584 ast_devstate_aggregate_init(&agg); 04585 while ((cur = strsep(&rest, "&"))) { 04586 ast_devstate_aggregate_add(&agg, ast_device_state(cur)); 04587 } 04588 04589 return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg)); 04590 }
int ast_extension_state_add | ( | const char * | context, | |
const char * | exten, | |||
ast_state_cb_type | change_cb, | |||
void * | data | |||
) |
Add watcher for extension states.
Registers a state change callback.
Definition at line 4839 of file pbx.c.
References ast_extension_state_add_destroy().
Referenced by __init_manager(), load_module(), and skinny_register().
04841 { 04842 return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data); 04843 }
int ast_extension_state_add_destroy | ( | const char * | context, | |
const char * | exten, | |||
ast_state_cb_type | change_cb, | |||
ast_state_cb_destroy_type | destroy_cb, | |||
void * | data | |||
) |
Add watcher for extension states with destructor.
Registers a state change callback with destructor.
Definition at line 4752 of file pbx.c.
References ao2_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension(), ast_free_ptr(), ast_hint_extension(), ast_strdup, ast_hint::callbacks, ast_state_cb::change_cb, ast_exten::cidmatch, ast_exten::data, ast_state_cb::data, ast_state_cb::destroy_cb, destroy_state_cb(), ast_exten::exten, hints, ast_state_cb::id, ast_exten::label, ast_exten::matchcid, ast_context::name, OBJ_NODATA, OBJ_UNLINK, ast_exten::parent, ast_exten::priority, ast_exten::registrar, statecbs, and stateid.
Referenced by ast_extension_state_add(), and handle_request_subscribe().
04754 { 04755 struct ast_hint *hint; 04756 struct ast_state_cb *state_cb; 04757 struct ast_exten *e; 04758 int id; 04759 04760 /* If there's no context and extension: add callback to statecbs list */ 04761 if (!context && !exten) { 04762 /* Prevent multiple adds from adding the same change_cb at the same time. */ 04763 ao2_lock(statecbs); 04764 04765 /* Remove any existing change_cb. */ 04766 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA); 04767 04768 /* Now insert the change_cb */ 04769 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 04770 ao2_unlock(statecbs); 04771 return -1; 04772 } 04773 state_cb->id = 0; 04774 state_cb->change_cb = change_cb; 04775 state_cb->destroy_cb = destroy_cb; 04776 state_cb->data = data; 04777 ao2_link(statecbs, state_cb); 04778 04779 ao2_ref(state_cb, -1); 04780 ao2_unlock(statecbs); 04781 return 0; 04782 } 04783 04784 if (!context || !exten) 04785 return -1; 04786 04787 /* This callback type is for only one hint, so get the hint */ 04788 e = ast_hint_extension(NULL, context, exten); 04789 if (!e) { 04790 return -1; 04791 } 04792 04793 /* If this is a pattern, dynamically create a new extension for this 04794 * particular match. Note that this will only happen once for each 04795 * individual extension, because the pattern will no longer match first. 04796 */ 04797 if (e->exten[0] == '_') { 04798 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04799 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04800 e->registrar); 04801 e = ast_hint_extension(NULL, context, exten); 04802 if (!e || e->exten[0] == '_') { 04803 return -1; 04804 } 04805 } 04806 04807 /* Find the hint in the hints container */ 04808 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 04809 hint = ao2_find(hints, e, 0); 04810 if (!hint) { 04811 ao2_unlock(hints); 04812 return -1; 04813 } 04814 04815 /* Now insert the callback in the callback list */ 04816 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 04817 ao2_ref(hint, -1); 04818 ao2_unlock(hints); 04819 return -1; 04820 } 04821 do { 04822 id = stateid++; /* Unique ID for this callback */ 04823 /* Do not allow id to ever be -1 or 0. */ 04824 } while (id == -1 || id == 0); 04825 state_cb->id = id; 04826 state_cb->change_cb = change_cb; /* Pointer to callback routine */ 04827 state_cb->destroy_cb = destroy_cb; 04828 state_cb->data = data; /* Data for the callback */ 04829 ao2_link(hint->callbacks, state_cb); 04830 04831 ao2_ref(state_cb, -1); 04832 ao2_ref(hint, -1); 04833 ao2_unlock(hints); 04834 04835 return id; 04836 }
int ast_extension_state_del | ( | int | id, | |
ast_state_cb_type | change_cb | |||
) |
ast_extension_state_del: Remove a watcher from the callback list
Deletes a registered state change callback by ID.
Definition at line 4861 of file pbx.c.
References ao2_callback, ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_hint::callbacks, find_hint_by_cb_id(), hints, OBJ_UNLINK, and statecbs.
Referenced by dialog_unlink_all(), handle_request_subscribe(), skinny_unregister(), and unload_module().
04862 { 04863 struct ast_state_cb *p_cur; 04864 int ret = -1; 04865 04866 if (!id) { /* id == 0 is a callback without extension */ 04867 if (!change_cb) { 04868 return ret; 04869 } 04870 p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK); 04871 if (p_cur) { 04872 ret = 0; 04873 ao2_ref(p_cur, -1); 04874 } 04875 } else { /* callback with extension, find the callback based on ID */ 04876 struct ast_hint *hint; 04877 04878 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 04879 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 04880 if (hint) { 04881 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 04882 if (p_cur) { 04883 ret = 0; 04884 ao2_ref(p_cur, -1); 04885 } 04886 ao2_ref(hint, -1); 04887 } 04888 ao2_unlock(hints); 04889 } 04890 04891 return ret; 04892 }
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.
c | this is not important | |
context | which context to look in | |
exten | which extension to search for | |
label | label of the action within the extension to match to priority | |
callerid | callerid to search for |
the | priority which matches the given label in the extension | |
-1 | if not found. |
Definition at line 5105 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by action_originate(), action_redirect(), handle_gosub(), handle_setpriority(), isexten_function_read(), and pbx_parseable_goto().
05106 { 05107 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05108 }
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.
Definition at line 5110 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
05111 { 05112 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05113 }
int ast_func_read | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | workspace, | |||
size_t | len | |||
) |
executes a read operation on a function
chan | Channel to execute on | |
function | Data containing the function call string (will be modified) | |
workspace | A pointer to safe memory to use for a return value | |
len | the number of bytes in workspace |
This application executes a function in read mode on a given channel.
0 | success | |
non-zero | failure |
Definition at line 3883 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_copy_string(), ast_custom_function_find(), ast_free, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_size(), ast_strdupa, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, and str.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
03884 { 03885 char *copy = ast_strdupa(function); 03886 char *args = func_args(copy); 03887 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03888 int res; 03889 struct ast_module_user *u = NULL; 03890 03891 if (acfptr == NULL) { 03892 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03893 } else if (!acfptr->read && !acfptr->read2) { 03894 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03895 } else if (acfptr->read) { 03896 if (acfptr->mod) { 03897 u = __ast_module_user_add(acfptr->mod, chan); 03898 } 03899 res = acfptr->read(chan, copy, args, workspace, len); 03900 if (acfptr->mod && u) { 03901 __ast_module_user_remove(acfptr->mod, u); 03902 } 03903 return res; 03904 } else { 03905 struct ast_str *str = ast_str_create(16); 03906 if (acfptr->mod) { 03907 u = __ast_module_user_add(acfptr->mod, chan); 03908 } 03909 res = acfptr->read2(chan, copy, args, &str, 0); 03910 if (acfptr->mod && u) { 03911 __ast_module_user_remove(acfptr->mod, u); 03912 } 03913 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 03914 ast_free(str); 03915 return res; 03916 } 03917 return -1; 03918 }
int ast_func_read2 | ( | struct ast_channel * | chan, | |
const char * | function, | |||
struct ast_str ** | str, | |||
ssize_t | maxlen | |||
) |
executes a read operation on a function
chan | Channel to execute on | |
function | Data containing the function call string (will be modified) | |
str | A dynamic string buffer into which to place the result. | |
maxlen | <0 if the dynamic buffer should not grow; >0 if the dynamic buffer should be limited to that number of bytes; 0 if the dynamic buffer has no upper limit |
This application executes a function in read mode on a given channel.
0 | success | |
non-zero | failure |
Definition at line 3920 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_str_buffer(), ast_str_make_space(), ast_str_reset(), ast_str_size(), ast_strdupa, copy(), func_args(), LOG_ERROR, maxsize, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, and VAR_BUF_SIZE.
Referenced by append_channel_vars(), and ast_str_substitute_variables_full().
03921 { 03922 char *copy = ast_strdupa(function); 03923 char *args = func_args(copy); 03924 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03925 int res; 03926 struct ast_module_user *u = NULL; 03927 03928 if (acfptr == NULL) { 03929 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03930 } else if (!acfptr->read && !acfptr->read2) { 03931 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03932 } else { 03933 if (acfptr->mod) { 03934 u = __ast_module_user_add(acfptr->mod, chan); 03935 } 03936 ast_str_reset(*str); 03937 if (acfptr->read2) { 03938 /* ast_str enabled */ 03939 res = acfptr->read2(chan, copy, args, str, maxlen); 03940 } else { 03941 /* Legacy function pointer, allocate buffer for result */ 03942 int maxsize = ast_str_size(*str); 03943 if (maxlen > -1) { 03944 if (maxlen == 0) { 03945 if (acfptr->read_max) { 03946 maxsize = acfptr->read_max; 03947 } else { 03948 maxsize = VAR_BUF_SIZE; 03949 } 03950 } else { 03951 maxsize = maxlen; 03952 } 03953 ast_str_make_space(str, maxsize); 03954 } 03955 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 03956 } 03957 if (acfptr->mod && u) { 03958 __ast_module_user_remove(acfptr->mod, u); 03959 } 03960 return res; 03961 } 03962 return -1; 03963 }
int ast_func_write | ( | struct ast_channel * | chan, | |
const char * | function, | |||
const char * | value | |||
) |
executes a write operation on a function
chan | Channel to execute on | |
function | Data containing the function call string (will be modified) | |
value | A value parameter to pass for writing |
This application executes a function in write mode on a given channel.
0 | success | |
non-zero | failure |
Definition at line 3965 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_strdupa, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.
Referenced by conf_run(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
03966 { 03967 char *copy = ast_strdupa(function); 03968 char *args = func_args(copy); 03969 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03970 03971 if (acfptr == NULL) 03972 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03973 else if (!acfptr->write) 03974 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 03975 else { 03976 int res; 03977 struct ast_module_user *u = NULL; 03978 if (acfptr->mod) 03979 u = __ast_module_user_add(acfptr->mod, chan); 03980 res = acfptr->write(chan, copy, args, value); 03981 if (acfptr->mod && u) 03982 __ast_module_user_remove(acfptr->mod, u); 03983 return res; 03984 } 03985 03986 return -1; 03987 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 10653 of file pbx.c.
References ast_context::name.
Referenced by _macro_exec(), ast_compile_ael2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_include2(), ast_context_remove_switch2(), ast_context_verify_includes(), ast_remove_hint(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), context_merge_incls_swits_igps_other_registrars(), destroy_hint(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
10654 { 10655 return con ? con->name : NULL; 10656 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 10691 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
10692 { 10693 return c ? c->registrar : NULL; 10694 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 10721 of file pbx.c.
References ast_exten::app.
Referenced by _macro_exec(), ast_add_hint(), ast_extension_state2(), ast_get_hint(), ast_str_get_hint(), find_matching_endwhile(), get_parking_exten(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), and print_ext().
10722 { 10723 return e ? e->app : NULL; 10724 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 10726 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), ast_masq_park_call_exten(), ast_park_call_exten(), ast_str_get_hint(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), print_ext(), and xfer_park_call_helper().
10727 { 10728 return e ? e->data : NULL; 10729 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 10716 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10717 { 10718 return e ? e->cidmatch : NULL; 10719 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 10658 of file pbx.c.
References ast_exten::parent.
Referenced by ast_remove_hint(), destroy_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), and hints_data_provider_get().
10659 { 10660 return exten ? exten->parent : NULL; 10661 }
const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 10668 of file pbx.c.
References ast_exten::label.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10669 { 10670 return exten ? exten->label : NULL; 10671 }
int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 10711 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10712 { 10713 return e ? e->matchcid : 0; 10714 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 10663 of file pbx.c.
References ast_exten::exten.
Referenced by ast_add_hint(), ast_remove_hint(), complete_core_show_hint(), complete_dialplan_remove_extension(), destroy_hint(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hint_hash(), hints_data_provider_get(), manager_show_dialplan_helper(), and show_dialplan_helper().
10664 { 10665 return exten ? exten->exten : NULL; 10666 }
int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 10683 of file pbx.c.
References ast_exten::priority.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().
10684 { 10685 return exten ? exten->priority : -1; 10686 }
const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 10696 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10697 { 10698 return e ? e->registrar : NULL; 10699 }
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 5062 of file pbx.c.
References ast_copy_string(), ast_get_extension_app(), ast_get_extension_app_data(), and ast_hint_extension().
Referenced by action_extensionstate(), get_cid_name(), get_destination(), hint_read(), manager_state_cb(), skinny_extensionstate_cb(), and state_notify_build_xml().
05063 { 05064 struct ast_exten *e = ast_hint_extension(c, context, exten); 05065 05066 if (e) { 05067 if (hint) 05068 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 05069 if (name) { 05070 const char *tmp = ast_get_extension_app_data(e); 05071 if (tmp) 05072 ast_copy_string(name, tmp, namesize); 05073 } 05074 return -1; 05075 } 05076 return 0; 05077 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10678 of file pbx.c.
References ast_ignorepat::pattern.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
10679 { 10680 return ip ? ip->pattern : NULL; 10681 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10706 of file pbx.c.
References ast_ignorepat::registrar.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10707 { 10708 return ip ? ip->registrar : NULL; 10709 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 10673 of file pbx.c.
References ast_include::name.
Referenced by complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
10674 { 10675 return inc ? inc->name : NULL; 10676 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 10701 of file pbx.c.
References ast_include::registrar.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10702 { 10703 return i ? i->registrar : NULL; 10704 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 10736 of file pbx.c.
References ast_sw::data.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10737 { 10738 return sw ? sw->data : NULL; 10739 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 10741 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
10742 { 10743 return sw->eval; 10744 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 10731 of file pbx.c.
References ast_sw::name.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10732 { 10733 return sw ? sw->name : NULL; 10734 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 10746 of file pbx.c.
References ast_sw::registrar.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10747 { 10748 return sw ? sw->registrar : NULL; 10749 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10841 of file pbx.c.
References __ast_goto_if_exists().
Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), dial_exec_full(), goto_exten(), onedigit_goto(), select_entry(), valid_exit(), vm_execmain(), and vmauthenticate().
10842 { 10843 return __ast_goto_if_exists(chan, context, exten, priority, 0); 10844 }
int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
const void * | ah_b | |||
) |
hashtable functions for contexts
Definition at line 1081 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01082 { 01083 const struct ast_context *ac = ah_a; 01084 const struct ast_context *bc = ah_b; 01085 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01086 return 1; 01087 /* assume context names are registered in a string table! */ 01088 return strcmp(ac->name, bc->name); 01089 }
unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1124 of file pbx.c.
References ast_hashtab_hash_string(), and ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01125 { 01126 const struct ast_context *ac = obj; 01127 return ast_hashtab_hash_string(ac->name); 01128 }
static struct ast_exten* ast_hint_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) | [static, read] |
Definition at line 4539 of file pbx.c.
References ast_hint_extension_nolock(), ast_rdlock_contexts(), and ast_unlock_contexts().
Referenced by ast_extension_state(), ast_extension_state_add_destroy(), ast_get_hint(), and ast_str_get_hint().
04540 { 04541 struct ast_exten *e; 04542 ast_rdlock_contexts(); 04543 e = ast_hint_extension_nolock(c, context, exten); 04544 ast_unlock_contexts(); 04545 return e; 04546 }
static struct ast_exten* ast_hint_extension_nolock | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) | [static, read] |
Find hint for given extension in context.
Definition at line 4533 of file pbx.c.
References E_MATCH, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.
Referenced by ast_hint_extension(), and ast_merge_contexts_and_delete().
04534 { 04535 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 04536 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 04537 }
int ast_ignore_pattern | ( | const char * | context, | |
const char * | pattern | |||
) |
Checks to see if a number should be ignored.
context | context to search within | |
pattern | to check whether it should be ignored or not |
Check if a number should be ignored with respect to dialtone cancellation.
0 | if the pattern should not be ignored | |
non-zero | if the pattern should be ignored |
Definition at line 8323 of file pbx.c.
References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_enbloc_call_message(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), and skinny_ss().
08324 { 08325 struct ast_context *con = ast_context_find(context); 08326 08327 if (con) { 08328 struct ast_ignorepat *pat; 08329 08330 for (pat = con->ignorepats; pat; pat = pat->next) { 08331 if (ast_extension_match(pat->pattern, pattern)) 08332 return 1; 08333 } 08334 } 08335 08336 return 0; 08337 }
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).
c | not really important XXX | |
context | context to serach within | |
exten | extension to check | |
priority | priority of extension path | |
callerid | callerid of extension being searched for |
Definition at line 5120 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by __analog_ss_thread(), __ast_pbx_run(), analog_ss_thread(), ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), readexten_exec(), and skinny_ss().
05121 { 05122 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 05123 }
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.
extcontexts | pointer to the ast_context structure | |
exttable | pointer to the ast_hashtab structure that contains all the elements in extcontexts | |
registrar | of 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 7620 of file pbx.c.
References __ast_internal_context_destroy(), ao2_callback, ao2_container_count(), ao2_find, ao2_iterator_destroy(), AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr(), ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), store_hint::callbacks, ast_hint::callbacks, ast_state_cb::change_cb, store_hint::context, context_merge(), context_merge_lock, contexts, contexts_table, ast_state_cb::data, ast_exten::data, store_hint::data, E_MATCH, store_hint::exten, ast_exten::exten, ast_hint::exten, hints, ast_hint::laststate, store_hint::laststate, ast_context::name, ast_context::next, ast_sw::next, OBJ_UNLINK, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_exten::registrar, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
07621 { 07622 double ft; 07623 struct ast_context *tmp; 07624 struct ast_context *oldcontextslist; 07625 struct ast_hashtab *oldtable; 07626 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07627 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07628 struct store_hint *saved_hint; 07629 struct ast_hint *hint; 07630 struct ast_exten *exten; 07631 int length; 07632 struct ast_state_cb *thiscb; 07633 struct ast_hashtab_iter *iter; 07634 struct ao2_iterator i; 07635 struct timeval begintime; 07636 struct timeval writelocktime; 07637 struct timeval endlocktime; 07638 struct timeval enddeltime; 07639 07640 /* 07641 * It is very important that this function hold the hints 07642 * container lock _and_ the conlock during its operation; not 07643 * only do we need to ensure that the list of contexts and 07644 * extensions does not change, but also that no hint callbacks 07645 * (watchers) are added or removed during the merge/delete 07646 * process 07647 * 07648 * In addition, the locks _must_ be taken in this order, because 07649 * there are already other code paths that use this order 07650 */ 07651 07652 begintime = ast_tvnow(); 07653 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */ 07654 ast_wrlock_contexts(); 07655 iter = ast_hashtab_start_traversal(contexts_table); 07656 while ((tmp = ast_hashtab_next(iter))) { 07657 context_merge(extcontexts, exttable, tmp, registrar); 07658 } 07659 ast_hashtab_end_traversal(iter); 07660 07661 ao2_lock(hints); 07662 writelocktime = ast_tvnow(); 07663 07664 /* preserve all watchers for hints */ 07665 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07666 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 07667 if (ao2_container_count(hint->callbacks)) { 07668 ao2_lock(hint); 07669 if (!hint->exten) { 07670 /* The extension has already been destroyed. (Should never happen here) */ 07671 ao2_unlock(hint); 07672 continue; 07673 } 07674 07675 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 07676 + sizeof(*saved_hint); 07677 if (!(saved_hint = ast_calloc(1, length))) { 07678 ao2_unlock(hint); 07679 continue; 07680 } 07681 07682 /* This removes all the callbacks from the hint into saved_hint. */ 07683 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 07684 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry); 07685 /* 07686 * We intentionally do not unref thiscb to account for the 07687 * non-ao2 reference in saved_hint->callbacks 07688 */ 07689 } 07690 07691 saved_hint->laststate = hint->laststate; 07692 saved_hint->context = saved_hint->data; 07693 strcpy(saved_hint->data, hint->exten->parent->name); 07694 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1; 07695 strcpy(saved_hint->exten, hint->exten->exten); 07696 ao2_unlock(hint); 07697 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); 07698 } 07699 } 07700 ao2_iterator_destroy(&i); 07701 07702 /* save the old table and list */ 07703 oldtable = contexts_table; 07704 oldcontextslist = contexts; 07705 07706 /* move in the new table and list */ 07707 contexts_table = exttable; 07708 contexts = *extcontexts; 07709 07710 /* 07711 * Restore the watchers for hints that can be found; notify 07712 * those that cannot be restored. 07713 */ 07714 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) { 07715 struct pbx_find_info q = { .stacklen = 0 }; 07716 07717 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten, 07718 PRIORITY_HINT, NULL, "", E_MATCH); 07719 /* 07720 * If this is a pattern, dynamically create a new extension for this 07721 * particular match. Note that this will only happen once for each 07722 * individual extension, because the pattern will no longer match first. 07723 */ 07724 if (exten && exten->exten[0] == '_') { 07725 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten, 07726 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr, 07727 exten->registrar); 07728 /* rwlocks are not recursive locks */ 07729 exten = ast_hint_extension_nolock(NULL, saved_hint->context, 07730 saved_hint->exten); 07731 } 07732 07733 /* Find the hint in the hints container */ 07734 hint = exten ? ao2_find(hints, exten, 0) : NULL; 07735 if (!hint) { 07736 /* 07737 * Notify watchers of this removed hint later when we aren't 07738 * encumberd by so many locks. 07739 */ 07740 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list); 07741 } else { 07742 ao2_lock(hint); 07743 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07744 ao2_link(hint->callbacks, thiscb); 07745 /* Ref that we added when putting into saved_hint->callbacks */ 07746 ao2_ref(thiscb, -1); 07747 } 07748 hint->laststate = saved_hint->laststate; 07749 ao2_unlock(hint); 07750 ao2_ref(hint, -1); 07751 ast_free(saved_hint); 07752 } 07753 } 07754 07755 ao2_unlock(hints); 07756 ast_unlock_contexts(); 07757 07758 /* 07759 * Notify watchers of all removed hints with the same lock 07760 * environment as handle_statechange(). 07761 */ 07762 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) { 07763 /* this hint has been removed, notify the watchers */ 07764 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07765 thiscb->change_cb(saved_hint->context, saved_hint->exten, 07766 AST_EXTENSION_REMOVED, thiscb->data); 07767 /* Ref that we added when putting into saved_hint->callbacks */ 07768 ao2_ref(thiscb, -1); 07769 } 07770 ast_free(saved_hint); 07771 } 07772 07773 ast_mutex_unlock(&context_merge_lock); 07774 endlocktime = ast_tvnow(); 07775 07776 /* 07777 * The old list and hashtab no longer are relevant, delete them 07778 * while the rest of asterisk is now freely using the new stuff 07779 * instead. 07780 */ 07781 07782 ast_hashtab_destroy(oldtable, NULL); 07783 07784 for (tmp = oldcontextslist; tmp; ) { 07785 struct ast_context *next; /* next starting point */ 07786 07787 next = tmp->next; 07788 __ast_internal_context_destroy(tmp); 07789 tmp = next; 07790 } 07791 enddeltime = ast_tvnow(); 07792 07793 ft = ast_tvdiff_us(writelocktime, begintime); 07794 ft /= 1000000.0; 07795 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 07796 07797 ft = ast_tvdiff_us(endlocktime, writelocktime); 07798 ft /= 1000000.0; 07799 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 07800 07801 ft = ast_tvdiff_us(enddeltime, endlocktime); 07802 ft /= 1000000.0; 07803 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 07804 07805 ft = ast_tvdiff_us(enddeltime, begintime); 07806 ft /= 1000000.0; 07807 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 07808 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10906 of file pbx.c.
References pbx_parseable_goto().
Referenced by _while_exec(), check_goto_on_transfer(), dial_exec_full(), gosub_exec(), ivr_dispatch(), parkandannounce_exec(), pbx_builtin_goto(), and while_continue_exec().
10907 { 10908 return pbx_parseable_goto(chan, goto_string, 0); 10909 }
int ast_pbx_init | ( | void | ) |
Provided by pbx.c
Definition at line 10983 of file pbx.c.
References ao2_container_alloc, ast_register_atexit(), HASH_EXTENHINT_SIZE, hint_cmp(), hint_hash(), hints, pbx_shutdown(), statecbs, and statecbs_cmp().
Referenced by main().
10984 { 10985 hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp); 10986 statecbs = ao2_container_alloc(1, NULL, statecbs_cmp); 10987 10988 ast_register_atexit(pbx_shutdown); 10989 10990 return (hints && statecbs) ? 0 : -1; 10991 }
int ast_pbx_outgoing_app | ( | const char * | type, | |
format_t | format, | |||
void * | data, | |||
int | timeout, | |||
const char * | app, | |||
const char * | appdata, | |||
int * | reason, | |||
int | sync, | |||
const char * | cid_num, | |||
const char * | cid_name, | |||
struct ast_variable * | vars, | |||
const char * | account, | |||
struct ast_channel ** | locked_channel | |||
) |
Synchronously or asynchronously make an outbound call and send it to a particular application with given extension
Definition at line 9217 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, async_stat::appdata, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create_detached, ast_set_variables(), AST_STATE_UP, ast_string_field_free_memory, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, errno, ast_channel::hangupcause, LOG_WARNING, async_stat::p, app_tmp::t, async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_app(), and originate_exec().
09218 { 09219 struct ast_channel *chan; 09220 struct app_tmp *tmp; 09221 int res = -1, cdr_res = -1; 09222 struct outgoing_helper oh; 09223 09224 memset(&oh, 0, sizeof(oh)); 09225 oh.vars = vars; 09226 oh.account = account; 09227 09228 if (locked_channel) 09229 *locked_channel = NULL; 09230 if (ast_strlen_zero(app)) { 09231 res = -1; 09232 goto outgoing_app_cleanup; 09233 } 09234 if (synchronous) { 09235 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09236 if (chan) { 09237 ast_set_variables(chan, vars); 09238 if (account) 09239 ast_cdr_setaccount(chan, account); 09240 if (chan->_state == AST_STATE_UP) { 09241 res = 0; 09242 ast_verb(4, "Channel %s was answered.\n", chan->name); 09243 tmp = ast_calloc(1, sizeof(*tmp)); 09244 if (!tmp || ast_string_field_init(tmp, 252)) { 09245 if (tmp) { 09246 ast_free(tmp); 09247 } 09248 res = -1; 09249 } else { 09250 ast_string_field_set(tmp, app, app); 09251 ast_string_field_set(tmp, data, appdata); 09252 tmp->chan = chan; 09253 if (synchronous > 1) { 09254 if (locked_channel) 09255 ast_channel_unlock(chan); 09256 ast_pbx_run_app(tmp); 09257 } else { 09258 if (locked_channel) 09259 ast_channel_lock(chan); 09260 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 09261 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 09262 ast_string_field_free_memory(tmp); 09263 ast_free(tmp); 09264 if (locked_channel) 09265 ast_channel_unlock(chan); 09266 ast_hangup(chan); 09267 res = -1; 09268 } else { 09269 if (locked_channel) 09270 *locked_channel = chan; 09271 } 09272 } 09273 } 09274 } else { 09275 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09276 if (chan->cdr) { /* update the cdr */ 09277 /* here we update the status of the call, which sould be busy. 09278 * if that fails then we set the status to failed */ 09279 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09280 ast_cdr_failed(chan->cdr); 09281 } 09282 ast_hangup(chan); 09283 } 09284 } 09285 09286 if (res < 0) { /* the call failed for some reason */ 09287 if (*reason == 0) { /* if the call failed (not busy or no answer) 09288 * update the cdr with the failed message */ 09289 cdr_res = ast_pbx_outgoing_cdr_failed(); 09290 if (cdr_res != 0) { 09291 res = cdr_res; 09292 goto outgoing_app_cleanup; 09293 } 09294 } 09295 } 09296 09297 } else { 09298 struct async_stat *as; 09299 if (!(as = ast_calloc(1, sizeof(*as)))) { 09300 res = -1; 09301 goto outgoing_app_cleanup; 09302 } 09303 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09304 if (!chan) { 09305 ast_free(as); 09306 res = -1; 09307 goto outgoing_app_cleanup; 09308 } 09309 as->chan = chan; 09310 ast_copy_string(as->app, app, sizeof(as->app)); 09311 if (appdata) 09312 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 09313 as->timeout = timeout; 09314 ast_set_variables(chan, vars); 09315 if (account) 09316 ast_cdr_setaccount(chan, account); 09317 /* Start a new thread, and get something handling this channel. */ 09318 if (locked_channel) 09319 ast_channel_lock(chan); 09320 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09321 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09322 ast_free(as); 09323 if (locked_channel) 09324 ast_channel_unlock(chan); 09325 ast_hangup(chan); 09326 res = -1; 09327 goto outgoing_app_cleanup; 09328 } else { 09329 if (locked_channel) 09330 *locked_channel = chan; 09331 } 09332 res = 0; 09333 } 09334 outgoing_app_cleanup: 09335 ast_variables_destroy(vars); 09336 return res; 09337 }
static int ast_pbx_outgoing_cdr_failed | ( | void | ) | [static] |
Function to post an empty cdr after a spool call fails.
Definition at line 9021 of file pbx.c.
References ast_cdr_alloc(), ast_cdr_detach(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_start(), ast_channel_unref, ast_dummy_channel_alloc, and ast_channel::cdr.
Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
09022 { 09023 /* allocate a channel */ 09024 struct ast_channel *chan = ast_dummy_channel_alloc(); 09025 09026 if (!chan) 09027 return -1; /* failure */ 09028 09029 chan->cdr = ast_cdr_alloc(); 09030 if (!chan->cdr) { 09031 /* allocation of the cdr failed */ 09032 chan = ast_channel_unref(chan); /* free the channel */ 09033 return -1; /* return failure */ 09034 } 09035 09036 /* allocation of the cdr was successful */ 09037 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 09038 ast_cdr_start(chan->cdr); /* record the start and stop time */ 09039 ast_cdr_end(chan->cdr); 09040 ast_cdr_failed(chan->cdr); /* set the status to failed */ 09041 ast_cdr_detach(chan->cdr); /* post and free the record */ 09042 chan->cdr = NULL; 09043 chan = ast_channel_unref(chan); /* free the channel */ 09044 09045 return 0; /* success */ 09046 }
int ast_pbx_outgoing_exten | ( | const char * | type, | |
format_t | format, | |||
void * | data, | |||
int | timeout, | |||
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int * | reason, | |||
int | sync, | |||
const char * | cid_num, | |||
const char * | cid_name, | |||
struct ast_variable * | vars, | |||
const char * | account, | |||
struct ast_channel ** | locked_channel | |||
) |
Synchronously or asynchronously make an outbound call and send it to a particular extension
Definition at line 9048 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_exists_extension(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create_detached, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, outgoing_helper::cid_name, outgoing_helper::cid_num, async_stat::context, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, async_stat::p, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_exten(), and originate_exec().
09049 { 09050 struct ast_channel *chan; 09051 struct async_stat *as; 09052 int res = -1, cdr_res = -1; 09053 struct outgoing_helper oh; 09054 09055 if (synchronous) { 09056 oh.context = context; 09057 oh.exten = exten; 09058 oh.priority = priority; 09059 oh.cid_num = cid_num; 09060 oh.cid_name = cid_name; 09061 oh.account = account; 09062 oh.vars = vars; 09063 oh.parent_channel = NULL; 09064 09065 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09066 if (channel) { 09067 *channel = chan; 09068 if (chan) 09069 ast_channel_lock(chan); 09070 } 09071 if (chan) { 09072 if (chan->_state == AST_STATE_UP) { 09073 res = 0; 09074 ast_verb(4, "Channel %s was answered.\n", chan->name); 09075 09076 if (synchronous > 1) { 09077 if (channel) 09078 ast_channel_unlock(chan); 09079 if (ast_pbx_run(chan)) { 09080 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09081 if (channel) 09082 *channel = NULL; 09083 ast_hangup(chan); 09084 chan = NULL; 09085 res = -1; 09086 } 09087 } else { 09088 if (ast_pbx_start(chan)) { 09089 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 09090 if (channel) { 09091 *channel = NULL; 09092 ast_channel_unlock(chan); 09093 } 09094 ast_hangup(chan); 09095 res = -1; 09096 } 09097 chan = NULL; 09098 } 09099 } else { 09100 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09101 09102 if (chan->cdr) { /* update the cdr */ 09103 /* here we update the status of the call, which sould be busy. 09104 * if that fails then we set the status to failed */ 09105 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09106 ast_cdr_failed(chan->cdr); 09107 } 09108 09109 if (channel) { 09110 *channel = NULL; 09111 ast_channel_unlock(chan); 09112 } 09113 ast_hangup(chan); 09114 chan = NULL; 09115 } 09116 } 09117 09118 if (res < 0) { /* the call failed for some reason */ 09119 if (*reason == 0) { /* if the call failed (not busy or no answer) 09120 * update the cdr with the failed message */ 09121 cdr_res = ast_pbx_outgoing_cdr_failed(); 09122 if (cdr_res != 0) { 09123 res = cdr_res; 09124 goto outgoing_exten_cleanup; 09125 } 09126 } 09127 09128 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 09129 /* check if "failed" exists */ 09130 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 09131 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 09132 if (chan) { 09133 char failed_reason[4] = ""; 09134 if (!ast_strlen_zero(context)) 09135 ast_copy_string(chan->context, context, sizeof(chan->context)); 09136 set_ext_pri(chan, "failed", 1); 09137 ast_set_variables(chan, vars); 09138 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 09139 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 09140 if (account) 09141 ast_cdr_setaccount(chan, account); 09142 if (ast_pbx_run(chan)) { 09143 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09144 ast_hangup(chan); 09145 } 09146 chan = NULL; 09147 } 09148 } 09149 } 09150 } else { 09151 if (!(as = ast_calloc(1, sizeof(*as)))) { 09152 res = -1; 09153 goto outgoing_exten_cleanup; 09154 } 09155 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 09156 if (channel) { 09157 *channel = chan; 09158 if (chan) 09159 ast_channel_lock(chan); 09160 } 09161 if (!chan) { 09162 ast_free(as); 09163 res = -1; 09164 goto outgoing_exten_cleanup; 09165 } 09166 as->chan = chan; 09167 ast_copy_string(as->context, context, sizeof(as->context)); 09168 set_ext_pri(as->chan, exten, priority); 09169 as->timeout = timeout; 09170 ast_set_variables(chan, vars); 09171 if (account) 09172 ast_cdr_setaccount(chan, account); 09173 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09174 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09175 ast_free(as); 09176 if (channel) { 09177 *channel = NULL; 09178 ast_channel_unlock(chan); 09179 } 09180 ast_hangup(chan); 09181 res = -1; 09182 goto outgoing_exten_cleanup; 09183 } 09184 res = 0; 09185 } 09186 outgoing_exten_cleanup: 09187 ast_variables_destroy(vars); 09188 return res; 09189 }
enum ast_pbx_result ast_pbx_run | ( | struct ast_channel * | c | ) |
Execute the PBX in the current thread.
c | channel 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.
Zero | on success | |
non-zero | on failure |
Definition at line 5626 of file pbx.c.
References ast_pbx_run_args().
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_pbx_outgoing_exten(), async_wait(), do_notify(), mgcp_ss(), skinny_newcall(), and unistim_ss().
05627 { 05628 return ast_pbx_run_args(c, NULL); 05629 }
static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 9201 of file pbx.c.
References app_tmp::app, ast_free, ast_hangup(), ast_log(), ast_string_field_free_memory, ast_verb, app_tmp::chan, app_tmp::data, LOG_WARNING, pbx_exec(), and pbx_findapp().
Referenced by ast_pbx_outgoing_app().
09202 { 09203 struct app_tmp *tmp = data; 09204 struct ast_app *app; 09205 app = pbx_findapp(tmp->app); 09206 if (app) { 09207 ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 09208 pbx_exec(tmp->chan, app, tmp->data); 09209 } else 09210 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 09211 ast_hangup(tmp->chan); 09212 ast_string_field_free_memory(tmp); 09213 ast_free(tmp); 09214 return NULL; 09215 }
enum ast_pbx_result ast_pbx_run_args | ( | struct ast_channel * | c, | |
struct ast_pbx_args * | args | |||
) |
Execute the PBX in the current thread.
c | channel to run the pbx on | |
args | options 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.
Zero | on success | |
non-zero | on failure |
Definition at line 5606 of file pbx.c.
References __ast_pbx_run(), ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_test_flag, decrease_call_count(), increase_call_count(), and LOG_WARNING.
Referenced by ast_pbx_run(), dial_exec_full(), handle_gosub(), and try_calling().
05607 { 05608 enum ast_pbx_result res = AST_PBX_SUCCESS; 05609 05610 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05611 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05612 return AST_PBX_FAILED; 05613 } 05614 05615 if (increase_call_count(c)) { 05616 return AST_PBX_CALL_LIMIT; 05617 } 05618 05619 res = __ast_pbx_run(c, args); 05620 05621 decrease_call_count(); 05622 05623 return res; 05624 }
enum ast_pbx_result ast_pbx_start | ( | struct ast_channel * | c | ) |
Create a new thread and start the PBX.
c | channel to start the pbx on |
Zero | on success | |
non-zero | on failure |
Definition at line 5579 of file pbx.c.
References ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, ast_test_flag, decrease_call_count(), increase_call_count(), LOG_WARNING, and pbx_thread().
Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_pbx_outgoing_exten(), bridge_call_thread(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), generic_recall(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), manage_parked_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), skinny_new(), and unistim_new().
05580 { 05581 pthread_t t; 05582 05583 if (!c) { 05584 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05585 return AST_PBX_FAILED; 05586 } 05587 05588 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05589 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05590 return AST_PBX_FAILED; 05591 } 05592 05593 if (increase_call_count(c)) 05594 return AST_PBX_CALL_LIMIT; 05595 05596 /* Start a new thread, and get something handling this channel. */ 05597 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05598 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05599 decrease_call_count(); 05600 return AST_PBX_FAILED; 05601 } 05602 05603 return AST_PBX_SUCCESS; 05604 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5636 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05637 { 05638 return totalcalls; 05639 }
int ast_rdlock_context | ( | struct ast_context * | con | ) |
Read locks a given context.
con | context to lock |
0 | on success | |
-1 | on failure |
Definition at line 10640 of file pbx.c.
References ast_rwlock_rdlock, and ast_context::lock.
Referenced by _macro_exec(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_cli_dialplan_save(), lookup_c_ip(), lookup_ci(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
10641 { 10642 return ast_rwlock_rdlock(&con->lock); 10643 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10622 of file pbx.c.
References ast_mutex_lock, and conlock.
Referenced by _macro_exec(), ast_context_find(), ast_context_find_or_create(), ast_hint_extension(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
10623 { 10624 return ast_mutex_lock(&conlock); 10625 }
int ast_register_application2 | ( | const char * | app, | |
int(*)(struct ast_channel *, const char *) | execute, | |||
const char * | synopsis, | |||
const char * | description, | |||
void * | mod | |||
) |
Dynamically register a new dial plan application.
Register an application.
Definition at line 6047 of file pbx.c.
References ast_app::arguments, ast_calloc, ast_free, ast_log(), ast_module_name(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_verb, AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), COLOR_BRCYAN, ast_app::docsrc, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, ast_app::seealso, ast_app::syntax, and term_color().
Referenced by ast_cc_init(), ast_features_init(), and load_pbx().
06048 { 06049 struct ast_app *tmp, *cur = NULL; 06050 char tmps[80]; 06051 int length, res; 06052 #ifdef AST_XML_DOCS 06053 char *tmpxml; 06054 #endif 06055 06056 AST_RWLIST_WRLOCK(&apps); 06057 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 06058 if (!(res = strcasecmp(app, tmp->name))) { 06059 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 06060 AST_RWLIST_UNLOCK(&apps); 06061 return -1; 06062 } else if (res < 0) 06063 break; 06064 } 06065 06066 length = sizeof(*tmp) + strlen(app) + 1; 06067 06068 if (!(tmp = ast_calloc(1, length))) { 06069 AST_RWLIST_UNLOCK(&apps); 06070 return -1; 06071 } 06072 06073 if (ast_string_field_init(tmp, 128)) { 06074 AST_RWLIST_UNLOCK(&apps); 06075 ast_free(tmp); 06076 return -1; 06077 } 06078 06079 strcpy(tmp->name, app); 06080 tmp->execute = execute; 06081 tmp->module = mod; 06082 06083 #ifdef AST_XML_DOCS 06084 /* Try to lookup the docs in our XML documentation database */ 06085 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 06086 /* load synopsis */ 06087 tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module)); 06088 ast_string_field_set(tmp, synopsis, tmpxml); 06089 ast_free(tmpxml); 06090 06091 /* load description */ 06092 tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module)); 06093 ast_string_field_set(tmp, description, tmpxml); 06094 ast_free(tmpxml); 06095 06096 /* load syntax */ 06097 tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module)); 06098 ast_string_field_set(tmp, syntax, tmpxml); 06099 ast_free(tmpxml); 06100 06101 /* load arguments */ 06102 tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module)); 06103 ast_string_field_set(tmp, arguments, tmpxml); 06104 ast_free(tmpxml); 06105 06106 /* load seealso */ 06107 tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module)); 06108 ast_string_field_set(tmp, seealso, tmpxml); 06109 ast_free(tmpxml); 06110 tmp->docsrc = AST_XML_DOC; 06111 } else { 06112 #endif 06113 ast_string_field_set(tmp, synopsis, synopsis); 06114 ast_string_field_set(tmp, description, description); 06115 #ifdef AST_XML_DOCS 06116 tmp->docsrc = AST_STATIC_DOC; 06117 } 06118 #endif 06119 06120 /* Store in alphabetical order */ 06121 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 06122 if (strcasecmp(tmp->name, cur->name) < 0) { 06123 AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list); 06124 break; 06125 } 06126 } 06127 AST_RWLIST_TRAVERSE_SAFE_END; 06128 if (!cur) 06129 AST_RWLIST_INSERT_TAIL(&apps, tmp, list); 06130 06131 ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 06132 06133 AST_RWLIST_UNLOCK(&apps); 06134 06135 return 0; 06136 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
This function registers a populated ast_switch structure with the asterisk switching architecture.
0 | success | |
non-zero | failure |
Definition at line 6142 of file pbx.c.
References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, LOG_WARNING, and ast_switch::name.
Referenced by load_module().
06143 { 06144 struct ast_switch *tmp; 06145 06146 AST_RWLIST_WRLOCK(&switches); 06147 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 06148 if (!strcasecmp(tmp->name, sw->name)) { 06149 AST_RWLIST_UNLOCK(&switches); 06150 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 06151 return -1; 06152 } 06153 } 06154 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 06155 AST_RWLIST_UNLOCK(&switches); 06156 06157 return 0; 06158 }
static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
Remove hint from extension.
Definition at line 4941 of file pbx.c.
References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), ast_get_context_name(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::context_name, ast_hint::exten, ast_hint::exten_name, hints, and OBJ_UNLINK.
Referenced by destroy_exten().
04942 { 04943 /* Cleanup the Notifys if hint is removed */ 04944 struct ast_hint *hint; 04945 04946 if (!e) { 04947 return -1; 04948 } 04949 04950 hint = ao2_find(hints, e, OBJ_UNLINK); 04951 if (!hint) { 04952 return -1; 04953 } 04954 04955 /* 04956 * The extension is being destroyed so we must save some 04957 * information to notify that the extension is deactivated. 04958 */ 04959 ao2_lock(hint); 04960 ast_copy_string(hint->context_name, 04961 ast_get_context_name(ast_get_extension_context(hint->exten)), 04962 sizeof(hint->context_name)); 04963 ast_copy_string(hint->exten_name, ast_get_extension_name(hint->exten), 04964 sizeof(hint->exten_name)); 04965 hint->exten = NULL; 04966 ao2_unlock(hint); 04967 04968 ao2_ref(hint, -1); 04969 04970 return 0; 04971 }
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).
c | not important | |
context | which context to generate the extension within | |
exten | new extension to add | |
priority | priority of new extension | |
callerid | callerid of extension | |
found | ||
combined_find_spawn | This adds a new extension to the asterisk extension list. |
0 | on success | |
-1 | on failure. |
Definition at line 5125 of file pbx.c.
References E_SPAWN, and pbx_extension_helper().
Referenced by __ast_pbx_run(), _macro_exec(), ast_bridge_call(), dial_exec_full(), and loopback_exec().
05126 { 05127 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 05128 }
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 5080 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), and ast_str_set().
Referenced by ast_str_retrieve_variable().
05081 { 05082 struct ast_exten *e = ast_hint_extension(c, context, exten); 05083 05084 if (!e) { 05085 return 0; 05086 } 05087 05088 if (hint) { 05089 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 05090 } 05091 if (name) { 05092 const char *tmp = ast_get_extension_app_data(e); 05093 if (tmp) { 05094 ast_str_set(name, namesize, "%s", tmp); 05095 } 05096 } 05097 return -1; 05098 }
const char* ast_str_retrieve_variable | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct ast_channel * | chan, | |||
struct varshead * | headp, | |||
const char * | var | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
chan | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
headp | If no channel is specified, a channel list from which to extract variable values | |
var | Variable name to retrieve. |
Definition at line 3370 of file pbx.c.
References ast_party_caller::ani2, ARRAY_LEN, ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_debug, ast_eid_default, ast_eid_to_str(), AST_LIST_TRAVERSE, ast_party_id_presentation(), ast_rwlock_rdlock, ast_rwlock_unlock, ast_str_buffer(), ast_str_get_hint(), ast_str_set(), ast_str_substring(), ast_strdupa, ast_var_name(), ast_var_value(), ast_channel::caller, ast_channel::context, ast_channel::dialed, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_party_caller::id, ast_party_id::number, parse_variable_name(), ast_party_number::plan, ast_channel::priority, ast_party_dialed::transit_network_select, and ast_channel::varshead.
Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().
03371 { 03372 const char not_found = '\0'; 03373 char *tmpvar; 03374 const char *ret; 03375 const char *s; /* the result */ 03376 int offset, length; 03377 int i, need_substring; 03378 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 03379 char workspace[20]; 03380 03381 if (c) { 03382 ast_channel_lock(c); 03383 places[0] = &c->varshead; 03384 } 03385 /* 03386 * Make a copy of var because parse_variable_name() modifies the string. 03387 * Then if called directly, we might need to run substring() on the result; 03388 * remember this for later in 'need_substring', 'offset' and 'length' 03389 */ 03390 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03391 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03392 03393 /* 03394 * Look first into predefined variables, then into variable lists. 03395 * Variable 's' points to the result, according to the following rules: 03396 * s == ¬_found (set at the beginning) means that we did not find a 03397 * matching variable and need to look into more places. 03398 * If s != ¬_found, s is a valid result string as follows: 03399 * s = NULL if the variable does not have a value; 03400 * you typically do this when looking for an unset predefined variable. 03401 * s = workspace if the result has been assembled there; 03402 * typically done when the result is built e.g. with an snprintf(), 03403 * so we don't need to do an additional copy. 03404 * s != workspace in case we have a string, that needs to be copied 03405 * (the ast_copy_string is done once for all at the end). 03406 * Typically done when the result is already available in some string. 03407 */ 03408 s = ¬_found; /* default value */ 03409 if (c) { /* This group requires a valid channel */ 03410 /* Names with common parts are looked up a piece at a time using strncmp. */ 03411 if (!strncmp(var, "CALL", 4)) { 03412 if (!strncmp(var + 4, "ING", 3)) { 03413 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03414 ast_str_set(str, maxlen, "%d", 03415 ast_party_id_presentation(&c->caller.id)); 03416 s = ast_str_buffer(*str); 03417 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03418 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03419 s = ast_str_buffer(*str); 03420 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03421 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03422 s = ast_str_buffer(*str); 03423 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03424 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03425 s = ast_str_buffer(*str); 03426 } 03427 } 03428 } else if (!strcmp(var, "HINT")) { 03429 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03430 } else if (!strcmp(var, "HINTNAME")) { 03431 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03432 } else if (!strcmp(var, "EXTEN")) { 03433 s = c->exten; 03434 } else if (!strcmp(var, "CONTEXT")) { 03435 s = c->context; 03436 } else if (!strcmp(var, "PRIORITY")) { 03437 ast_str_set(str, maxlen, "%d", c->priority); 03438 s = ast_str_buffer(*str); 03439 } else if (!strcmp(var, "CHANNEL")) { 03440 s = c->name; 03441 } else if (!strcmp(var, "UNIQUEID")) { 03442 s = c->uniqueid; 03443 } else if (!strcmp(var, "HANGUPCAUSE")) { 03444 ast_str_set(str, maxlen, "%d", c->hangupcause); 03445 s = ast_str_buffer(*str); 03446 } 03447 } 03448 if (s == ¬_found) { /* look for more */ 03449 if (!strcmp(var, "EPOCH")) { 03450 ast_str_set(str, maxlen, "%u", (int) time(NULL)); 03451 s = ast_str_buffer(*str); 03452 } else if (!strcmp(var, "SYSTEMNAME")) { 03453 s = ast_config_AST_SYSTEM_NAME; 03454 } else if (!strcmp(var, "ENTITYID")) { 03455 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03456 s = workspace; 03457 } 03458 } 03459 /* if not found, look into chanvars or global vars */ 03460 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03461 struct ast_var_t *variables; 03462 if (!places[i]) 03463 continue; 03464 if (places[i] == &globals) 03465 ast_rwlock_rdlock(&globalslock); 03466 AST_LIST_TRAVERSE(places[i], variables, entries) { 03467 if (!strcasecmp(ast_var_name(variables), var)) { 03468 s = ast_var_value(variables); 03469 break; 03470 } 03471 } 03472 if (places[i] == &globals) 03473 ast_rwlock_unlock(&globalslock); 03474 } 03475 if (s == ¬_found || s == NULL) { 03476 ast_debug(5, "Result of '%s' is NULL\n", var); 03477 ret = NULL; 03478 } else { 03479 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03480 if (s != ast_str_buffer(*str)) { 03481 ast_str_set(str, maxlen, "%s", s); 03482 } 03483 ret = ast_str_buffer(*str); 03484 if (need_substring) { 03485 ret = ast_str_substring(*str, offset, length); 03486 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03487 } 03488 } 03489 03490 if (c) { 03491 ast_channel_unlock(c); 03492 } 03493 return ret; 03494 }
void ast_str_substitute_variables | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct ast_channel * | chan, | |||
const char * | templ | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
chan | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
templ | Variable template to expand. |
Definition at line 4168 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), config_curl(), custom_log(), cut_internal(), destroy_curl(), exec_exec(), func_mchan_read(), function_eval2(), function_fieldnum_helper(), function_fieldqty_helper(), handle_getvariablefull(), import_helper(), listfilter(), make_email_file(), realtime_curl(), realtime_multi_curl(), replace(), require_curl(), sendmail(), sendpage(), shift_pop(), store_curl(), syslog_log(), tryexec_exec(), unshift_push(), update2_curl(), and update_curl().
04169 { 04170 size_t used; 04171 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 04172 }
void ast_str_substitute_variables_full | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct ast_channel * | c, | |||
struct varshead * | headp, | |||
const char * | templ, | |||
size_t * | used | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
c | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
headp | If no channel is specified, a channel list from which to extract variable values | |
templ | Variable template to expand. | |
used | Number of bytes read from the template. |
Definition at line 3989 of file pbx.c.
References ast_channel_unref, ast_debug, ast_dummy_channel_alloc, ast_free, ast_func_read2(), ast_log(), ast_str_append(), ast_str_append_substr(), ast_str_buffer(), ast_str_create(), ast_str_expr(), ast_str_reset(), ast_str_retrieve_variable(), ast_str_set_substr(), ast_str_strlen(), ast_str_substitute_variables_full(), ast_str_substring(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), and ast_channel::varshead.
Referenced by ast_str_substitute_variables(), ast_str_substitute_variables_full(), and ast_str_substitute_variables_varshead().
03990 { 03991 /* Substitutes variables into buf, based on string templ */ 03992 char *cp4 = NULL; 03993 const char *tmp, *whereweare; 03994 int orig_size = 0; 03995 int offset, offset2, isfunction; 03996 const char *nextvar, *nextexp, *nextthing; 03997 const char *vars, *vare; 03998 char *finalvars; 03999 int pos, brackets, needsub, len; 04000 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 04001 04002 ast_str_reset(*buf); 04003 whereweare = tmp = templ; 04004 while (!ast_strlen_zero(whereweare)) { 04005 /* reset our buffer */ 04006 ast_str_reset(substr3); 04007 04008 /* Assume we're copying the whole remaining string */ 04009 pos = strlen(whereweare); 04010 nextvar = NULL; 04011 nextexp = NULL; 04012 nextthing = strchr(whereweare, '$'); 04013 if (nextthing) { 04014 switch (nextthing[1]) { 04015 case '{': 04016 nextvar = nextthing; 04017 pos = nextvar - whereweare; 04018 break; 04019 case '[': 04020 nextexp = nextthing; 04021 pos = nextexp - whereweare; 04022 break; 04023 default: 04024 pos = 1; 04025 } 04026 } 04027 04028 if (pos) { 04029 /* Copy that many bytes */ 04030 ast_str_append_substr(buf, maxlen, whereweare, pos); 04031 04032 templ += pos; 04033 whereweare += pos; 04034 } 04035 04036 if (nextvar) { 04037 /* We have a variable. Find the start and end, and determine 04038 if we are going to have to recursively call ourselves on the 04039 contents */ 04040 vars = vare = nextvar + 2; 04041 brackets = 1; 04042 needsub = 0; 04043 04044 /* Find the end of it */ 04045 while (brackets && *vare) { 04046 if ((vare[0] == '$') && (vare[1] == '{')) { 04047 needsub++; 04048 } else if (vare[0] == '{') { 04049 brackets++; 04050 } else if (vare[0] == '}') { 04051 brackets--; 04052 } else if ((vare[0] == '$') && (vare[1] == '[')) 04053 needsub++; 04054 vare++; 04055 } 04056 if (brackets) 04057 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04058 len = vare - vars - 1; 04059 04060 /* Skip totally over variable string */ 04061 whereweare += (len + 3); 04062 04063 /* Store variable name (and truncate) */ 04064 ast_str_set_substr(&substr1, 0, vars, len); 04065 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 04066 04067 /* Substitute if necessary */ 04068 if (needsub) { 04069 size_t used; 04070 if (!substr2) { 04071 substr2 = ast_str_create(16); 04072 } 04073 04074 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04075 finalvars = ast_str_buffer(substr2); 04076 } else { 04077 finalvars = ast_str_buffer(substr1); 04078 } 04079 04080 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 04081 if (isfunction) { 04082 /* Evaluate function */ 04083 if (c || !headp) { 04084 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04085 } else { 04086 struct varshead old; 04087 struct ast_channel *bogus = ast_dummy_channel_alloc(); 04088 if (bogus) { 04089 memcpy(&old, &bogus->varshead, sizeof(old)); 04090 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 04091 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04092 /* Don't deallocate the varshead that was passed in */ 04093 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 04094 ast_channel_unref(bogus); 04095 } else { 04096 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04097 } 04098 } 04099 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 04100 } else { 04101 /* Retrieve variable value */ 04102 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 04103 cp4 = ast_str_buffer(substr3); 04104 } 04105 if (cp4) { 04106 ast_str_substring(substr3, offset, offset2); 04107 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04108 } 04109 } else if (nextexp) { 04110 /* We have an expression. Find the start and end, and determine 04111 if we are going to have to recursively call ourselves on the 04112 contents */ 04113 vars = vare = nextexp + 2; 04114 brackets = 1; 04115 needsub = 0; 04116 04117 /* Find the end of it */ 04118 while (brackets && *vare) { 04119 if ((vare[0] == '$') && (vare[1] == '[')) { 04120 needsub++; 04121 brackets++; 04122 vare++; 04123 } else if (vare[0] == '[') { 04124 brackets++; 04125 } else if (vare[0] == ']') { 04126 brackets--; 04127 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04128 needsub++; 04129 vare++; 04130 } 04131 vare++; 04132 } 04133 if (brackets) 04134 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04135 len = vare - vars - 1; 04136 04137 /* Skip totally over expression */ 04138 whereweare += (len + 3); 04139 04140 /* Store variable name (and truncate) */ 04141 ast_str_set_substr(&substr1, 0, vars, len); 04142 04143 /* Substitute if necessary */ 04144 if (needsub) { 04145 size_t used; 04146 if (!substr2) { 04147 substr2 = ast_str_create(16); 04148 } 04149 04150 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04151 finalvars = ast_str_buffer(substr2); 04152 } else { 04153 finalvars = ast_str_buffer(substr1); 04154 } 04155 04156 if (ast_str_expr(&substr3, 0, c, finalvars)) { 04157 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 04158 } 04159 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04160 } 04161 } 04162 *used = ast_str_strlen(*buf) - orig_size; 04163 ast_free(substr1); 04164 ast_free(substr2); 04165 ast_free(substr3); 04166 }
void ast_str_substitute_variables_varshead | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct varshead * | headp, | |||
const char * | templ | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
headp | If no channel is specified, a channel list from which to extract variable values | |
templ | Variable template to expand. |
Definition at line 4174 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by add_user_extension(), build_user_routes(), phoneprov_callback(), pp_each_extension_helper(), and pp_each_user_helper().
04175 { 04176 size_t used; 04177 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 04178 }
static const char* ast_str_substring | ( | struct ast_str * | value, | |
int | offset, | |||
int | length | |||
) | [static] |
Definition at line 3305 of file pbx.c.
References ast_str_buffer(), ast_str_reset(), ast_str_strlen(), and ast_str_update().
Referenced by ast_str_retrieve_variable(), and ast_str_substitute_variables_full().
03306 { 03307 int lr; /* length of the input string after the copy */ 03308 03309 lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */ 03310 03311 /* Quick check if no need to do anything */ 03312 if (offset == 0 && length >= lr) /* take the whole string */ 03313 return ast_str_buffer(value); 03314 03315 if (offset < 0) { /* translate negative offset into positive ones */ 03316 offset = lr + offset; 03317 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 03318 offset = 0; 03319 } 03320 03321 /* too large offset result in empty string so we know what to return */ 03322 if (offset >= lr) { 03323 ast_str_reset(value); 03324 return ast_str_buffer(value); 03325 } 03326 03327 if (offset > 0) { 03328 /* Go ahead and chop off the beginning */ 03329 memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1); 03330 lr -= offset; 03331 } 03332 03333 if (length >= 0 && length < lr) { /* truncate if necessary */ 03334 char *tmp = ast_str_buffer(value); 03335 tmp[length] = '\0'; 03336 ast_str_update(value); 03337 } else if (length < 0) { 03338 if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */ 03339 char *tmp = ast_str_buffer(value); 03340 tmp[lr + length] = '\0'; 03341 ast_str_update(value); 03342 } else { 03343 ast_str_reset(value); 03344 } 03345 } else { 03346 /* Nothing to do, but update the buffer length */ 03347 ast_str_update(value); 03348 } 03349 03350 return ast_str_buffer(value); 03351 }
int ast_unlock_context | ( | struct ast_context * | con | ) |
Unlocks | the given context |
con | context to unlock |
0 | on success | |
-1 | on failure |
Definition at line 10645 of file pbx.c.
References ast_rwlock_unlock, and ast_context::lock.
Referenced by __ast_context_destroy(), _macro_exec(), ast_add_extension2_lockopt(), ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_extension_callerid2(), ast_context_remove_ignorepat2(), ast_context_remove_include2(), ast_context_remove_switch2(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_cli_dialplan_save(), lookup_c_ip(), lookup_ci(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
10646 { 10647 return ast_rwlock_unlock(&con->lock); 10648 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 10627 of file pbx.c.
References ast_mutex_unlock, and conlock.
Referenced by _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
10628 { 10629 return ast_mutex_unlock(&conlock); 10630 }
int ast_unregister_application | ( | const char * | app | ) |
Unregister an application.
app | name of the application (does not have to be the same string as the one that was registered) |
This unregisters an application from Asterisk's internal application list.
0 | success | |
-1 | failure |
Definition at line 7393 of file pbx.c.
References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, ast_app::name, and unreference_cached_app().
Referenced by __unload_module(), cc_shutdown(), features_shutdown(), load_module(), unload_module(), and unload_pbx().
07394 { 07395 struct ast_app *tmp; 07396 07397 AST_RWLIST_WRLOCK(&apps); 07398 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 07399 if (!strcasecmp(app, tmp->name)) { 07400 unreference_cached_app(tmp); 07401 AST_RWLIST_REMOVE_CURRENT(list); 07402 ast_verb(2, "Unregistered application '%s'\n", tmp->name); 07403 ast_string_field_free_memory(tmp); 07404 ast_free(tmp); 07405 break; 07406 } 07407 } 07408 AST_RWLIST_TRAVERSE_SAFE_END; 07409 AST_RWLIST_UNLOCK(&apps); 07410 07411 return tmp ? 0 : -1; 07412 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Unregisters a switch from asterisk.
Definition at line 6160 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
06161 { 06162 AST_RWLIST_WRLOCK(&switches); 06163 AST_RWLIST_REMOVE(&switches, sw, list); 06164 AST_RWLIST_UNLOCK(&switches); 06165 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) | [read] |
Definition at line 10759 of file pbx.c.
References ast_exten::next, and ast_context::root.
Referenced by complete_dialplan_remove_extension(), context_used(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) | [read] |
Definition at line 10792 of file pbx.c.
References ast_context::ignorepats, and ast_ignorepat::next.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), context_used(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
10794 { 10795 if (!ip) 10796 return con ? con->ignorepats : NULL; 10797 else 10798 return ip->next; 10799 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) | [read] |
Definition at line 10783 of file pbx.c.
References ast_context::includes, and ast_include::next.
Referenced by ast_context_verify_includes(), complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), context_used(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) | [read] |
Definition at line 10768 of file pbx.c.
References ast_context::alts, AST_LIST_FIRST, and AST_LIST_NEXT.
Referenced by context_merge_incls_swits_igps_other_registrars(), context_used(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10770 { 10771 if (!sw) 10772 return con ? AST_LIST_FIRST(&con->alts) : NULL; 10773 else 10774 return AST_LIST_NEXT(sw, list); 10775 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 10754 of file pbx.c.
References contexts, and ast_context::next.
Referenced by _macro_exec(), ast_context_find(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_load_module(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
struct ast_exten* ast_walk_extension_priorities | ( | struct ast_exten * | exten, | |
struct ast_exten * | priority | |||
) | [read] |
Definition at line 10777 of file pbx.c.
References ast_exten::peer.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), show_dialplan_helper(), and unreference_cached_app().
10779 { 10780 return priority ? priority->peer : exten; 10781 }
int ast_wrlock_context | ( | struct ast_context * | con | ) |
Write locks a given context.
con | context to lock |
0 | on success | |
-1 | on failure |
Definition at line 10635 of file pbx.c.
References ast_rwlock_wrlock, and ast_context::lock.
Referenced by __ast_context_destroy(), ast_add_extension2_lockopt(), ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_extension_callerid2(), ast_context_remove_ignorepat2(), ast_context_remove_include2(), and ast_context_remove_switch2().
10636 { 10637 return ast_rwlock_wrlock(&con->lock); 10638 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10617 of file pbx.c.
References ast_mutex_lock, and conlock.
Referenced by ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and complete_dialplan_remove_include().
10618 { 10619 return ast_mutex_lock(&conlock); 10620 }
static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 8958 of file pbx.c.
References ast_channel::_state, async_stat::app, async_stat::appdata, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, ast_copy_string(), AST_FRAME_CONTROL, ast_free, ast_frfree, ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), ast_remaining_ms(), AST_STATE_UP, ast_strlen_zero(), ast_tvnow(), ast_verb, ast_waitfor(), async_stat::chan, ast_channel::context, async_stat::context, ast_channel::exten, async_stat::exten, f, ast_frame::frametype, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, pbx_exec(), pbx_findapp(), ast_channel::priority, async_stat::priority, ast_frame::subclass, and async_stat::timeout.
Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
08959 { 08960 struct async_stat *as = data; 08961 struct ast_channel *chan = as->chan; 08962 int timeout = as->timeout; 08963 int res; 08964 struct ast_frame *f; 08965 struct ast_app *app; 08966 struct timeval start = ast_tvnow(); 08967 int ms; 08968 08969 while ((ms = ast_remaining_ms(start, timeout)) && 08970 chan->_state != AST_STATE_UP) { 08971 res = ast_waitfor(chan, ms); 08972 if (res < 1) 08973 break; 08974 08975 f = ast_read(chan); 08976 if (!f) 08977 break; 08978 if (f->frametype == AST_FRAME_CONTROL) { 08979 if ((f->subclass.integer == AST_CONTROL_BUSY) || 08980 (f->subclass.integer == AST_CONTROL_CONGESTION) ) { 08981 ast_frfree(f); 08982 break; 08983 } 08984 } 08985 ast_frfree(f); 08986 } 08987 if (chan->_state == AST_STATE_UP) { 08988 if (!ast_strlen_zero(as->app)) { 08989 app = pbx_findapp(as->app); 08990 if (app) { 08991 ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 08992 pbx_exec(chan, app, as->appdata); 08993 } else 08994 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 08995 } else { 08996 if (!ast_strlen_zero(as->context)) 08997 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 08998 if (!ast_strlen_zero(as->exten)) 08999 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 09000 if (as->priority > 0) 09001 chan->priority = as->priority; 09002 /* Run the PBX */ 09003 if (ast_pbx_run(chan)) { 09004 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 09005 } else { 09006 /* PBX will have taken care of this */ 09007 chan = NULL; 09008 } 09009 } 09010 } 09011 ast_free(as); 09012 if (chan) 09013 ast_hangup(chan); 09014 return NULL; 09015 }
static void cli_match_char_tree | ( | struct match_char * | node, | |
char * | prefix, | |||
int | fd | |||
) | [static] |
Definition at line 1624 of file pbx.c.
References match_char::alt_char, ast_cli(), ast_str_alloca, ast_str_buffer(), ast_str_set(), match_char::deleted, ast_exten::exten, match_char::exten, match_char::is_pattern, match_char::next_char, match_char::specificity, and match_char::x.
Referenced by show_debug_helper().
01625 { 01626 char extenstr[40]; 01627 struct ast_str *my_prefix = ast_str_alloca(1024); 01628 01629 extenstr[0] = '\0'; 01630 01631 if (node->exten) { 01632 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01633 } 01634 01635 if (strlen(node->x) > 1) { 01636 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01637 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01638 node->exten ? node->exten->exten : "", extenstr); 01639 } else { 01640 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01641 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01642 node->exten ? node->exten->exten : "", extenstr); 01643 } 01644 01645 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01646 01647 if (node->next_char) 01648 cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd); 01649 01650 if (node->alt_char) 01651 cli_match_char_tree(node->alt_char, prefix, fd); 01652 }
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.
c,buf,buflen,pos | ||
waittime | is in milliseconds |
0 | on timeout or done. | |
-1 | on error. |
Definition at line 5146 of file pbx.c.
References ast_channel::_softhangup, ast_channel_clear_softhangup(), ast_matchmore_extension(), AST_SOFTHANGUP_ASYNCGOTO, ast_waitfordigit(), ast_channel::caller, ast_channel::context, ast_pbx::dtimeoutms, ast_party_caller::id, ast_party_id::number, ast_channel::pbx, S_COR, ast_party_number::str, and ast_party_number::valid.
Referenced by __ast_pbx_run().
05147 { 05148 int digit; 05149 05150 buf[pos] = '\0'; /* make sure it is properly terminated */ 05151 while (ast_matchmore_extension(c, c->context, buf, 1, 05152 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05153 /* As long as we're willing to wait, and as long as it's not defined, 05154 keep reading digits until we can't possibly get a right answer anymore. */ 05155 digit = ast_waitfordigit(c, waittime); 05156 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05157 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05158 } else { 05159 if (!digit) /* No entry */ 05160 break; 05161 if (digit < 0) /* Error, maybe a hangup */ 05162 return -1; 05163 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 05164 buf[pos++] = digit; 05165 buf[pos] = '\0'; 05166 } 05167 waittime = c->pbx->dtimeoutms; 05168 } 05169 } 05170 return 0; 05171 }
static int compare_char | ( | const void * | a, | |
const void * | b | |||
) | [static] |
Definition at line 1072 of file pbx.c.
Referenced by get_pattern_node().
static char* complete_core_show_hint | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
autocomplete for CLI command 'core show hint'
Definition at line 6347 of file pbx.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_get_extension_name(), ast_strdup, ast_hint::exten, and hints.
Referenced by handle_show_hint().
06348 { 06349 struct ast_hint *hint; 06350 char *ret = NULL; 06351 int which = 0; 06352 int wordlen; 06353 struct ao2_iterator i; 06354 06355 if (pos != 3) 06356 return NULL; 06357 06358 wordlen = strlen(word); 06359 06360 /* walk through all hints */ 06361 i = ao2_iterator_init(hints, 0); 06362 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06363 ao2_lock(hint); 06364 if (!hint->exten) { 06365 /* The extension has already been destroyed */ 06366 ao2_unlock(hint); 06367 continue; 06368 } 06369 if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) { 06370 ret = ast_strdup(ast_get_extension_name(hint->exten)); 06371 ao2_unlock(hint); 06372 ao2_ref(hint, -1); 06373 break; 06374 } 06375 ao2_unlock(hint); 06376 } 06377 ao2_iterator_destroy(&i); 06378 06379 return ret; 06380 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 6557 of file pbx.c.
References ast_get_context_name(), ast_rdlock_contexts(), ast_strdup, ast_unlock_contexts(), and ast_walk_contexts().
Referenced by handle_debug_dialplan(), and handle_show_dialplan().
06559 { 06560 struct ast_context *c = NULL; 06561 char *ret = NULL; 06562 int which = 0; 06563 int wordlen; 06564 06565 /* we are do completion of [exten@]context on second position only */ 06566 if (pos != 2) 06567 return NULL; 06568 06569 ast_rdlock_contexts(); 06570 06571 wordlen = strlen(word); 06572 06573 /* walk through all contexts and return the n-th match */ 06574 while ( (c = ast_walk_contexts(c)) ) { 06575 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 06576 ret = ast_strdup(ast_get_context_name(c)); 06577 break; 06578 } 06579 } 06580 06581 ast_unlock_contexts(); 06582 06583 return ret; 06584 }
static void context_merge | ( | struct ast_context ** | extcontexts, | |
struct ast_hashtab * | exttable, | |||
struct ast_context * | context, | |||
const char * | registrar | |||
) | [static] |
Definition at line 7534 of file pbx.c.
References ast_exten::app, ast_add_extension2(), ast_context_find_or_create(), 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, ast_exten::datad, ast_exten::exten, first, ast_exten::label, LOG_ERROR, ast_exten::matchcid, ast_context::name, ast_exten::peer_table, ast_exten::priority, ast_context::refcount, ast_context::registrar, ast_exten::registrar, and ast_context::root_table.
Referenced by ast_merge_contexts_and_delete().
07535 { 07536 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */ 07537 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item; 07538 struct ast_hashtab_iter *exten_iter; 07539 struct ast_hashtab_iter *prio_iter; 07540 int insert_count = 0; 07541 int first = 1; 07542 07543 /* We'll traverse all the extensions/prios, and see which are not registrar'd with 07544 the current registrar, and copy them to the new context. If the new context does not 07545 exist, we'll create it "on demand". If no items are in this context to copy, then we'll 07546 only create the empty matching context if the old one meets the criteria */ 07547 07548 if (context->root_table) { 07549 exten_iter = ast_hashtab_start_traversal(context->root_table); 07550 while ((exten_item=ast_hashtab_next(exten_iter))) { 07551 if (new) { 07552 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item); 07553 } else { 07554 new_exten_item = NULL; 07555 } 07556 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 07557 while ((prio_item=ast_hashtab_next(prio_iter))) { 07558 int res1; 07559 char *dupdstr; 07560 07561 if (new_exten_item) { 07562 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item); 07563 } else { 07564 new_prio_item = NULL; 07565 } 07566 if (strcmp(prio_item->registrar,registrar) == 0) { 07567 continue; 07568 } 07569 /* make sure the new context exists, so we have somewhere to stick this exten/prio */ 07570 if (!new) { 07571 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 */ 07572 } 07573 07574 /* copy in the includes, switches, and ignorepats */ 07575 if (first) { /* but, only need to do this once */ 07576 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07577 first = 0; 07578 } 07579 07580 if (!new) { 07581 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name); 07582 ast_hashtab_end_traversal(prio_iter); 07583 ast_hashtab_end_traversal(exten_iter); 07584 return; /* no sense continuing. */ 07585 } 07586 /* we will not replace existing entries in the new context with stuff from the old context. 07587 but, if this is because of some sort of registrar conflict, we ought to say something... */ 07588 07589 dupdstr = ast_strdup(prio_item->data); 07590 07591 res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 07592 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar); 07593 if (!res1 && new_exten_item && new_prio_item){ 07594 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n", 07595 context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar); 07596 } else { 07597 /* 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, 07598 and no double frees take place, either! */ 07599 insert_count++; 07600 } 07601 } 07602 ast_hashtab_end_traversal(prio_iter); 07603 } 07604 ast_hashtab_end_traversal(exten_iter); 07605 } 07606 07607 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 || 07608 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) { 07609 /* we could have given it the registrar of the other module who incremented the refcount, 07610 but that's not available, so we give it the registrar we know about */ 07611 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar); 07612 07613 /* copy in the includes, switches, and ignorepats */ 07614 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07615 } 07616 }
static void context_merge_incls_swits_igps_other_registrars | ( | struct ast_context * | new, | |
struct ast_context * | old, | |||
const char * | registrar | |||
) | [static] |
Definition at line 7501 of file pbx.c.
References ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), 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(), ast_verb, ast_walk_context_ignorepats(), ast_walk_context_includes(), and ast_walk_context_switches().
Referenced by context_merge().
07502 { 07503 struct ast_include *i; 07504 struct ast_ignorepat *ip; 07505 struct ast_sw *sw; 07506 07507 ast_verb(3, "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); 07508 /* copy in the includes, switches, and ignorepats */ 07509 /* walk through includes */ 07510 for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) { 07511 if (strcmp(ast_get_include_registrar(i), registrar) == 0) 07512 continue; /* not mine */ 07513 ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i)); 07514 } 07515 07516 /* walk through switches */ 07517 for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) { 07518 if (strcmp(ast_get_switch_registrar(sw), registrar) == 0) 07519 continue; /* not mine */ 07520 ast_context_add_switch2(new, ast_get_switch_name(sw), ast_get_switch_data(sw), ast_get_switch_eval(sw), ast_get_switch_registrar(sw)); 07521 } 07522 07523 /* walk thru ignorepats ... */ 07524 for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) { 07525 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) 07526 continue; /* not mine */ 07527 ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip)); 07528 } 07529 }
static void create_match_char_tree | ( | struct ast_context * | con | ) | [static] |
Definition at line 2246 of file pbx.c.
References add_exten_to_pattern_tree(), ast_hashtab_end_traversal(), ast_hashtab_get_stats(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_log(), ast_exten::exten, LOG_DEBUG, LOG_ERROR, ast_context::name, and ast_context::root_table.
Referenced by pbx_find_extension().
02247 { 02248 struct ast_hashtab_iter *t1; 02249 struct ast_exten *e1; 02250 #ifdef NEED_DEBUG 02251 int biggest_bucket, resizes, numobjs, numbucks; 02252 02253 ast_log(LOG_DEBUG,"Creating Extension Trie for context %s(%p)\n", con->name, con); 02254 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks); 02255 ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n", 02256 numobjs, numbucks, biggest_bucket, resizes); 02257 #endif 02258 t1 = ast_hashtab_start_traversal(con->root_table); 02259 while ((e1 = ast_hashtab_next(t1))) { 02260 if (e1->exten) { 02261 add_exten_to_pattern_tree(con, e1, 0); 02262 } else { 02263 ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n"); 02264 } 02265 } 02266 ast_hashtab_end_traversal(t1); 02267 }
static void decrease_call_count | ( | void | ) | [static] |
Definition at line 5537 of file pbx.c.
References ast_mutex_lock, ast_mutex_unlock, countcalls, and maxcalllock.
Referenced by ast_pbx_run_args(), ast_pbx_start(), and pbx_thread().
05538 { 05539 ast_mutex_lock(&maxcalllock); 05540 if (countcalls > 0) 05541 countcalls--; 05542 ast_mutex_unlock(&maxcalllock); 05543 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 5545 of file pbx.c.
References ast_free, ast_hashtab_destroy(), ast_remove_hint(), ast_exten::data, ast_exten::datad, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, and PRIORITY_HINT.
Referenced by __ast_internal_context_destroy(), and ast_context_remove_extension_callerid2().
05546 { 05547 if (e->priority == PRIORITY_HINT) 05548 ast_remove_hint(e); 05549 05550 if (e->peer_table) 05551 ast_hashtab_destroy(e->peer_table,0); 05552 if (e->peer_label_table) 05553 ast_hashtab_destroy(e->peer_label_table, 0); 05554 if (e->datad) 05555 e->datad(e->data); 05556 ast_free(e); 05557 }
static void destroy_hint | ( | void * | obj | ) | [static] |
Definition at line 4911 of file pbx.c.
References ao2_callback, ao2_ref, AST_EXTENSION_DEACTIVATED, ast_get_context_name(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, ast_state_cb::change_cb, ast_hint::context_name, ast_state_cb::data, ast_hint::exten, ast_hint::exten_name, and OBJ_UNLINK.
Referenced by ast_add_hint().
04912 { 04913 struct ast_hint *hint = obj; 04914 04915 if (hint->callbacks) { 04916 struct ast_state_cb *state_cb; 04917 const char *context_name; 04918 const char *exten_name; 04919 04920 if (hint->exten) { 04921 context_name = ast_get_context_name(ast_get_extension_context(hint->exten)); 04922 exten_name = ast_get_extension_name(hint->exten); 04923 hint->exten = NULL; 04924 } else { 04925 /* The extension has already been destroyed */ 04926 context_name = hint->context_name; 04927 exten_name = hint->exten_name; 04928 } 04929 while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 04930 /* Notify with -1 and remove all callbacks */ 04931 /* NOTE: The casts will not be needed for v1.10 and later */ 04932 state_cb->change_cb((char *) context_name, (char *) exten_name, 04933 AST_EXTENSION_DEACTIVATED, state_cb->data); 04934 ao2_ref(state_cb, -1); 04935 } 04936 ao2_ref(hint->callbacks, -1); 04937 } 04938 }
static void destroy_pattern_tree | ( | struct match_char * | pattern_tree | ) | [static] |
Definition at line 2269 of file pbx.c.
References match_char::alt_char, ast_free, match_char::exten, and match_char::next_char.
Referenced by __ast_internal_context_destroy().
02270 { 02271 /* destroy all the alternates */ 02272 if (pattern_tree->alt_char) { 02273 destroy_pattern_tree(pattern_tree->alt_char); 02274 pattern_tree->alt_char = 0; 02275 } 02276 /* destroy all the nexts */ 02277 if (pattern_tree->next_char) { 02278 destroy_pattern_tree(pattern_tree->next_char); 02279 pattern_tree->next_char = 0; 02280 } 02281 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */ 02282 ast_free(pattern_tree); 02283 }
static void destroy_state_cb | ( | void * | doomed | ) | [static] |
Definition at line 4742 of file pbx.c.
References ast_state_cb::data, ast_state_cb::destroy_cb, and ast_state_cb::id.
Referenced by ast_extension_state_add_destroy().
04743 { 04744 struct ast_state_cb *state_cb = doomed; 04745 04746 if (state_cb->destroy_cb) { 04747 state_cb->destroy_cb(state_cb->id, state_cb->data); 04748 } 04749 }
static void device_state_cb | ( | const struct ast_event * | event, | |
void * | unused | |||
) | [static] |
Definition at line 10485 of file pbx.c.
References ast_calloc, ast_event_get_ie_str(), AST_EVENT_IE_DEVICE, ast_free, ast_log(), ast_strlen_zero(), ast_taskprocessor_push(), statechange::dev, handle_statechange(), and LOG_ERROR.
Referenced by load_pbx().
10486 { 10487 const char *device; 10488 struct statechange *sc; 10489 10490 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 10491 if (ast_strlen_zero(device)) { 10492 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n"); 10493 return; 10494 } 10495 10496 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1))) 10497 return; 10498 strcpy(sc->dev, device); 10499 if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) { 10500 ast_free(sc); 10501 } 10502 }
static void exception_store_free | ( | void * | data | ) | [static] |
Definition at line 3496 of file pbx.c.
References ast_free, and ast_string_field_free_memory.
03497 { 03498 struct pbx_exception *exception = data; 03499 ast_string_field_free_memory(exception); 03500 ast_free(exception); 03501 }
static int ext_cmp | ( | const char * | left, | |
const char * | right | |||
) | [static] |
Definition at line 2616 of file pbx.c.
References ext_cmp_exten(), and ext_cmp_pattern().
Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().
02617 { 02618 /* Make sure non-pattern extens come first. */ 02619 if (left[0] != '_') { 02620 if (right[0] == '_') { 02621 return -1; 02622 } 02623 /* Compare two non-pattern extens. */ 02624 return ext_cmp_exten(left, right); 02625 } 02626 if (right[0] != '_') { 02627 return 1; 02628 } 02629 02630 /* 02631 * OK, we need full pattern sorting routine. 02632 * 02633 * Skip past the underscores 02634 */ 02635 return ext_cmp_pattern(left + 1, right + 1); 02636 }
static int ext_cmp_exten | ( | const char * | left, | |
const char * | right | |||
) | [static] |
Definition at line 2366 of file pbx.c.
Referenced by _extension_match_core(), and ext_cmp().
02367 { 02368 int cmp; 02369 02370 for (;;) { 02371 /* Ignore '-' chars as eye candy fluff. */ 02372 while (*left == '-') { 02373 ++left; 02374 } 02375 while (*right == '-') { 02376 ++right; 02377 } 02378 02379 cmp = *left - *right; 02380 if (cmp) { 02381 break; 02382 } 02383 if (!*left) { 02384 /* 02385 * Get here only if both strings ended at the same time. cmp 02386 * would be non-zero if only one string ended. 02387 */ 02388 break; 02389 } 02390 ++left; 02391 ++right; 02392 } 02393 return cmp; 02394 }
static int ext_cmp_exten_partial | ( | const char * | left, | |
const char * | right | |||
) | [static] |
Definition at line 2323 of file pbx.c.
Referenced by _extension_match_core().
02324 { 02325 int cmp; 02326 02327 for (;;) { 02328 /* Ignore '-' chars as eye candy fluff. */ 02329 while (*left == '-') { 02330 ++left; 02331 } 02332 while (*right == '-') { 02333 ++right; 02334 } 02335 02336 if (!*right) { 02337 /* 02338 * Right ended first for partial match or both ended at the same 02339 * time for a match. 02340 */ 02341 cmp = 0; 02342 break; 02343 } 02344 02345 cmp = *left - *right; 02346 if (cmp) { 02347 break; 02348 } 02349 ++left; 02350 ++right; 02351 } 02352 return cmp; 02353 }
static int ext_cmp_exten_strlen | ( | const char * | str | ) | [static] |
static int ext_cmp_pattern | ( | const char * | left, | |
const char * | right | |||
) | [static] |
Definition at line 2568 of file pbx.c.
References ARRAY_LEN, and ext_cmp_pattern_pos().
Referenced by _extension_match_core(), and ext_cmp().
02569 { 02570 int cmp; 02571 int left_pos; 02572 int right_pos; 02573 02574 for (;;) { 02575 unsigned char left_bitwise[32] = { 0, }; 02576 unsigned char right_bitwise[32] = { 0, }; 02577 02578 left_pos = ext_cmp_pattern_pos(&left, left_bitwise); 02579 right_pos = ext_cmp_pattern_pos(&right, right_bitwise); 02580 cmp = left_pos - right_pos; 02581 if (!cmp) { 02582 /* 02583 * Are the character sets different, even though they score the same? 02584 * 02585 * Note: Must swap left and right to get the sense of the 02586 * comparison correct. Otherwise, we would need to multiply by 02587 * -1 instead. 02588 */ 02589 cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise)); 02590 } 02591 if (cmp) { 02592 break; 02593 } 02594 if (!left) { 02595 /* 02596 * Get here only if both patterns ended at the same time. cmp 02597 * would be non-zero if only one pattern ended. 02598 */ 02599 break; 02600 } 02601 } 02602 return cmp; 02603 }
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 2453 of file pbx.c.
References ast_log(), BITS_PER, and LOG_WARNING.
Referenced by ext_cmp_pattern().
02454 { 02455 #define BITS_PER 8 /* Number of bits per unit (byte). */ 02456 unsigned char c; 02457 unsigned char cmin; 02458 int count; 02459 const char *end; 02460 02461 do { 02462 /* Get character and advance. (Ignore '-' chars as eye candy fluff.) */ 02463 do { 02464 c = *(*p)++; 02465 } while (c == '-'); 02466 02467 /* always return unless we have a set of chars */ 02468 switch (c) { 02469 default: 02470 /* ordinary character */ 02471 bitwise[c / BITS_PER] = 1 << ((BITS_PER - 1) - (c % BITS_PER)); 02472 return 0x0100 | c; 02473 02474 case 'n': 02475 case 'N': 02476 /* 2..9 */ 02477 bitwise[6] = 0x3f; 02478 bitwise[7] = 0xc0; 02479 return 0x0800 | '2'; 02480 02481 case 'x': 02482 case 'X': 02483 /* 0..9 */ 02484 bitwise[6] = 0xff; 02485 bitwise[7] = 0xc0; 02486 return 0x0A00 | '0'; 02487 02488 case 'z': 02489 case 'Z': 02490 /* 1..9 */ 02491 bitwise[6] = 0x7f; 02492 bitwise[7] = 0xc0; 02493 return 0x0900 | '1'; 02494 02495 case '.': 02496 /* wildcard */ 02497 return 0x18000; 02498 02499 case '!': 02500 /* earlymatch */ 02501 return 0x28000; /* less specific than '.' */ 02502 02503 case '\0': 02504 /* empty string */ 02505 *p = NULL; 02506 return 0x30000; 02507 02508 case '[': 02509 /* char set */ 02510 break; 02511 } 02512 /* locate end of set */ 02513 end = strchr(*p, ']'); 02514 02515 if (!end) { 02516 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02517 return 0x40000; /* XXX make this entry go last... */ 02518 } 02519 02520 count = 0; 02521 cmin = 0xFF; 02522 for (; *p < end; ++*p) { 02523 unsigned char c1; /* first char in range */ 02524 unsigned char c2; /* last char in range */ 02525 02526 c1 = (*p)[0]; 02527 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 02528 c2 = (*p)[2]; 02529 *p += 2; /* skip a total of 3 chars */ 02530 } else { /* individual character */ 02531 c2 = c1; 02532 } 02533 if (c1 < cmin) { 02534 cmin = c1; 02535 } 02536 for (; c1 <= c2; ++c1) { 02537 unsigned char mask = 1 << ((BITS_PER - 1) - (c1 % BITS_PER)); 02538 02539 /* 02540 * Note: If two character sets score the same, the one with the 02541 * lowest ASCII values will compare as coming first. Must fill 02542 * in most significant bits for lower ASCII values to accomplish 02543 * the desired sort order. 02544 */ 02545 if (!(bitwise[c1 / BITS_PER] & mask)) { 02546 /* Add the character to the set. */ 02547 bitwise[c1 / BITS_PER] |= mask; 02548 count += 0x100; 02549 } 02550 } 02551 } 02552 ++*p; 02553 } while (!count);/* While the char set was empty. */ 02554 return count | cmin; 02555 }
static int ext_strncpy | ( | char * | dst, | |
const char * | src, | |||
int | len | |||
) | [static] |
copy a string skipping whitespace
Definition at line 8500 of file pbx.c.
Referenced by ast_add_extension2_lockopt().
08501 { 08502 int count = 0; 08503 int insquares = 0; 08504 08505 while (*src && (count < len - 1)) { 08506 if (*src == '[') { 08507 insquares = 1; 08508 } else if (*src == ']') { 08509 insquares = 0; 08510 } else if (*src == ' ' && !insquares) { 08511 src++; 08512 continue; 08513 } 08514 *dst = *src; 08515 dst++; 08516 src++; 08517 count++; 08518 } 08519 *dst = '\0'; 08520 08521 return count; 08522 }
static int extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 2855 of file pbx.c.
References _extension_match_core(), ast_add_profile(), ast_mark(), and ast_strlen_zero().
Referenced by ast_extension_close(), ast_extension_match(), and pbx_find_extension().
02856 { 02857 int i; 02858 static int prof_id = -2; /* marker for 'unallocated' id */ 02859 if (prof_id == -2) { 02860 prof_id = ast_add_profile("ext_match", 0); 02861 } 02862 ast_mark(prof_id, 1); 02863 i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode); 02864 ast_mark(prof_id, 0); 02865 return i; 02866 }
static struct ast_context * find_context | ( | const char * | context | ) | [static, read] |
lookup for a context with a given name,
found | context or NULL if not found. |
Definition at line 5671 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), contexts_table, and fake_context::name.
05672 { 05673 struct fake_context item; 05674 05675 ast_copy_string(item.name, context, sizeof(item.name)); 05676 05677 return ast_hashtab_lookup(contexts_table, &item); 05678 }
static struct ast_context * find_context_locked | ( | const char * | context | ) | [static, read] |
lookup for a context with a given name,
with | conlock held if found. | |
NULL | if not found. |
Definition at line 5685 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), contexts_table, and fake_context::name.
Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), and ast_context_unlockmacro().
05686 { 05687 struct ast_context *c; 05688 struct fake_context item; 05689 05690 ast_copy_string(item.name, context, sizeof(item.name)); 05691 05692 ast_rdlock_contexts(); 05693 c = ast_hashtab_lookup(contexts_table, &item); 05694 if (!c) { 05695 ast_unlock_contexts(); 05696 } 05697 05698 return c; 05699 }
static int find_hint_by_cb_id | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Remove a watcher from the callback list.
Definition at line 4846 of file pbx.c.
References ao2_find, ao2_ref, ast_hint::callbacks, CMP_MATCH, and CMP_STOP.
Referenced by ast_extension_state_del().
static char* func_args | ( | char * | function | ) | [static] |
return a pointer to the arguments of the function, and terminates the function name with '\0'
Definition at line 3865 of file pbx.c.
References args, ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), ast_func_read2(), and ast_func_write().
03866 { 03867 char *args = strchr(function, '('); 03868 03869 if (!args) { 03870 ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function); 03871 } else { 03872 char *p; 03873 *args++ = '\0'; 03874 if ((p = strrchr(args, ')'))) { 03875 *p = '\0'; 03876 } else { 03877 ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args); 03878 } 03879 } 03880 return args; 03881 }
static struct ast_exten * get_canmatch_exten | ( | struct match_char * | node | ) | [static, read] |
Definition at line 1654 of file pbx.c.
References ast_log(), ast_exten::exten, match_char::exten, LOG_NOTICE, match_char::next_char, and match_char::x.
01655 { 01656 /* find the exten at the end of the rope */ 01657 struct match_char *node2 = node; 01658 01659 for (node2 = node; node2; node2 = node2->next_char) { 01660 if (node2->exten) { 01661 #ifdef NEED_DEBUG_HERE 01662 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten); 01663 #endif 01664 return node2->exten; 01665 } 01666 } 01667 #ifdef NEED_DEBUG_HERE 01668 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x); 01669 #endif 01670 return 0; 01671 }
static const char* get_pattern_node | ( | struct pattern_node * | node, | |
const char * | src, | |||
int | pattern, | |||
const char * | extenbuf | |||
) | [static] |
Definition at line 2003 of file pbx.c.
References ast_log(), pattern_node::buf, compare_char(), first, INC_DST_OVERFLOW_CHECK, last, LOG_ERROR, LOG_WARNING, and pattern_node::specif.
Referenced by add_exten_to_pattern_tree().
02004 { 02005 #define INC_DST_OVERFLOW_CHECK \ 02006 do { \ 02007 if (dst - node->buf < sizeof(node->buf) - 1) { \ 02008 ++dst; \ 02009 } else { \ 02010 overflow = 1; \ 02011 } \ 02012 } while (0) 02013 02014 node->specif = 0; 02015 node->buf[0] = '\0'; 02016 while (*src) { 02017 if (*src == '[' && pattern) { 02018 char *dst = node->buf; 02019 const char *src_next; 02020 int length; 02021 int overflow = 0; 02022 02023 /* get past the '[' */ 02024 ++src; 02025 for (;;) { 02026 if (*src == '\\') { 02027 /* Escaped character. */ 02028 ++src; 02029 if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') { 02030 *dst = *src++; 02031 INC_DST_OVERFLOW_CHECK; 02032 } 02033 } else if (*src == '-') { 02034 unsigned char first; 02035 unsigned char last; 02036 02037 src_next = src; 02038 first = *(src_next - 1); 02039 last = *++src_next; 02040 02041 if (last == '\\') { 02042 /* Escaped character. */ 02043 last = *++src_next; 02044 } 02045 02046 /* Possible char range. */ 02047 if (node->buf[0] && last) { 02048 /* Expand the char range. */ 02049 while (++first <= last) { 02050 *dst = first; 02051 INC_DST_OVERFLOW_CHECK; 02052 } 02053 src = src_next + 1; 02054 } else { 02055 /* 02056 * There was no left or right char for the range. 02057 * It is just a '-'. 02058 */ 02059 *dst = *src++; 02060 INC_DST_OVERFLOW_CHECK; 02061 } 02062 } else if (*src == '\0') { 02063 ast_log(LOG_WARNING, 02064 "A matching ']' was not found for '[' in exten pattern '%s'\n", 02065 extenbuf); 02066 break; 02067 } else if (*src == ']') { 02068 ++src; 02069 break; 02070 } else { 02071 *dst = *src++; 02072 INC_DST_OVERFLOW_CHECK; 02073 } 02074 } 02075 /* null terminate the exploded range */ 02076 *dst = '\0'; 02077 02078 if (overflow) { 02079 ast_log(LOG_ERROR, 02080 "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n", 02081 extenbuf); 02082 node->buf[0] = '\0'; 02083 continue; 02084 } 02085 02086 /* Sort the characters in character set. */ 02087 length = strlen(node->buf); 02088 if (!length) { 02089 ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n", 02090 extenbuf); 02091 node->buf[0] = '\0'; 02092 continue; 02093 } 02094 qsort(node->buf, length, 1, compare_char); 02095 02096 /* Remove duplicate characters from character set. */ 02097 dst = node->buf; 02098 src_next = node->buf; 02099 while (*src_next++) { 02100 if (*dst != *src_next) { 02101 *++dst = *src_next; 02102 } 02103 } 02104 02105 length = strlen(node->buf); 02106 length <<= 8; 02107 node->specif = length | (unsigned char) node->buf[0]; 02108 break; 02109 } else if (*src == '-') { 02110 /* Skip dashes in all extensions. */ 02111 ++src; 02112 } else { 02113 if (*src == '\\') { 02114 /* 02115 * XXX The escape character here does not remove any special 02116 * meaning to characters except the '[', '\\', and '-' 02117 * characters since they are special only in this function. 02118 */ 02119 node->buf[0] = *++src; 02120 if (!node->buf[0]) { 02121 break; 02122 } 02123 } else { 02124 node->buf[0] = *src; 02125 if (pattern) { 02126 /* make sure n,x,z patterns are canonicalized to N,X,Z */ 02127 if (node->buf[0] == 'n') { 02128 node->buf[0] = 'N'; 02129 } else if (node->buf[0] == 'x') { 02130 node->buf[0] = 'X'; 02131 } else if (node->buf[0] == 'z') { 02132 node->buf[0] = 'Z'; 02133 } 02134 } 02135 } 02136 node->buf[1] = '\0'; 02137 node->specif = 1; 02138 ++src; 02139 break; 02140 } 02141 } 02142 return src; 02143 02144 #undef INC_DST_OVERFLOW_CHECK 02145 }
static unsigned get_range | ( | char * | src, | |
int | max, | |||
const char *const | names[], | |||
const char * | msg | |||
) | [static] |
helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers.
Definition at line 7855 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and lookup_name().
Referenced by ast_build_timing().
07856 { 07857 int start, end; /* start and ending position */ 07858 unsigned int mask = 0; 07859 char *part; 07860 07861 /* Check for whole range */ 07862 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 07863 return (1 << max) - 1; 07864 } 07865 07866 while ((part = strsep(&src, "&"))) { 07867 /* Get start and ending position */ 07868 char *endpart = strchr(part, '-'); 07869 if (endpart) { 07870 *endpart++ = '\0'; 07871 } 07872 /* Find the start */ 07873 if ((start = lookup_name(part, names, max)) < 0) { 07874 ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part); 07875 continue; 07876 } 07877 if (endpart) { /* find end of range */ 07878 if ((end = lookup_name(endpart, names, max)) < 0) { 07879 ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart); 07880 continue; 07881 } 07882 } else { 07883 end = start; 07884 } 07885 /* Fill the mask. Remember that ranges are cyclic */ 07886 mask |= (1 << end); /* initialize with last element */ 07887 while (start != end) { 07888 mask |= (1 << start); 07889 if (++start >= max) { 07890 start = 0; 07891 } 07892 } 07893 } 07894 return mask; 07895 }
static void get_timerange | ( | struct ast_timing * | i, | |
char * | times | |||
) | [static] |
store a bitmask of valid times, one bit each 1 minute
Definition at line 7898 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
07899 { 07900 char *endpart, *part; 07901 int x; 07902 int st_h, st_m; 07903 int endh, endm; 07904 int minute_start, minute_end; 07905 07906 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 07907 memset(i->minmask, 0, sizeof(i->minmask)); 07908 07909 /* 1-minute per bit */ 07910 /* Star is all times */ 07911 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 07912 /* 48, because each hour takes 2 integers; 30 bits each */ 07913 for (x = 0; x < 48; x++) { 07914 i->minmask[x] = 0x3fffffff; /* 30 bits */ 07915 } 07916 return; 07917 } 07918 /* Otherwise expect a range */ 07919 while ((part = strsep(×, "&"))) { 07920 if (!(endpart = strchr(part, '-'))) { 07921 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 07922 ast_log(LOG_WARNING, "%s isn't a valid time.\n", part); 07923 continue; 07924 } 07925 i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30)); 07926 continue; 07927 } 07928 *endpart++ = '\0'; 07929 /* why skip non digits? Mostly to skip spaces */ 07930 while (*endpart && !isdigit(*endpart)) { 07931 endpart++; 07932 } 07933 if (!*endpart) { 07934 ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part); 07935 continue; 07936 } 07937 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 07938 ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part); 07939 continue; 07940 } 07941 if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) { 07942 ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart); 07943 continue; 07944 } 07945 minute_start = st_h * 60 + st_m; 07946 minute_end = endh * 60 + endm; 07947 /* Go through the time and enable each appropriate bit */ 07948 for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) { 07949 i->minmask[x / 30] |= (1 << (x % 30)); 07950 } 07951 /* Do the last one */ 07952 i->minmask[x / 30] |= (1 << (x % 30)); 07953 } 07954 /* All done */ 07955 return; 07956 }
static char* handle_debug_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Send ack once.
Definition at line 6884 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), dialplan_counters::context_existence, exten, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_debug_helper(), dialplan_counters::total_context, ast_cli_entry::usage, and ast_cli_args::word.
06885 { 06886 char *exten = NULL, *context = NULL; 06887 /* Variables used for different counters */ 06888 struct dialplan_counters counters; 06889 const char *incstack[AST_PBX_MAX_STACK]; 06890 06891 switch (cmd) { 06892 case CLI_INIT: 06893 e->command = "dialplan debug"; 06894 e->usage = 06895 "Usage: dialplan debug [context]\n" 06896 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n"; 06897 return NULL; 06898 case CLI_GENERATE: 06899 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 06900 } 06901 06902 memset(&counters, 0, sizeof(counters)); 06903 06904 if (a->argc != 2 && a->argc != 3) 06905 return CLI_SHOWUSAGE; 06906 06907 /* we obtain [exten@]context? if yes, split them ... */ 06908 /* note: we ignore the exten totally here .... */ 06909 if (a->argc == 3) { 06910 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 06911 context = ast_strdupa(a->argv[2]); 06912 exten = strsep(&context, "@"); 06913 /* change empty strings to NULL */ 06914 if (ast_strlen_zero(exten)) 06915 exten = NULL; 06916 } else { /* no '@' char, only context given */ 06917 context = ast_strdupa(a->argv[2]); 06918 } 06919 if (ast_strlen_zero(context)) 06920 context = NULL; 06921 } 06922 /* else Show complete dial plan, context and exten are NULL */ 06923 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 06924 06925 /* check for input failure and throw some error messages */ 06926 if (context && !counters.context_existence) { 06927 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 06928 return CLI_FAILURE; 06929 } 06930 06931 06932 ast_cli(a->fd,"-= %d %s. =-\n", 06933 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 06934 06935 /* everything ok */ 06936 return CLI_SUCCESS; 06937 }
static char* handle_set_chanvar | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7257 of file pbx.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_get_by_name(), ast_channel_unref, ast_cli(), ast_complete_channels(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, pbx_builtin_setvar_helper(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
07258 { 07259 struct ast_channel *chan; 07260 const char *chan_name, *var_name, *var_value; 07261 07262 switch (cmd) { 07263 case CLI_INIT: 07264 e->command = "dialplan set chanvar"; 07265 e->usage = 07266 "Usage: dialplan set chanvar <channel> <varname> <value>\n" 07267 " Set channel variable <varname> to <value>\n"; 07268 return NULL; 07269 case CLI_GENERATE: 07270 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 07271 } 07272 07273 if (a->argc != e->args + 3) 07274 return CLI_SHOWUSAGE; 07275 07276 chan_name = a->argv[e->args]; 07277 var_name = a->argv[e->args + 1]; 07278 var_value = a->argv[e->args + 2]; 07279 07280 if (!(chan = ast_channel_get_by_name(chan_name))) { 07281 ast_cli(a->fd, "Channel '%s' not found\n", chan_name); 07282 return CLI_FAILURE; 07283 } 07284 07285 pbx_builtin_setvar_helper(chan, var_name, var_value); 07286 07287 chan = ast_channel_unref(chan); 07288 07289 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name); 07290 07291 return CLI_SUCCESS; 07292 }
static char* handle_set_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7294 of file pbx.c.
References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pbx_set_extenpatternmatchnew(), and ast_cli_entry::usage.
07295 { 07296 int oldval = 0; 07297 07298 switch (cmd) { 07299 case CLI_INIT: 07300 e->command = "dialplan set extenpatternmatchnew true"; 07301 e->usage = 07302 "Usage: dialplan set extenpatternmatchnew true|false\n" 07303 " Use the NEW extension pattern matching algorithm, true or false.\n"; 07304 return NULL; 07305 case CLI_GENERATE: 07306 return NULL; 07307 } 07308 07309 if (a->argc != 4) 07310 return CLI_SHOWUSAGE; 07311 07312 oldval = pbx_set_extenpatternmatchnew(1); 07313 07314 if (oldval) 07315 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n"); 07316 else 07317 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n"); 07318 07319 return CLI_SUCCESS; 07320 }
static char* handle_set_global | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7235 of file pbx.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pbx_builtin_setvar_helper(), and ast_cli_entry::usage.
07236 { 07237 switch (cmd) { 07238 case CLI_INIT: 07239 e->command = "dialplan set global"; 07240 e->usage = 07241 "Usage: dialplan set global <name> <value>\n" 07242 " Set global dialplan variable <name> to <value>\n"; 07243 return NULL; 07244 case CLI_GENERATE: 07245 return NULL; 07246 } 07247 07248 if (a->argc != e->args + 2) 07249 return CLI_SHOWUSAGE; 07250 07251 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]); 07252 ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]); 07253 07254 return CLI_SUCCESS; 07255 }
static char* handle_show_application | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6246 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_complete_applications(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_app::name, print_app_docs(), ast_cli_entry::usage, and ast_cli_args::word.
06247 { 06248 struct ast_app *aa; 06249 int app, no_registered_app = 1; 06250 06251 switch (cmd) { 06252 case CLI_INIT: 06253 e->command = "core show application"; 06254 e->usage = 06255 "Usage: core show application <application> [<application> [<application> [...]]]\n" 06256 " Describes a particular application.\n"; 06257 return NULL; 06258 case CLI_GENERATE: 06259 /* 06260 * There is a possibility to show informations about more than one 06261 * application at one time. You can type 'show application Dial Echo' and 06262 * you will see informations about these two applications ... 06263 */ 06264 return ast_complete_applications(a->line, a->word, a->n); 06265 } 06266 06267 if (a->argc < 4) { 06268 return CLI_SHOWUSAGE; 06269 } 06270 06271 AST_RWLIST_RDLOCK(&apps); 06272 AST_RWLIST_TRAVERSE(&apps, aa, list) { 06273 /* Check for each app that was supplied as an argument */ 06274 for (app = 3; app < a->argc; app++) { 06275 if (strcasecmp(aa->name, a->argv[app])) { 06276 continue; 06277 } 06278 06279 /* We found it! */ 06280 no_registered_app = 0; 06281 06282 print_app_docs(aa, a->fd); 06283 } 06284 } 06285 AST_RWLIST_UNLOCK(&apps); 06286 06287 /* we found at least one app? no? */ 06288 if (no_registered_app) { 06289 ast_cli(a->fd, "Your application(s) is (are) not registered\n"); 06290 return CLI_FAILURE; 06291 } 06292 06293 return CLI_SUCCESS; 06294 }
static char* handle_show_applications | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6471 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_cli_complete(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_app::description, ast_cli_args::fd, ast_cli_args::n, ast_app::name, ast_cli_args::pos, ast_app::synopsis, ast_cli_entry::usage, and ast_cli_args::word.
06472 { 06473 struct ast_app *aa; 06474 int like = 0, describing = 0; 06475 int total_match = 0; /* Number of matches in like clause */ 06476 int total_apps = 0; /* Number of apps registered */ 06477 static const char * const choices[] = { "like", "describing", NULL }; 06478 06479 switch (cmd) { 06480 case CLI_INIT: 06481 e->command = "core show applications [like|describing]"; 06482 e->usage = 06483 "Usage: core show applications [{like|describing} <text>]\n" 06484 " List applications which are currently available.\n" 06485 " If 'like', <text> will be a substring of the app name\n" 06486 " If 'describing', <text> will be a substring of the description\n"; 06487 return NULL; 06488 case CLI_GENERATE: 06489 return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n); 06490 } 06491 06492 AST_RWLIST_RDLOCK(&apps); 06493 06494 if (AST_RWLIST_EMPTY(&apps)) { 06495 ast_cli(a->fd, "There are no registered applications\n"); 06496 AST_RWLIST_UNLOCK(&apps); 06497 return CLI_SUCCESS; 06498 } 06499 06500 /* core list applications like <keyword> */ 06501 if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) { 06502 like = 1; 06503 } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) { 06504 describing = 1; 06505 } 06506 06507 /* core list applications describing <keyword1> [<keyword2>] [...] */ 06508 if ((!like) && (!describing)) { 06509 ast_cli(a->fd, " -= Registered Asterisk Applications =-\n"); 06510 } else { 06511 ast_cli(a->fd, " -= Matching Asterisk Applications =-\n"); 06512 } 06513 06514 AST_RWLIST_TRAVERSE(&apps, aa, list) { 06515 int printapp = 0; 06516 total_apps++; 06517 if (like) { 06518 if (strcasestr(aa->name, a->argv[4])) { 06519 printapp = 1; 06520 total_match++; 06521 } 06522 } else if (describing) { 06523 if (aa->description) { 06524 /* Match all words on command line */ 06525 int i; 06526 printapp = 1; 06527 for (i = 4; i < a->argc; i++) { 06528 if (!strcasestr(aa->description, a->argv[i])) { 06529 printapp = 0; 06530 } else { 06531 total_match++; 06532 } 06533 } 06534 } 06535 } else { 06536 printapp = 1; 06537 } 06538 06539 if (printapp) { 06540 ast_cli(a->fd," %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>"); 06541 } 06542 } 06543 if ((!like) && (!describing)) { 06544 ast_cli(a->fd, " -= %d Applications Registered =-\n",total_apps); 06545 } else { 06546 ast_cli(a->fd, " -= %d Applications Matching =-\n",total_match); 06547 } 06548 06549 AST_RWLIST_UNLOCK(&apps); 06550 06551 return CLI_SUCCESS; 06552 }
static char* handle_show_chanvar | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
CLI support for listing chanvar's variables in a parseable way.
Definition at line 7200 of file pbx.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_get_by_name(), ast_channel_unref, ast_cli(), ast_complete_channels(), ast_str_alloca, ast_str_buffer(), ast_str_strlen(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, pbx_builtin_serialize_variables(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
07201 { 07202 struct ast_channel *chan = NULL; 07203 struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */ 07204 07205 switch (cmd) { 07206 case CLI_INIT: 07207 e->command = "dialplan show chanvar"; 07208 e->usage = 07209 "Usage: dialplan show chanvar <channel>\n" 07210 " List current channel variables and their values\n"; 07211 return NULL; 07212 case CLI_GENERATE: 07213 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 07214 } 07215 07216 if (a->argc != e->args + 1) 07217 return CLI_SHOWUSAGE; 07218 07219 if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) { 07220 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]); 07221 return CLI_FAILURE; 07222 } 07223 07224 pbx_builtin_serialize_variables(chan, &vars); 07225 07226 if (ast_str_strlen(vars)) { 07227 ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars)); 07228 } 07229 07230 chan = ast_channel_unref(chan); 07231 07232 return CLI_SUCCESS; 07233 }
static char* handle_show_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6817 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), dialplan_counters::context_existence, exten, dialplan_counters::extension_existence, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_dialplan_helper(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_prio, ast_cli_entry::usage, and ast_cli_args::word.
06818 { 06819 char *exten = NULL, *context = NULL; 06820 /* Variables used for different counters */ 06821 struct dialplan_counters counters; 06822 const char *incstack[AST_PBX_MAX_STACK]; 06823 06824 switch (cmd) { 06825 case CLI_INIT: 06826 e->command = "dialplan show"; 06827 e->usage = 06828 "Usage: dialplan show [[exten@]context]\n" 06829 " Show dialplan\n"; 06830 return NULL; 06831 case CLI_GENERATE: 06832 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 06833 } 06834 06835 memset(&counters, 0, sizeof(counters)); 06836 06837 if (a->argc != 2 && a->argc != 3) 06838 return CLI_SHOWUSAGE; 06839 06840 /* we obtain [exten@]context? if yes, split them ... */ 06841 if (a->argc == 3) { 06842 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 06843 context = ast_strdupa(a->argv[2]); 06844 exten = strsep(&context, "@"); 06845 /* change empty strings to NULL */ 06846 if (ast_strlen_zero(exten)) 06847 exten = NULL; 06848 } else { /* no '@' char, only context given */ 06849 context = ast_strdupa(a->argv[2]); 06850 } 06851 if (ast_strlen_zero(context)) 06852 context = NULL; 06853 } 06854 /* else Show complete dial plan, context and exten are NULL */ 06855 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 06856 06857 /* check for input failure and throw some error messages */ 06858 if (context && !counters.context_existence) { 06859 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 06860 return CLI_FAILURE; 06861 } 06862 06863 if (exten && !counters.extension_existence) { 06864 if (context) 06865 ast_cli(a->fd, "There is no existence of %s@%s extension\n", 06866 exten, context); 06867 else 06868 ast_cli(a->fd, 06869 "There is no existence of '%s' extension in all contexts\n", 06870 exten); 06871 return CLI_FAILURE; 06872 } 06873 06874 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n", 06875 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 06876 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 06877 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 06878 06879 /* everything ok */ 06880 return CLI_SUCCESS; 06881 }
static char* handle_show_function | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3618 of file pbx.c.
References ast_custom_function::acflist, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_custom_function_find(), ast_free, ast_malloc, AST_MAX_APP, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, ast_xmldoc_printable(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_CYAN, COLOR_MAGENTA, ast_cli_entry::command, ast_custom_function::docsrc, ast_cli_args::fd, ast_cli_args::n, ast_custom_function::name, S_OR, synopsis, term_color(), ast_cli_entry::usage, and ast_cli_args::word.
03619 { 03620 struct ast_custom_function *acf; 03621 /* Maximum number of characters added by terminal coloring is 22 */ 03622 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40]; 03623 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL; 03624 char stxtitle[40], *syntax = NULL, *arguments = NULL; 03625 int syntax_size, description_size, synopsis_size, arguments_size, seealso_size; 03626 char *ret = NULL; 03627 int which = 0; 03628 int wordlen; 03629 03630 switch (cmd) { 03631 case CLI_INIT: 03632 e->command = "core show function"; 03633 e->usage = 03634 "Usage: core show function <function>\n" 03635 " Describe a particular dialplan function.\n"; 03636 return NULL; 03637 case CLI_GENERATE: 03638 wordlen = strlen(a->word); 03639 /* case-insensitive for convenience in this 'complete' function */ 03640 AST_RWLIST_RDLOCK(&acf_root); 03641 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03642 if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) { 03643 ret = ast_strdup(acf->name); 03644 break; 03645 } 03646 } 03647 AST_RWLIST_UNLOCK(&acf_root); 03648 03649 return ret; 03650 } 03651 03652 if (a->argc < 4) { 03653 return CLI_SHOWUSAGE; 03654 } 03655 03656 if (!(acf = ast_custom_function_find(a->argv[3]))) { 03657 ast_cli(a->fd, "No function by that name registered.\n"); 03658 return CLI_FAILURE; 03659 } 03660 03661 syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03662 if (!(syntax = ast_malloc(syntax_size))) { 03663 ast_cli(a->fd, "Memory allocation failure!\n"); 03664 return CLI_FAILURE; 03665 } 03666 03667 snprintf(info, sizeof(info), "\n -= Info about function '%s' =- \n\n", acf->name); 03668 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 03669 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03670 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03671 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 03672 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 03673 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 03674 term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 03675 #ifdef AST_XML_DOCS 03676 if (acf->docsrc == AST_XML_DOC) { 03677 arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1); 03678 synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1); 03679 description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1); 03680 seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1); 03681 } else 03682 #endif 03683 { 03684 synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03685 synopsis = ast_malloc(synopsis_size); 03686 03687 description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03688 description = ast_malloc(description_size); 03689 03690 arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03691 arguments = ast_malloc(arguments_size); 03692 03693 seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03694 seealso = ast_malloc(seealso_size); 03695 03696 /* check allocated memory. */ 03697 if (!synopsis || !description || !arguments || !seealso) { 03698 ast_free(synopsis); 03699 ast_free(description); 03700 ast_free(arguments); 03701 ast_free(seealso); 03702 ast_free(syntax); 03703 return CLI_FAILURE; 03704 } 03705 03706 term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 03707 term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 03708 term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size); 03709 term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 03710 } 03711 03712 ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 03713 infotitle, syntitle, synopsis, destitle, description, 03714 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 03715 03716 ast_free(arguments); 03717 ast_free(synopsis); 03718 ast_free(description); 03719 ast_free(seealso); 03720 ast_free(syntax); 03721 03722 return CLI_SUCCESS; 03723 }
static char* handle_show_functions | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3576 of file pbx.c.
References ast_custom_function::acflist, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_custom_function::name, S_OR, and ast_cli_entry::usage.
03577 { 03578 struct ast_custom_function *acf; 03579 int count_acf = 0; 03580 int like = 0; 03581 03582 switch (cmd) { 03583 case CLI_INIT: 03584 e->command = "core show functions [like]"; 03585 e->usage = 03586 "Usage: core show functions [like <text>]\n" 03587 " List builtin functions, optionally only those matching a given string\n"; 03588 return NULL; 03589 case CLI_GENERATE: 03590 return NULL; 03591 } 03592 03593 if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) { 03594 like = 1; 03595 } else if (a->argc != 3) { 03596 return CLI_SHOWUSAGE; 03597 } 03598 03599 ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 03600 03601 AST_RWLIST_RDLOCK(&acf_root); 03602 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03603 if (!like || strstr(acf->name, a->argv[4])) { 03604 count_acf++; 03605 ast_cli(a->fd, "%-20.20s %-35.35s %s\n", 03606 S_OR(acf->name, ""), 03607 S_OR(acf->syntax, ""), 03608 S_OR(acf->synopsis, "")); 03609 } 03610 } 03611 AST_RWLIST_UNLOCK(&acf_root); 03612 03613 ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 03614 03615 return CLI_SUCCESS; 03616 }
static char* handle_show_globals | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
CLI support for listing global variables in a parseable way.
Definition at line 7142 of file pbx.c.
References ast_cli(), AST_LIST_TRAVERSE, ast_rwlock_rdlock, ast_rwlock_unlock, ast_var_name(), ast_var_value(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, globals, globalslock, and ast_cli_entry::usage.
07143 { 07144 int i = 0; 07145 struct ast_var_t *newvariable; 07146 07147 switch (cmd) { 07148 case CLI_INIT: 07149 e->command = "dialplan show globals"; 07150 e->usage = 07151 "Usage: dialplan show globals\n" 07152 " List current global dialplan variables and their values\n"; 07153 return NULL; 07154 case CLI_GENERATE: 07155 return NULL; 07156 } 07157 07158 ast_rwlock_rdlock(&globalslock); 07159 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 07160 i++; 07161 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 07162 } 07163 ast_rwlock_unlock(&globalslock); 07164 ast_cli(a->fd, "\n -- %d variable(s)\n", i); 07165 07166 return CLI_SUCCESS; 07167 }
static char* handle_show_hint | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
handle_show_hint: CLI support for listing registered dial plan hint
Definition at line 6383 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_core_show_hint(), ast_hint::exten, ast_cli_args::fd, hints, ast_hint::laststate, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
06384 { 06385 struct ast_hint *hint; 06386 int watchers; 06387 int num = 0, extenlen; 06388 struct ao2_iterator i; 06389 06390 switch (cmd) { 06391 case CLI_INIT: 06392 e->command = "core show hint"; 06393 e->usage = 06394 "Usage: core show hint <exten>\n" 06395 " List registered hint\n"; 06396 return NULL; 06397 case CLI_GENERATE: 06398 return complete_core_show_hint(a->line, a->word, a->pos, a->n); 06399 } 06400 06401 if (a->argc < 4) 06402 return CLI_SHOWUSAGE; 06403 06404 if (ao2_container_count(hints) == 0) { 06405 ast_cli(a->fd, "There are no registered dialplan hints\n"); 06406 return CLI_SUCCESS; 06407 } 06408 06409 extenlen = strlen(a->argv[3]); 06410 i = ao2_iterator_init(hints, 0); 06411 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06412 ao2_lock(hint); 06413 if (!hint->exten) { 06414 /* The extension has already been destroyed */ 06415 ao2_unlock(hint); 06416 continue; 06417 } 06418 if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) { 06419 watchers = ao2_container_count(hint->callbacks); 06420 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 06421 ast_get_extension_name(hint->exten), 06422 ast_get_context_name(ast_get_extension_context(hint->exten)), 06423 ast_get_extension_app(hint->exten), 06424 ast_extension_state2str(hint->laststate), watchers); 06425 num++; 06426 } 06427 ao2_unlock(hint); 06428 } 06429 ao2_iterator_destroy(&i); 06430 if (!num) 06431 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]); 06432 else 06433 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]); 06434 return CLI_SUCCESS; 06435 }
static char* handle_show_hints | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
handle_show_hints: CLI support for listing registered dial plan hints
Definition at line 6297 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_hint::exten, ast_cli_args::fd, hints, ast_hint::laststate, and ast_cli_entry::usage.
06298 { 06299 struct ast_hint *hint; 06300 int num = 0; 06301 int watchers; 06302 struct ao2_iterator i; 06303 06304 switch (cmd) { 06305 case CLI_INIT: 06306 e->command = "core show hints"; 06307 e->usage = 06308 "Usage: core show hints\n" 06309 " List registered hints\n"; 06310 return NULL; 06311 case CLI_GENERATE: 06312 return NULL; 06313 } 06314 06315 if (ao2_container_count(hints) == 0) { 06316 ast_cli(a->fd, "There are no registered dialplan hints\n"); 06317 return CLI_SUCCESS; 06318 } 06319 /* ... we have hints ... */ 06320 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 06321 06322 i = ao2_iterator_init(hints, 0); 06323 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06324 ao2_lock(hint); 06325 if (!hint->exten) { 06326 /* The extension has already been destroyed */ 06327 ao2_unlock(hint); 06328 continue; 06329 } 06330 watchers = ao2_container_count(hint->callbacks); 06331 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 06332 ast_get_extension_name(hint->exten), 06333 ast_get_context_name(ast_get_extension_context(hint->exten)), 06334 ast_get_extension_app(hint->exten), 06335 ast_extension_state2str(hint->laststate), watchers); 06336 ao2_unlock(hint); 06337 num++; 06338 } 06339 ao2_iterator_destroy(&i); 06340 06341 ast_cli(a->fd, "----------------\n"); 06342 ast_cli(a->fd, "- %d hints registered\n", num); 06343 return CLI_SUCCESS; 06344 }
static char* handle_show_switches | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
handle_show_switches: CLI support for listing registered dial plan switches
Definition at line 6439 of file pbx.c.
References ast_cli(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_switch::description, ast_cli_args::fd, ast_switch::name, and ast_cli_entry::usage.
06440 { 06441 struct ast_switch *sw; 06442 06443 switch (cmd) { 06444 case CLI_INIT: 06445 e->command = "core show switches"; 06446 e->usage = 06447 "Usage: core show switches\n" 06448 " List registered switches\n"; 06449 return NULL; 06450 case CLI_GENERATE: 06451 return NULL; 06452 } 06453 06454 AST_RWLIST_RDLOCK(&switches); 06455 06456 if (AST_RWLIST_EMPTY(&switches)) { 06457 AST_RWLIST_UNLOCK(&switches); 06458 ast_cli(a->fd, "There are no registered alternative switches\n"); 06459 return CLI_SUCCESS; 06460 } 06461 06462 ast_cli(a->fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 06463 AST_RWLIST_TRAVERSE(&switches, sw, list) 06464 ast_cli(a->fd, "%s: %s\n", sw->name, sw->description); 06465 06466 AST_RWLIST_UNLOCK(&switches); 06467 06468 return CLI_SUCCESS; 06469 }
static int handle_statechange | ( | void * | datap | ) | [static] |
Definition at line 4640 of file pbx.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), ast_extension_state3(), ast_free, ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_str_buffer(), ast_str_create(), ast_str_set(), ast_hint::callbacks, ast_state_cb::change_cb, context_merge_lock, ast_state_cb::data, statechange::dev, ast_hint::exten, hints, ast_hint::laststate, parse(), and statecbs.
Referenced by device_state_cb().
04641 { 04642 struct ast_hint *hint; 04643 struct ast_str *hint_app; 04644 struct statechange *sc = datap; 04645 struct ao2_iterator i; 04646 struct ao2_iterator cb_iter; 04647 char context_name[AST_MAX_CONTEXT]; 04648 char exten_name[AST_MAX_EXTENSION]; 04649 04650 hint_app = ast_str_create(1024); 04651 if (!hint_app) { 04652 ast_free(sc); 04653 return -1; 04654 } 04655 04656 ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */ 04657 i = ao2_iterator_init(hints, 0); 04658 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 04659 struct ast_state_cb *state_cb; 04660 char *cur, *parse; 04661 int state; 04662 04663 ao2_lock(hint); 04664 if (!hint->exten) { 04665 /* The extension has already been destroyed */ 04666 ao2_unlock(hint); 04667 continue; 04668 } 04669 04670 /* Does this hint monitor the device that changed state? */ 04671 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten)); 04672 parse = ast_str_buffer(hint_app); 04673 while ((cur = strsep(&parse, "&"))) { 04674 if (!strcasecmp(cur, sc->dev)) { 04675 /* The hint monitors the device. */ 04676 break; 04677 } 04678 } 04679 if (!cur) { 04680 /* The hint does not monitor the device. */ 04681 ao2_unlock(hint); 04682 continue; 04683 } 04684 04685 /* 04686 * Save off strings in case the hint extension gets destroyed 04687 * while we are notifying the watchers. 04688 */ 04689 ast_copy_string(context_name, 04690 ast_get_context_name(ast_get_extension_context(hint->exten)), 04691 sizeof(context_name)); 04692 ast_copy_string(exten_name, ast_get_extension_name(hint->exten), 04693 sizeof(exten_name)); 04694 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten)); 04695 ao2_unlock(hint); 04696 04697 /* 04698 * Get device state for this hint. 04699 * 04700 * NOTE: We cannot hold any locks while determining the hint 04701 * device state or notifying the watchers without causing a 04702 * deadlock. (conlock, hints, and hint) 04703 */ 04704 state = ast_extension_state3(hint_app); 04705 if (state == hint->laststate) { 04706 continue; 04707 } 04708 04709 /* Device state changed since last check - notify the watchers. */ 04710 hint->laststate = state; /* record we saw the change */ 04711 04712 /* For general callbacks */ 04713 cb_iter = ao2_iterator_init(statecbs, 0); 04714 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) { 04715 state_cb->change_cb(context_name, exten_name, state, state_cb->data); 04716 } 04717 ao2_iterator_destroy(&cb_iter); 04718 04719 /* For extension callbacks */ 04720 cb_iter = ao2_iterator_init(hint->callbacks, 0); 04721 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) { 04722 state_cb->change_cb(context_name, exten_name, state, state_cb->data); 04723 } 04724 ao2_iterator_destroy(&cb_iter); 04725 } 04726 ao2_iterator_destroy(&i); 04727 ast_mutex_unlock(&context_merge_lock); 04728 04729 ast_free(hint_app); 04730 ast_free(sc); 04731 return 0; 04732 }
static char* handle_unset_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 7322 of file pbx.c.
References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pbx_set_extenpatternmatchnew(), and ast_cli_entry::usage.
07323 { 07324 int oldval = 0; 07325 07326 switch (cmd) { 07327 case CLI_INIT: 07328 e->command = "dialplan set extenpatternmatchnew false"; 07329 e->usage = 07330 "Usage: dialplan set extenpatternmatchnew true|false\n" 07331 " Use the NEW extension pattern matching algorithm, true or false.\n"; 07332 return NULL; 07333 case CLI_GENERATE: 07334 return NULL; 07335 } 07336 07337 if (a->argc != 4) 07338 return CLI_SHOWUSAGE; 07339 07340 oldval = pbx_set_extenpatternmatchnew(0); 07341 07342 if (!oldval) 07343 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n"); 07344 else 07345 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n"); 07346 07347 return CLI_SUCCESS; 07348 }
static int hashtab_compare_exten_labels | ( | const void * | ah_a, | |
const void * | ah_b | |||
) | [static] |
static int hashtab_compare_exten_numbers | ( | const void * | ah_a, | |
const void * | ah_b | |||
) | [static] |
Definition at line 1110 of file pbx.c.
References ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
static int hashtab_compare_extens | ( | const void * | ha_a, | |
const void * | ah_b | |||
) | [static] |
Definition at line 1091 of file pbx.c.
References ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
01092 { 01093 const struct ast_exten *ac = ah_a; 01094 const struct ast_exten *bc = ah_b; 01095 int x = strcmp(ac->exten, bc->exten); 01096 if (x) { /* if exten names are diff, then return */ 01097 return x; 01098 } 01099 01100 /* but if they are the same, do the cidmatch values match? */ 01101 if (ac->matchcid && bc->matchcid) { 01102 return strcmp(ac->cidmatch,bc->cidmatch); 01103 } else if (!ac->matchcid && !bc->matchcid) { 01104 return 0; /* if there's no matchcid on either side, then this is a match */ 01105 } else { 01106 return 1; /* if there's matchcid on one but not the other, they are different */ 01107 } 01108 }
static unsigned int hashtab_hash_extens | ( | const void * | obj | ) | [static] |
Definition at line 1130 of file pbx.c.
References ast_hashtab_hash_string(), ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
01131 { 01132 const struct ast_exten *ac = obj; 01133 unsigned int x = ast_hashtab_hash_string(ac->exten); 01134 unsigned int y = 0; 01135 if (ac->matchcid) 01136 y = ast_hashtab_hash_string(ac->cidmatch); 01137 return x+y; 01138 }
static unsigned int hashtab_hash_labels | ( | const void * | obj | ) | [static] |
Definition at line 1146 of file pbx.c.
References ast_hashtab_hash_string(), ast_exten::label, and S_OR.
Referenced by ast_add_extension2_lockopt().
01147 { 01148 const struct ast_exten *ac = obj; 01149 return ast_hashtab_hash_string(S_OR(ac->label, "")); 01150 }
static unsigned int hashtab_hash_priority | ( | const void * | obj | ) | [static] |
Definition at line 1140 of file pbx.c.
References ast_hashtab_hash_int(), and ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
01141 { 01142 const struct ast_exten *ac = obj; 01143 return ast_hashtab_hash_int(ac->priority); 01144 }
static int hint_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
static int hint_hash | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 10935 of file pbx.c.
References ast_get_extension_name(), ast_str_case_hash(), ast_strlen_zero(), ast_hint::exten, and ast_hint::exten_name.
Referenced by ast_pbx_init().
10936 { 10937 const struct ast_hint *hint = obj; 10938 const char *exten_name; 10939 int res; 10940 10941 exten_name = ast_get_extension_name(hint->exten); 10942 if (ast_strlen_zero(exten_name)) { 10943 /* 10944 * If the exten or extension name isn't set, return 0 so that 10945 * the ao2_find() search will start in the first bucket. 10946 */ 10947 res = 0; 10948 } else { 10949 res = ast_str_case_hash(exten_name); 10950 } 10951 10952 return res; 10953 }
static int hint_id_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 4895 of file pbx.c.
References CMP_MATCH, CMP_STOP, and ast_state_cb::id.
Referenced by ast_add_hint().
04896 { 04897 const struct ast_state_cb *cb = obj; 04898 int *id = arg; 04899 04900 return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0; 04901 }
static int hints_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 10508 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_data_add_int(), ast_data_add_node(), ast_data_add_str(), ast_data_remove_node(), ast_data_search_match(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, ast_hint::exten, hints, and ast_hint::laststate.
10510 { 10511 struct ast_data *data_hint; 10512 struct ast_hint *hint; 10513 int watchers; 10514 struct ao2_iterator i; 10515 10516 if (ao2_container_count(hints) == 0) { 10517 return 0; 10518 } 10519 10520 i = ao2_iterator_init(hints, 0); 10521 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 10522 watchers = ao2_container_count(hint->callbacks); 10523 data_hint = ast_data_add_node(data_root, "hint"); 10524 if (!data_hint) { 10525 continue; 10526 } 10527 ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten)); 10528 ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten))); 10529 ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten)); 10530 ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate)); 10531 ast_data_add_int(data_hint, "watchers", watchers); 10532 10533 if (!ast_data_search_match(search, data_hint)) { 10534 ast_data_remove_node(data_root, data_hint); 10535 } 10536 } 10537 ao2_iterator_destroy(&i); 10538 10539 return 0; 10540 }
static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 1490 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
Referenced by pbx_find_extension().
01491 { 01492 if (!i->hastime) 01493 return 1; 01494 01495 return ast_check_timing(&(i->timing)); 01496 }
static int increase_call_count | ( | const struct ast_channel * | c | ) | [static] |
Increase call count for channel.
0 | on success | |
non-zero | if a configured limit (maxcalls, maxload, minmemfree) was reached |
Definition at line 5490 of file pbx.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, countcalls, LOG_WARNING, maxcalllock, option_maxcalls, option_maxload, option_minmemfree, and totalcalls.
Referenced by ast_pbx_run_args(), and ast_pbx_start().
05491 { 05492 int failed = 0; 05493 double curloadavg; 05494 #if defined(HAVE_SYSINFO) 05495 long curfreemem; 05496 struct sysinfo sys_info; 05497 #endif 05498 05499 ast_mutex_lock(&maxcalllock); 05500 if (option_maxcalls) { 05501 if (countcalls >= option_maxcalls) { 05502 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 05503 failed = -1; 05504 } 05505 } 05506 if (option_maxload) { 05507 getloadavg(&curloadavg, 1); 05508 if (curloadavg >= option_maxload) { 05509 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 05510 failed = -1; 05511 } 05512 } 05513 #if defined(HAVE_SYSINFO) 05514 if (option_minmemfree) { 05515 if (!sysinfo(&sys_info)) { 05516 /* make sure that the free system memory is above the configured low watermark 05517 * convert the amount of freeram from mem_units to MB */ 05518 curfreemem = sys_info.freeram * sys_info.mem_unit; 05519 curfreemem /= 1024 * 1024; 05520 if (curfreemem < option_minmemfree) { 05521 ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree); 05522 failed = -1; 05523 } 05524 } 05525 } 05526 #endif 05527 05528 if (!failed) { 05529 countcalls++; 05530 totalcalls++; 05531 } 05532 ast_mutex_unlock(&maxcalllock); 05533 05534 return failed; 05535 }
static void insert_in_next_chars_alt_char_list | ( | struct match_char ** | parent_ptr, | |
struct match_char * | node | |||
) | [static] |
Definition at line 1908 of file pbx.c.
References match_char::alt_char, and match_char::specificity.
Referenced by add_pattern_node().
01909 { 01910 struct match_char *curr, *lcurr; 01911 01912 /* insert node into the tree at "current", so the alt_char list from current is 01913 sorted in increasing value as you go to the leaves */ 01914 if (!(*parent_ptr)) { 01915 *parent_ptr = node; 01916 return; 01917 } 01918 01919 if ((*parent_ptr)->specificity > node->specificity) { 01920 /* insert at head */ 01921 node->alt_char = (*parent_ptr); 01922 *parent_ptr = node; 01923 return; 01924 } 01925 01926 lcurr = *parent_ptr; 01927 for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) { 01928 if (curr->specificity > node->specificity) { 01929 node->alt_char = curr; 01930 lcurr->alt_char = node; 01931 break; 01932 } 01933 lcurr = curr; 01934 } 01935 01936 if (!curr) { 01937 lcurr->alt_char = node; 01938 } 01939 01940 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 10576 of file pbx.c.
References __ast_custom_function_register(), ARRAY_LEN, ast_cli_register_multiple(), ast_data_register_multiple_core, AST_EVENT_DEVICE_STATE, AST_EVENT_IE_END, ast_event_subscribe(), ast_log(), ast_manager_register_xml, ast_register_application2(), ast_register_atexit(), ast_taskprocessor_get(), ast_verb, builtins, device_state_cb(), device_state_sub, EVENT_FLAG_CONFIG, EVENT_FLAG_REPORTING, exception_function, LOG_ERROR, LOG_WARNING, manager_show_dialplan(), pbx_cli, pbx_data_providers, testtime_function, and unload_pbx().
Referenced by main().
10577 { 10578 int x; 10579 10580 ast_register_atexit(unload_pbx); 10581 10582 /* Initialize the PBX */ 10583 ast_verb(1, "Asterisk PBX Core Initializing\n"); 10584 if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) { 10585 ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n"); 10586 } 10587 10588 ast_verb(1, "Registering builtin applications:\n"); 10589 ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli)); 10590 ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers)); 10591 __ast_custom_function_register(&exception_function, NULL); 10592 __ast_custom_function_register(&testtime_function, NULL); 10593 10594 /* Register builtin applications */ 10595 for (x = 0; x < ARRAY_LEN(builtins); x++) { 10596 ast_verb(1, "[%s]\n", builtins[x].name); 10597 if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) { 10598 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 10599 return -1; 10600 } 10601 } 10602 10603 /* Register manager application */ 10604 ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan); 10605 10606 if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL, 10607 AST_EVENT_IE_END))) { 10608 return -1; 10609 } 10610 10611 return 0; 10612 }
static int lookup_name | ( | const char * | s, | |
const char *const | names[], | |||
int | max | |||
) | [static] |
Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values.
Definition at line 7832 of file pbx.c.
Referenced by get_range().
07833 { 07834 int i; 07835 07836 if (names && *s > '9') { 07837 for (i = 0; names[i]; i++) { 07838 if (!strcasecmp(s, names[i])) { 07839 return i; 07840 } 07841 } 07842 } 07843 07844 /* Allow months and weekdays to be specified as numbers, as well */ 07845 if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) { 07846 /* What the array offset would have been: "1" would be at offset 0 */ 07847 return i - 1; 07848 } 07849 return -1; /* error return */ 07850 }
static void manager_dpsendack | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Send ack once.
Definition at line 6940 of file pbx.c.
References astman_send_listack().
Referenced by manager_show_dialplan(), and manager_show_dialplan_helper().
06941 { 06942 astman_send_listack(s, m, "DialPlan list will follow", "start"); 06943 }
static int manager_show_dialplan | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager listing of dial plan.
Definition at line 7085 of file pbx.c.
References ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), dialplan_counters::context_existence, exten, dialplan_counters::extension_existence, manager_dpsendack(), manager_show_dialplan_helper(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.
Referenced by load_pbx().
07086 { 07087 const char *exten, *context; 07088 const char *id = astman_get_header(m, "ActionID"); 07089 char idtext[256]; 07090 07091 /* Variables used for different counters */ 07092 struct dialplan_counters counters; 07093 07094 if (!ast_strlen_zero(id)) 07095 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 07096 else 07097 idtext[0] = '\0'; 07098 07099 memset(&counters, 0, sizeof(counters)); 07100 07101 exten = astman_get_header(m, "Extension"); 07102 context = astman_get_header(m, "Context"); 07103 07104 manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL); 07105 07106 if (!ast_strlen_zero(context) && !counters.context_existence) { 07107 char errorbuf[BUFSIZ]; 07108 07109 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context); 07110 astman_send_error(s, m, errorbuf); 07111 return 0; 07112 } 07113 if (!ast_strlen_zero(exten) && !counters.extension_existence) { 07114 char errorbuf[BUFSIZ]; 07115 07116 if (!ast_strlen_zero(context)) 07117 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context); 07118 else 07119 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten); 07120 astman_send_error(s, m, errorbuf); 07121 return 0; 07122 } 07123 07124 if (!counters.total_items) { 07125 manager_dpsendack(s, m); 07126 } 07127 07128 astman_append(s, "Event: ShowDialPlanComplete\r\n" 07129 "EventList: Complete\r\n" 07130 "ListItems: %d\r\n" 07131 "ListExtensions: %d\r\n" 07132 "ListPriorities: %d\r\n" 07133 "ListContexts: %d\r\n" 07134 "%s" 07135 "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext); 07136 07137 /* everything ok */ 07138 return 0; 07139 }
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, | |||
struct ast_include * | rinclude | |||
) | [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 6949 of file pbx.c.
References 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_rdlock_context(), ast_rdlock_contexts(), ast_strlen_zero(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), ast_walk_contexts(), ast_walk_extension_priorities(), astman_append(), astman_send_error(), dialplan_counters::context_existence, dialplan_counters::extension_existence, LOG_WARNING, manager_dpsendack(), PRIORITY_HINT, dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.
Referenced by manager_show_dialplan().
06953 { 06954 struct ast_context *c; 06955 int res = 0, old_total_exten = dpc->total_exten; 06956 06957 if (ast_strlen_zero(exten)) 06958 exten = NULL; 06959 if (ast_strlen_zero(context)) 06960 context = NULL; 06961 06962 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten); 06963 06964 /* try to lock contexts */ 06965 if (ast_rdlock_contexts()) { 06966 astman_send_error(s, m, "Failed to lock contexts"); 06967 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n"); 06968 return -1; 06969 } 06970 06971 c = NULL; /* walk all contexts ... */ 06972 while ( (c = ast_walk_contexts(c)) ) { 06973 struct ast_exten *e; 06974 struct ast_include *i; 06975 struct ast_ignorepat *ip; 06976 06977 if (context && strcmp(ast_get_context_name(c), context) != 0) 06978 continue; /* not the name we want */ 06979 06980 dpc->context_existence = 1; 06981 dpc->total_context++; 06982 06983 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c)); 06984 06985 if (ast_rdlock_context(c)) { /* failed to lock */ 06986 ast_debug(3, "manager_show_dialplan: Failed to lock context\n"); 06987 continue; 06988 } 06989 06990 /* XXX note- an empty context is not printed */ 06991 e = NULL; /* walk extensions in context */ 06992 while ( (e = ast_walk_context_extensions(c, e)) ) { 06993 struct ast_exten *p; 06994 06995 /* looking for extension? is this our extension? */ 06996 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) { 06997 /* not the one we are looking for, continue */ 06998 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e)); 06999 continue; 07000 } 07001 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e)); 07002 07003 dpc->extension_existence = 1; 07004 07005 dpc->total_exten++; 07006 07007 p = NULL; /* walk next extension peers */ 07008 while ( (p = ast_walk_extension_priorities(e, p)) ) { 07009 int prio = ast_get_extension_priority(p); 07010 07011 dpc->total_prio++; 07012 if (!dpc->total_items++) 07013 manager_dpsendack(s, m); 07014 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07015 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) ); 07016 07017 /* XXX maybe make this conditional, if p != e ? */ 07018 if (ast_get_extension_label(p)) 07019 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p)); 07020 07021 if (prio == PRIORITY_HINT) { 07022 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p)); 07023 } else { 07024 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)); 07025 } 07026 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e)); 07027 } 07028 } 07029 07030 i = NULL; /* walk included and write info ... */ 07031 while ( (i = ast_walk_context_includes(c, i)) ) { 07032 if (exten) { 07033 /* Check all includes for the requested extension */ 07034 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i); 07035 } else { 07036 if (!dpc->total_items++) 07037 manager_dpsendack(s, m); 07038 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07039 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)); 07040 astman_append(s, "\r\n"); 07041 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i)); 07042 } 07043 } 07044 07045 ip = NULL; /* walk ignore patterns and write info ... */ 07046 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 07047 const char *ipname = ast_get_ignorepat_name(ip); 07048 char ignorepat[AST_MAX_EXTENSION]; 07049 07050 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 07051 if (!exten || ast_extension_match(ignorepat, exten)) { 07052 if (!dpc->total_items++) 07053 manager_dpsendack(s, m); 07054 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07055 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip)); 07056 astman_append(s, "\r\n"); 07057 } 07058 } 07059 if (!rinclude) { 07060 struct ast_sw *sw = NULL; 07061 while ( (sw = ast_walk_context_switches(c, sw)) ) { 07062 if (!dpc->total_items++) 07063 manager_dpsendack(s, m); 07064 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 07065 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)); 07066 astman_append(s, "\r\n"); 07067 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw)); 07068 } 07069 } 07070 07071 ast_unlock_context(c); 07072 } 07073 ast_unlock_contexts(); 07074 07075 if (dpc->total_exten == old_total_exten) { 07076 ast_debug(3, "manager_show_dialplan: Found nothing new\n"); 07077 /* Nothing new under the sun */ 07078 return -1; 07079 } else { 07080 return res; 07081 } 07082 }
static int matchcid | ( | const char * | cidpattern, | |
const char * | callerid | |||
) | [static] |
Definition at line 2926 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
02927 { 02928 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 02929 failing to get a number should count as a match, otherwise not */ 02930 02931 if (ast_strlen_zero(callerid)) { 02932 return ast_strlen_zero(cidpattern) ? 1 : 0; 02933 } 02934 02935 return ast_extension_match(cidpattern, callerid); 02936 }
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 1732 of file pbx.c.
References match_char::alt_char, ast_debug, ast_log(), scoreboard::canmatch, match_char::deleted, E_CANMATCH, E_MATCHMORE, ast_exten::exten, scoreboard::exten, match_char::exten, match_char::is_pattern, ast_exten::label, LOG_NOTICE, NEW_MATCHER_CHK_MATCH, NEW_MATCHER_RECURSE, match_char::next_char, match_char::specificity, update_scoreboard(), and match_char::x.
Referenced by pbx_find_extension().
01733 { 01734 struct match_char *p; /* note minimal stack storage requirements */ 01735 struct ast_exten pattern = { .label = label }; 01736 #ifdef DEBUG_THIS 01737 if (tree) 01738 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action)); 01739 else 01740 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action)); 01741 #endif 01742 for (p = tree; p; p = p->alt_char) { 01743 if (p->is_pattern) { 01744 if (p->x[0] == 'N') { 01745 if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) { 01746 #define NEW_MATCHER_CHK_MATCH \ 01747 if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */ \ 01748 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \ 01749 update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \ 01750 if (!p->deleted) { \ 01751 if (action == E_FINDLABEL) { \ 01752 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \ 01753 ast_debug(4, "Found label in preferred extension\n"); \ 01754 return; \ 01755 } \ 01756 } else { \ 01757 ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten); \ 01758 return; /* the first match, by definition, will be the best, because of the sorted tree */ \ 01759 } \ 01760 } \ 01761 } \ 01762 } 01763 01764 #define NEW_MATCHER_RECURSE \ 01765 if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \ 01766 || p->next_char->x[0] == '!')) { \ 01767 if (*(str + 1) || p->next_char->x[0] == '!') { \ 01768 new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01769 if (score->exten) { \ 01770 ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten); \ 01771 return; /* the first match is all we need */ \ 01772 } \ 01773 } else { \ 01774 new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01775 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \ 01776 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \ 01777 "NULL"); \ 01778 return; /* the first match is all we need */ \ 01779 } \ 01780 } \ 01781 } else if ((p->next_char || action == E_CANMATCH) && !*(str + 1)) { \ 01782 score->canmatch = 1; \ 01783 score->canmatch_exten = get_canmatch_exten(p); \ 01784 if (action == E_CANMATCH || action == E_MATCHMORE) { \ 01785 ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \ 01786 return; \ 01787 } \ 01788 } 01789 01790 NEW_MATCHER_CHK_MATCH; 01791 NEW_MATCHER_RECURSE; 01792 } 01793 } else if (p->x[0] == 'Z') { 01794 if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) { 01795 NEW_MATCHER_CHK_MATCH; 01796 NEW_MATCHER_RECURSE; 01797 } 01798 } else if (p->x[0] == 'X') { 01799 if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) { 01800 NEW_MATCHER_CHK_MATCH; 01801 NEW_MATCHER_RECURSE; 01802 } 01803 } else if (p->x[0] == '.' && p->x[1] == 0) { 01804 /* how many chars will the . match against? */ 01805 int i = 0; 01806 const char *str2 = str; 01807 while (*str2 && *str2 != '/') { 01808 str2++; 01809 i++; 01810 } 01811 if (p->exten && *str2 != '/') { 01812 update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p); 01813 if (score->exten) { 01814 ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten); 01815 return; /* the first match is all we need */ 01816 } 01817 } 01818 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01819 new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action); 01820 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01821 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL"); 01822 return; /* the first match is all we need */ 01823 } 01824 } 01825 } else if (p->x[0] == '!' && p->x[1] == 0) { 01826 /* how many chars will the . match against? */ 01827 int i = 1; 01828 const char *str2 = str; 01829 while (*str2 && *str2 != '/') { 01830 str2++; 01831 i++; 01832 } 01833 if (p->exten && *str2 != '/') { 01834 update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p); 01835 if (score->exten) { 01836 ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten); 01837 return; /* the first match is all we need */ 01838 } 01839 } 01840 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01841 new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action); 01842 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01843 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01844 return; /* the first match is all we need */ 01845 } 01846 } 01847 } else if (p->x[0] == '/' && p->x[1] == 0) { 01848 /* the pattern in the tree includes the cid match! */ 01849 if (p->next_char && callerid && *callerid) { 01850 new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action); 01851 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01852 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01853 return; /* the first match is all we need */ 01854 } 01855 } 01856 } else if (strchr(p->x, *str)) { 01857 ast_debug(4, "Nothing strange about this match\n"); 01858 NEW_MATCHER_CHK_MATCH; 01859 NEW_MATCHER_RECURSE; 01860 } 01861 } else if (strchr(p->x, *str)) { 01862 ast_debug(4, "Nothing strange about this match\n"); 01863 NEW_MATCHER_CHK_MATCH; 01864 NEW_MATCHER_RECURSE; 01865 } 01866 } 01867 ast_debug(4, "return at end of func\n"); 01868 }
static int parse_variable_name | ( | char * | var, | |
int * | offset, | |||
int * | length, | |||
int * | isfunc | |||
) | [static] |
extract offset:length from variable name.
Definition at line 3236 of file pbx.c.
Referenced by ast_str_retrieve_variable(), ast_str_substitute_variables_full(), and pbx_substitute_variables_helper_full().
03237 { 03238 int parens = 0; 03239 03240 *offset = 0; 03241 *length = INT_MAX; 03242 *isfunc = 0; 03243 for (; *var; var++) { 03244 if (*var == '(') { 03245 (*isfunc)++; 03246 parens++; 03247 } else if (*var == ')') { 03248 parens--; 03249 } else if (*var == ':' && parens == 0) { 03250 *var++ = '\0'; 03251 sscanf(var, "%30d:%30d", offset, length); 03252 return 1; /* offset:length valid */ 03253 } 03254 } 03255 return 0; 03256 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 10384 of file pbx.c.
References AST_LIST_REMOVE_HEAD, ast_rwlock_unlock, ast_rwlock_wrlock, ast_var_delete(), globals, and globalslock.
Referenced by handle_cli_dialplan_reload(), and reload().
10385 { 10386 struct ast_var_t *vardata; 10387 10388 ast_rwlock_wrlock(&globalslock); 10389 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 10390 ast_var_delete(vardata); 10391 ast_rwlock_unlock(&globalslock); 10392 }
const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
const char * | name | |||
) |
Return a pointer to the value of the corresponding channel variable.
const char *var; ast_channel_lock(chan); if ((var = pbx_builtin_getvar_helper(chan, "MYVAR"))) { var = ast_strdupa(var); } ast_channel_unlock(chan);
Definition at line 10148 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_rwlock_rdlock, ast_rwlock_unlock, ast_var_name(), ast_var_value(), globals, globalslock, and ast_channel::varshead.
Referenced by __ast_pbx_run(), _macro_exec(), _while_exec(), agentmonitoroutgoing_exec(), analog_call(), append_channel_vars(), array(), ast_bridge_call(), ast_bridge_timelimit(), ast_call_forward(), ast_channel_connected_line_macro(), ast_channel_redirecting_macro(), ast_eivr_getvariable(), ast_hangup(), ast_monitor_stop(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_run(), confbridge_exec(), create_dynamic_parkinglot(), crement_function_read(), dahdi_hangup(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_check(), feature_interpret(), find_by_mark(), find_conf_realtime(), findparkinglotname(), func_channel_read(), generic_fax_exec(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), meetme_menu_admin_extended(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_exec(), park_call_full(), park_space_reserve(), pbx_builtin_background(), pbx_builtin_gotoiftime(), queue_exec(), real_ctx(), receivefax_exec(), retrydial_exec(), ring_entry(), run_agi(), sendfax_exec(), set_config_flags(), set_local_info(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridge_vars(), and wait_for_answer().
10149 { 10150 struct ast_var_t *variables; 10151 const char *ret = NULL; 10152 int i; 10153 struct varshead *places[2] = { NULL, &globals }; 10154 10155 if (!name) 10156 return NULL; 10157 10158 if (chan) { 10159 ast_channel_lock(chan); 10160 places[0] = &chan->varshead; 10161 } 10162 10163 for (i = 0; i < 2; i++) { 10164 if (!places[i]) 10165 continue; 10166 if (places[i] == &globals) 10167 ast_rwlock_rdlock(&globalslock); 10168 AST_LIST_TRAVERSE(places[i], variables, entries) { 10169 if (!strcmp(name, ast_var_name(variables))) { 10170 ret = ast_var_value(variables); 10171 break; 10172 } 10173 } 10174 if (places[i] == &globals) 10175 ast_rwlock_unlock(&globalslock); 10176 if (ret) 10177 break; 10178 } 10179 10180 if (chan) 10181 ast_channel_unlock(chan); 10182 10183 return ret; 10184 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10406 of file pbx.c.
References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), and pbx_checkcondition().
10407 { 10408 char *condition, *branch1, *branch2, *branch; 10409 char *stringp; 10410 10411 if (ast_strlen_zero(data)) { 10412 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 10413 return 0; 10414 } 10415 10416 stringp = ast_strdupa(data); 10417 condition = strsep(&stringp,"?"); 10418 branch1 = strsep(&stringp,":"); 10419 branch2 = strsep(&stringp,""); 10420 branch = pbx_checkcondition(condition) ? branch1 : branch2; 10421 10422 if (ast_strlen_zero(branch)) { 10423 ast_debug(1, "Not taking any branch\n"); 10424 return 0; 10425 } 10426 10427 return pbx_builtin_goto(chan, branch); 10428 }
int pbx_builtin_importvar | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10344 of file pbx.c.
References ast_alloca, ast_channel_get_by_name(), ast_channel_unref, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), value, and VAR_BUF_SIZE.
10345 { 10346 char *name; 10347 char *value; 10348 char *channel; 10349 char tmp[VAR_BUF_SIZE]; 10350 static int deprecation_warning = 0; 10351 10352 if (ast_strlen_zero(data)) { 10353 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 10354 return 0; 10355 } 10356 tmp[0] = 0; 10357 if (!deprecation_warning) { 10358 ast_log(LOG_WARNING, "ImportVar is deprecated. Please use Set(varname=${IMPORT(channel,variable)}) instead.\n"); 10359 deprecation_warning = 1; 10360 } 10361 10362 value = ast_strdupa(data); 10363 name = strsep(&value,"="); 10364 channel = strsep(&value,","); 10365 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 10366 struct ast_channel *chan2 = ast_channel_get_by_name(channel); 10367 if (chan2) { 10368 char *s = ast_alloca(strlen(value) + 4); 10369 sprintf(s, "${%s}", value); 10370 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 10371 chan2 = ast_channel_unref(chan2); 10372 } 10373 pbx_builtin_setvar_helper(chan, name, tmp); 10374 } 10375 10376 return(0); 10377 }
static int pbx_builtin_incomplete | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 9669 of file pbx.c.
References __ast_answer(), ast_channel::_state, ast_check_hangup(), AST_CONTROL_INCOMPLETE, ast_indicate(), AST_PBX_INCOMPLETE, AST_STATE_UP, and ast_strlen_zero().
09670 { 09671 const char *options = data; 09672 int answer = 1; 09673 09674 /* Some channels can receive DTMF in unanswered state; some cannot */ 09675 if (!ast_strlen_zero(options) && strchr(options, 'n')) { 09676 answer = 0; 09677 } 09678 09679 /* If the channel is hungup, stop waiting */ 09680 if (ast_check_hangup(chan)) { 09681 return -1; 09682 } else if (chan->_state != AST_STATE_UP && answer) { 09683 __ast_answer(chan, 0, 1); 09684 } 09685 09686 ast_indicate(chan, AST_CONTROL_INCOMPLETE); 09687 09688 return AST_PBX_INCOMPLETE; 09689 }
static int pbx_builtin_noop | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
void pbx_builtin_pushvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Add a variable to the channel variable stack, without removing any previously set value.
Definition at line 10186 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, ast_log(), ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_verb, globals, globalslock, LOG_WARNING, and ast_channel::varshead.
Referenced by acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), and frame_set_var().
10187 { 10188 struct ast_var_t *newvariable; 10189 struct varshead *headp; 10190 10191 if (name[strlen(name)-1] == ')') { 10192 char *function = ast_strdupa(name); 10193 10194 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 10195 ast_func_write(chan, function, value); 10196 return; 10197 } 10198 10199 if (chan) { 10200 ast_channel_lock(chan); 10201 headp = &chan->varshead; 10202 } else { 10203 ast_rwlock_wrlock(&globalslock); 10204 headp = &globals; 10205 } 10206 10207 if (value) { 10208 if (headp == &globals) 10209 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10210 newvariable = ast_var_assign(name, value); 10211 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10212 } 10213 10214 if (chan) 10215 ast_channel_unlock(chan); 10216 else 10217 ast_rwlock_unlock(&globalslock); 10218 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
const char * | reason | |||
) |
Definition at line 3545 of file pbx.c.
References raise_exception().
03546 { 03547 /* Priority will become 1, next time through the AUTOLOOP */ 03548 return raise_exception(chan, reason, 0); 03549 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10467 of file pbx.c.
References ast_say_character_str().
10468 { 10469 int res = 0; 10470 10471 if (data) 10472 res = ast_say_character_str(chan, data, "", chan->language); 10473 return res; 10474 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10458 of file pbx.c.
References ast_say_digit_str().
10459 { 10460 int res = 0; 10461 10462 if (data) 10463 res = ast_say_digit_str(chan, data, "", chan->language); 10464 return res; 10465 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10430 of file pbx.c.
References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), and LOG_WARNING.
10431 { 10432 char tmp[256]; 10433 char *number = tmp; 10434 char *options; 10435 10436 if (ast_strlen_zero(data)) { 10437 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 10438 return -1; 10439 } 10440 ast_copy_string(tmp, data, sizeof(tmp)); 10441 strsep(&number, ","); 10442 options = strsep(&number, ","); 10443 if (options) { 10444 if ( strcasecmp(options, "f") && strcasecmp(options, "m") && 10445 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 10446 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 10447 return -1; 10448 } 10449 } 10450 10451 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 10452 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 10453 } 10454 10455 return 0; 10456 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 10476 of file pbx.c.
References ast_say_phonetic_str().
10477 { 10478 int res = 0; 10479 10480 if (data) 10481 res = ast_say_phonetic_str(chan, data, "", chan->language); 10482 return res; 10483 }
int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
struct ast_str ** | buf | |||
) |
Create a human-readable string, specifying all variables and their corresponding values.
chan | Channel from which to read variables | |
buf | Dynamic string in which to place the result (should be allocated with ast_str_create). |
Definition at line 10117 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_reset(), ast_var_name(), ast_var_value(), LOG_ERROR, total, var, and ast_channel::varshead.
Referenced by ast_var_channels_table(), dumpchan_exec(), handle_show_chanvar(), handle_showchan(), and vars2manager().
10118 { 10119 struct ast_var_t *variables; 10120 const char *var, *val; 10121 int total = 0; 10122 10123 if (!chan) 10124 return 0; 10125 10126 ast_str_reset(*buf); 10127 10128 ast_channel_lock(chan); 10129 10130 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 10131 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 10132 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 10133 ) { 10134 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 10135 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 10136 break; 10137 } else 10138 total++; 10139 } else 10140 break; 10141 } 10142 10143 ast_channel_unlock(chan); 10144 10145 return total; 10146 }
int pbx_builtin_setvar | ( | struct ast_channel * | chan, | |
const char * | data | |||
) |
Parse and set a single channel variable, where the name and value are separated with an '=' character.
Definition at line 10278 of file pbx.c.
References ast_compat_app_set, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_builtin_setvar_multiple(), and value.
Referenced by ast_compile_ael2().
10279 { 10280 char *name, *value, *mydata; 10281 10282 if (ast_compat_app_set) { 10283 return pbx_builtin_setvar_multiple(chan, data); 10284 } 10285 10286 if (ast_strlen_zero(data)) { 10287 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 10288 return 0; 10289 } 10290 10291 mydata = ast_strdupa(data); 10292 name = strsep(&mydata, "="); 10293 value = mydata; 10294 if (!value) { 10295 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 10296 return 0; 10297 } 10298 10299 if (strchr(name, ' ')) { 10300 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 10301 } 10302 10303 pbx_builtin_setvar_helper(chan, name, value); 10304 10305 return 0; 10306 }
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.
Definition at line 10220 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, and ast_channel::varshead.
Referenced by __analog_ss_thread(), __ast_pbx_run(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_helper(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), analog_ss_thread(), aqm_exec(), array(), ast_bridge_call(), ast_cc_agent_set_interfaces_chanvar(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_pickup_call(), ast_rtp_instance_set_stats_vars(), ast_set_cc_interfaces_chanvar(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), cccancel_exec(), ccreq_exec(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmf(), dahdi_new(), dial_exec_full(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parked_call(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), parked_call_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), receivefax_exec(), record_exec(), reload_module(), return_exec(), rollback_exec(), rotate_file(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), shift_pop(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), start_monitor_exec(), system_exec_helper(), testtime_write(), transfer_exec(), transmit(), tryexec_exec(), unshift_push(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().
10221 { 10222 struct ast_var_t *newvariable; 10223 struct varshead *headp; 10224 const char *nametail = name; 10225 10226 if (name[strlen(name) - 1] == ')') { 10227 char *function = ast_strdupa(name); 10228 10229 return ast_func_write(chan, function, value); 10230 } 10231 10232 if (chan) { 10233 ast_channel_lock(chan); 10234 headp = &chan->varshead; 10235 } else { 10236 ast_rwlock_wrlock(&globalslock); 10237 headp = &globals; 10238 } 10239 10240 /* For comparison purposes, we have to strip leading underscores */ 10241 if (*nametail == '_') { 10242 nametail++; 10243 if (*nametail == '_') 10244 nametail++; 10245 } 10246 10247 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 10248 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 10249 /* there is already such a variable, delete it */ 10250 AST_LIST_REMOVE_CURRENT(entries); 10251 ast_var_delete(newvariable); 10252 break; 10253 } 10254 } 10255 AST_LIST_TRAVERSE_SAFE_END; 10256 10257 if (value) { 10258 if (headp == &globals) 10259 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10260 newvariable = ast_var_assign(name, value); 10261 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10262 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 10263 "Channel: %s\r\n" 10264 "Variable: %s\r\n" 10265 "Value: %s\r\n" 10266 "Uniqueid: %s\r\n", 10267 chan ? chan->name : "none", name, value, 10268 chan ? chan->uniqueid : "none"); 10269 } 10270 10271 if (chan) 10272 ast_channel_unlock(chan); 10273 else 10274 ast_rwlock_unlock(&globalslock); 10275 return 0; 10276 }
int pbx_builtin_setvar_multiple | ( | struct ast_channel * | chan, | |
const char * | data | |||
) |
Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
Definition at line 10308 of file pbx.c.
References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_channel::context, ast_channel::exten, LOG_WARNING, pbx_builtin_setvar_helper(), ast_channel::priority, and value.
Referenced by pbx_builtin_setvar(), queue_function_var(), set_queue_variables(), and try_calling().
10309 { 10310 char *data; 10311 int x; 10312 AST_DECLARE_APP_ARGS(args, 10313 AST_APP_ARG(pair)[24]; 10314 ); 10315 AST_DECLARE_APP_ARGS(pair, 10316 AST_APP_ARG(name); 10317 AST_APP_ARG(value); 10318 ); 10319 10320 if (ast_strlen_zero(vdata)) { 10321 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 10322 return 0; 10323 } 10324 10325 data = ast_strdupa(vdata); 10326 AST_STANDARD_APP_ARGS(args, data); 10327 10328 for (x = 0; x < args.argc; x++) { 10329 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 10330 if (pair.argc == 2) { 10331 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 10332 if (strchr(pair.name, ' ')) 10333 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", pair.name, pair.value); 10334 } else if (!chan) { 10335 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 10336 } else { 10337 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 10338 } 10339 } 10340 10341 return 0; 10342 }
int pbx_checkcondition | ( | const char * | condition | ) |
Evaluate a condition.
0 | if the condition is NULL or of zero length | |
int | If the string is an integer, the integer representation of the integer is returned | |
1 | Any other non-empty string |
Definition at line 10394 of file pbx.c.
References ast_strlen_zero().
Referenced by _macro_exec(), _while_exec(), acf_if(), execif_exec(), gosubif_exec(), macroif_exec(), pbx_builtin_gotoif(), and testtime_write().
10395 { 10396 int res; 10397 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 10398 return 0; 10399 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 10400 return res; 10401 } else { /* Strings are true */ 10402 return 1; 10403 } 10404 }
static void pbx_destroy | ( | struct ast_pbx * | p | ) | [static] |
Definition at line 1498 of file pbx.c.
References ast_free.
Referenced by __ast_pbx_run().
01499 { 01500 ast_free(p); 01501 }
int pbx_exec | ( | struct ast_channel * | c, | |
struct ast_app * | app, | |||
const char * | data | |||
) |
Execute an application.
c | channel to execute on | |
app | which app to execute | |
data | the data passed into the app |
This application executes an application on a given channel. It saves the stack and executes the given application passing in the given data.
0 | success | |
-1 | failure |
c | Channel | |
app | Application | |
data | Data for execution |
Definition at line 1418 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_channel::appl, ast_cdr_setapp(), AST_CEL_APP_END, AST_CEL_APP_START, ast_cel_report_event(), ast_check_hangup(), ast_log(), ast_opt_dont_warn, ast_strlen_zero(), ast_channel::cdr, ast_channel::data, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, and S_OR.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01421 { 01422 int res; 01423 struct ast_module_user *u = NULL; 01424 const char *saved_c_appl; 01425 const char *saved_c_data; 01426 01427 if (c->cdr && !ast_check_hangup(c)) 01428 ast_cdr_setapp(c->cdr, app->name, data); 01429 01430 /* save channel values */ 01431 saved_c_appl= c->appl; 01432 saved_c_data= c->data; 01433 01434 c->appl = app->name; 01435 c->data = data; 01436 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01437 01438 if (app->module) 01439 u = __ast_module_user_add(app->module, c); 01440 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01441 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01442 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01443 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01444 app->name, (char *) data); 01445 } 01446 res = app->execute(c, S_OR(data, "")); 01447 if (app->module && u) 01448 __ast_module_user_remove(app->module, u); 01449 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01450 /* restore channel values */ 01451 c->appl = saved_c_appl; 01452 c->data = saved_c_data; 01453 return res; 01454 }
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,
0 | on success. | |
-1 | on failure. |
Definition at line 4425 of file pbx.c.
References ast_exten::app, app, ast_copy_string(), ast_debug, ast_log(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_verb, ast_exten::cached_app, COLOR_BRCYAN, COLOR_BRMAGENTA, ast_channel::context, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCH, E_MATCHMORE, EVENT_FLAG_DIALPLAN, ast_switch::exec, EXT_DATA_SIZE, ast_channel::exten, pbx_find_info::foundcontext, LOG_NOTICE, LOG_WARNING, manager_event, ast_switch::name, ast_app::name, pbx_exec(), pbx_find_extension(), pbx_findapp(), pbx_substitute_variables(), ast_channel::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, term_color(), and VERBOSITY_ATLEAST.
Referenced by ast_canmatch_extension(), ast_exists_extension(), ast_findlabel_extension(), ast_findlabel_extension2(), ast_matchmore_extension(), and ast_spawn_extension().
04428 { 04429 struct ast_exten *e; 04430 struct ast_app *app; 04431 int res; 04432 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 04433 char passdata[EXT_DATA_SIZE]; 04434 04435 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 04436 04437 ast_rdlock_contexts(); 04438 if (found) 04439 *found = 0; 04440 04441 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 04442 if (e) { 04443 if (found) 04444 *found = 1; 04445 if (matching_action) { 04446 ast_unlock_contexts(); 04447 return -1; /* success, we found it */ 04448 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 04449 res = e->priority; 04450 ast_unlock_contexts(); 04451 return res; /* the priority we were looking for */ 04452 } else { /* spawn */ 04453 if (!e->cached_app) 04454 e->cached_app = pbx_findapp(e->app); 04455 app = e->cached_app; 04456 ast_unlock_contexts(); 04457 if (!app) { 04458 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 04459 return -1; 04460 } 04461 if (c->context != context) 04462 ast_copy_string(c->context, context, sizeof(c->context)); 04463 if (c->exten != exten) 04464 ast_copy_string(c->exten, exten, sizeof(c->exten)); 04465 c->priority = priority; 04466 pbx_substitute_variables(passdata, sizeof(passdata), c, e); 04467 #ifdef CHANNEL_TRACE 04468 ast_channel_trace_update(c); 04469 #endif 04470 ast_debug(1, "Launching '%s'\n", app->name); 04471 if (VERBOSITY_ATLEAST(3)) { 04472 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 04473 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 04474 exten, context, priority, 04475 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 04476 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 04477 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 04478 "in new stack"); 04479 } 04480 manager_event(EVENT_FLAG_DIALPLAN, "Newexten", 04481 "Channel: %s\r\n" 04482 "Context: %s\r\n" 04483 "Extension: %s\r\n" 04484 "Priority: %d\r\n" 04485 "Application: %s\r\n" 04486 "AppData: %s\r\n" 04487 "Uniqueid: %s\r\n", 04488 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 04489 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 04490 } 04491 } else if (q.swo) { /* not found here, but in another switch */ 04492 if (found) 04493 *found = 1; 04494 ast_unlock_contexts(); 04495 if (matching_action) { 04496 return -1; 04497 } else { 04498 if (!q.swo->exec) { 04499 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 04500 res = -1; 04501 } 04502 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 04503 } 04504 } else { /* not found anywhere, see what happened */ 04505 ast_unlock_contexts(); 04506 /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */ 04507 switch (q.status) { 04508 case STATUS_NO_CONTEXT: 04509 if (!matching_action && !combined_find_spawn) 04510 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, "")); 04511 break; 04512 case STATUS_NO_EXTENSION: 04513 if (!matching_action && !combined_find_spawn) 04514 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, "")); 04515 break; 04516 case STATUS_NO_PRIORITY: 04517 if (!matching_action && !combined_find_spawn) 04518 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, "")); 04519 break; 04520 case STATUS_NO_LABEL: 04521 if (context && !combined_find_spawn) 04522 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, "")); 04523 break; 04524 default: 04525 ast_debug(1, "Shouldn't happen!\n"); 04526 } 04527 04528 return (matching_action) ? 0 : -1; 04529 } 04530 }
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 | |||
) | [read] |
Definition at line 2938 of file pbx.c.
References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, 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(), ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, scoreboard::exten, extenpatternmatchnew, extension_match_core(), find_context(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_context::name, ast_sw::name, new_find_extension(), ast_include::next, scoreboard::node, overrideswitch, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, 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, switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().
Referenced by ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), check_goto(), check_pval_item(), get_parking_exten(), pbx_extension_helper(), pbx_find_extension(), register_peer_exten(), and remove_exten_if_exist().
02942 { 02943 int x, res; 02944 struct ast_context *tmp = NULL; 02945 struct ast_exten *e = NULL, *eroot = NULL; 02946 struct ast_include *i = NULL; 02947 struct ast_sw *sw = NULL; 02948 struct ast_exten pattern = {NULL, }; 02949 struct scoreboard score = {0, }; 02950 struct ast_str *tmpdata = NULL; 02951 02952 pattern.label = label; 02953 pattern.priority = priority; 02954 #ifdef NEED_DEBUG_HERE 02955 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02956 #endif 02957 02958 /* Initialize status if appropriate */ 02959 if (q->stacklen == 0) { 02960 q->status = STATUS_NO_CONTEXT; 02961 q->swo = NULL; 02962 q->data = NULL; 02963 q->foundcontext = NULL; 02964 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02965 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02966 return NULL; 02967 } 02968 02969 /* Check first to see if we've already been checked */ 02970 for (x = 0; x < q->stacklen; x++) { 02971 if (!strcasecmp(q->incstack[x], context)) 02972 return NULL; 02973 } 02974 02975 if (bypass) { /* bypass means we only look there */ 02976 tmp = bypass; 02977 } else { /* look in contexts */ 02978 tmp = find_context(context); 02979 if (!tmp) { 02980 return NULL; 02981 } 02982 } 02983 02984 if (q->status < STATUS_NO_EXTENSION) 02985 q->status = STATUS_NO_EXTENSION; 02986 02987 /* Do a search for matching extension */ 02988 02989 eroot = NULL; 02990 score.total_specificity = 0; 02991 score.exten = 0; 02992 score.total_length = 0; 02993 if (!tmp->pattern_tree && tmp->root_table) { 02994 create_match_char_tree(tmp); 02995 #ifdef NEED_DEBUG 02996 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 02997 log_match_char_tree(tmp->pattern_tree," "); 02998 #endif 02999 } 03000 #ifdef NEED_DEBUG 03001 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 03002 log_match_char_tree(tmp->pattern_tree, ":: "); 03003 #endif 03004 03005 do { 03006 if (!ast_strlen_zero(overrideswitch)) { 03007 char *osw = ast_strdupa(overrideswitch), *name; 03008 struct ast_switch *asw; 03009 ast_switch_f *aswf = NULL; 03010 char *datap; 03011 int eval = 0; 03012 03013 name = strsep(&osw, "/"); 03014 asw = pbx_findswitch(name); 03015 03016 if (!asw) { 03017 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 03018 break; 03019 } 03020 03021 if (osw && strchr(osw, '$')) { 03022 eval = 1; 03023 } 03024 03025 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03026 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n"); 03027 break; 03028 } else if (eval) { 03029 /* Substitute variables now */ 03030 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03031 datap = ast_str_buffer(tmpdata); 03032 } else { 03033 datap = osw; 03034 } 03035 03036 /* equivalent of extension_match_core() at the switch level */ 03037 if (action == E_CANMATCH) 03038 aswf = asw->canmatch; 03039 else if (action == E_MATCHMORE) 03040 aswf = asw->matchmore; 03041 else /* action == E_MATCH */ 03042 aswf = asw->exists; 03043 if (!aswf) { 03044 res = 0; 03045 } else { 03046 if (chan) { 03047 ast_autoservice_start(chan); 03048 } 03049 res = aswf(chan, context, exten, priority, callerid, datap); 03050 if (chan) { 03051 ast_autoservice_stop(chan); 03052 } 03053 } 03054 if (res) { /* Got a match */ 03055 q->swo = asw; 03056 q->data = datap; 03057 q->foundcontext = context; 03058 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03059 return NULL; 03060 } 03061 } 03062 } while (0); 03063 03064 if (extenpatternmatchnew) { 03065 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 03066 eroot = score.exten; 03067 03068 if (score.last_char == '!' && action == E_MATCHMORE) { 03069 /* We match an extension ending in '!'. 03070 * The decision in this case is final and is NULL (no match). 03071 */ 03072 #ifdef NEED_DEBUG_HERE 03073 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 03074 #endif 03075 return NULL; 03076 } 03077 03078 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 03079 q->status = STATUS_SUCCESS; 03080 #ifdef NEED_DEBUG_HERE 03081 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 03082 #endif 03083 return score.canmatch_exten; 03084 } 03085 03086 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 03087 if (score.node) { 03088 struct ast_exten *z = trie_find_next_match(score.node); 03089 if (z) { 03090 #ifdef NEED_DEBUG_HERE 03091 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 03092 #endif 03093 } else { 03094 if (score.canmatch_exten) { 03095 #ifdef NEED_DEBUG_HERE 03096 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 03097 #endif 03098 return score.canmatch_exten; 03099 } else { 03100 #ifdef NEED_DEBUG_HERE 03101 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 03102 #endif 03103 } 03104 } 03105 return z; 03106 } 03107 #ifdef NEED_DEBUG_HERE 03108 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 03109 #endif 03110 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 03111 } 03112 03113 if (eroot) { 03114 /* found entry, now look for the right priority */ 03115 if (q->status < STATUS_NO_PRIORITY) 03116 q->status = STATUS_NO_PRIORITY; 03117 e = NULL; 03118 if (action == E_FINDLABEL && label ) { 03119 if (q->status < STATUS_NO_LABEL) 03120 q->status = STATUS_NO_LABEL; 03121 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03122 } else { 03123 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03124 } 03125 if (e) { /* found a valid match */ 03126 q->status = STATUS_SUCCESS; 03127 q->foundcontext = context; 03128 #ifdef NEED_DEBUG_HERE 03129 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 03130 #endif 03131 return e; 03132 } 03133 } 03134 } else { /* the old/current default exten pattern match algorithm */ 03135 03136 /* scan the list trying to match extension and CID */ 03137 eroot = NULL; 03138 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 03139 int match = extension_match_core(eroot->exten, exten, action); 03140 /* 0 on fail, 1 on match, 2 on earlymatch */ 03141 03142 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 03143 continue; /* keep trying */ 03144 if (match == 2 && action == E_MATCHMORE) { 03145 /* We match an extension ending in '!'. 03146 * The decision in this case is final and is NULL (no match). 03147 */ 03148 return NULL; 03149 } 03150 /* found entry, now look for the right priority */ 03151 if (q->status < STATUS_NO_PRIORITY) 03152 q->status = STATUS_NO_PRIORITY; 03153 e = NULL; 03154 if (action == E_FINDLABEL && label ) { 03155 if (q->status < STATUS_NO_LABEL) 03156 q->status = STATUS_NO_LABEL; 03157 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03158 } else { 03159 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03160 } 03161 if (e) { /* found a valid match */ 03162 q->status = STATUS_SUCCESS; 03163 q->foundcontext = context; 03164 return e; 03165 } 03166 } 03167 } 03168 03169 /* Check alternative switches */ 03170 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 03171 struct ast_switch *asw = pbx_findswitch(sw->name); 03172 ast_switch_f *aswf = NULL; 03173 char *datap; 03174 03175 if (!asw) { 03176 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 03177 continue; 03178 } 03179 03180 /* Substitute variables now */ 03181 if (sw->eval) { 03182 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03183 ast_log(LOG_WARNING, "Can't evaluate switch?!\n"); 03184 continue; 03185 } 03186 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03187 } 03188 03189 /* equivalent of extension_match_core() at the switch level */ 03190 if (action == E_CANMATCH) 03191 aswf = asw->canmatch; 03192 else if (action == E_MATCHMORE) 03193 aswf = asw->matchmore; 03194 else /* action == E_MATCH */ 03195 aswf = asw->exists; 03196 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 03197 if (!aswf) 03198 res = 0; 03199 else { 03200 if (chan) 03201 ast_autoservice_start(chan); 03202 res = aswf(chan, context, exten, priority, callerid, datap); 03203 if (chan) 03204 ast_autoservice_stop(chan); 03205 } 03206 if (res) { /* Got a match */ 03207 q->swo = asw; 03208 q->data = datap; 03209 q->foundcontext = context; 03210 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03211 return NULL; 03212 } 03213 } 03214 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 03215 /* Now try any includes we have in this context */ 03216 for (i = tmp->includes; i; i = i->next) { 03217 if (include_valid(i)) { 03218 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 03219 #ifdef NEED_DEBUG_HERE 03220 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 03221 #endif 03222 return e; 03223 } 03224 if (q->swo) 03225 return NULL; 03226 } 03227 } 03228 return NULL; 03229 }
struct ast_app* pbx_findapp | ( | const char * | app | ) | [read] |
Find application handle in linked list.
Look up an application.
Definition at line 1462 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_app::name.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), try_calling(), and tryexec_exec().
01463 { 01464 struct ast_app *tmp; 01465 01466 AST_RWLIST_RDLOCK(&apps); 01467 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01468 if (!strcasecmp(tmp->name, app)) 01469 break; 01470 } 01471 AST_RWLIST_UNLOCK(&apps); 01472 01473 return tmp; 01474 }
static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static, read] |
Definition at line 1476 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_switch::name.
Referenced by pbx_find_extension().
01477 { 01478 struct ast_switch *asw; 01479 01480 AST_RWLIST_RDLOCK(&switches); 01481 AST_RWLIST_TRAVERSE(&switches, asw, list) { 01482 if (!strcasecmp(asw->name, sw)) 01483 break; 01484 } 01485 AST_RWLIST_UNLOCK(&switches); 01486 01487 return asw; 01488 }
static int pbx_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string, | |||
int | async | |||
) | [static] |
Definition at line 10851 of file pbx.c.
References ast_async_goto(), ast_explicit_goto(), ast_findlabel_extension(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_channel::caller, ast_channel::context, ast_channel::exten, ast_party_caller::id, LOG_WARNING, ast_party_id::number, ast_channel::priority, S_COR, ast_party_number::str, and ast_party_number::valid.
Referenced by ast_async_parseable_goto(), and ast_parseable_goto().
10852 { 10853 char *exten, *pri, *context; 10854 char *stringp; 10855 int ipri; 10856 int mode = 0; 10857 10858 if (ast_strlen_zero(goto_string)) { 10859 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n"); 10860 return -1; 10861 } 10862 stringp = ast_strdupa(goto_string); 10863 context = strsep(&stringp, ","); /* guaranteed non-null */ 10864 exten = strsep(&stringp, ","); 10865 pri = strsep(&stringp, ","); 10866 if (!exten) { /* Only a priority in this one */ 10867 pri = context; 10868 exten = NULL; 10869 context = NULL; 10870 } else if (!pri) { /* Only an extension and priority in this one */ 10871 pri = exten; 10872 exten = context; 10873 context = NULL; 10874 } 10875 if (*pri == '+') { 10876 mode = 1; 10877 pri++; 10878 } else if (*pri == '-') { 10879 mode = -1; 10880 pri++; 10881 } 10882 if (sscanf(pri, "%30d", &ipri) != 1) { 10883 ipri = ast_findlabel_extension(chan, context ? context : chan->context, 10884 exten ? exten : chan->exten, pri, 10885 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)); 10886 if (ipri < 1) { 10887 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 10888 return -1; 10889 } else 10890 mode = 0; 10891 } 10892 /* At this point we have a priority and maybe an extension and a context */ 10893 10894 if (mode) 10895 ipri = chan->priority + (ipri * mode); 10896 10897 if (async) 10898 ast_async_goto(chan, context, exten, ipri); 10899 else 10900 ast_explicit_goto(chan, context, exten, ipri); 10901 10902 return 0; 10903 10904 }
void pbx_retrieve_variable | ( | struct ast_channel * | c, | |
const char * | var, | |||
char ** | ret, | |||
char * | workspace, | |||
int | workspacelen, | |||
struct varshead * | headp | |||
) |
Support for Asterisk built-in variables in the dialplan.
Retrieve the value of a builtin variable or variable from the channel variable stack.
Definition at line 3359 of file pbx.c.
References ast_copy_string(), ast_free, ast_str_buffer(), ast_str_create(), ast_str_retrieve_variable(), and str.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
03360 { 03361 struct ast_str *str = ast_str_create(16); 03362 const char *cret; 03363 03364 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 03365 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 03366 *ret = cret ? workspace : NULL; 03367 ast_free(str); 03368 }
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 5641 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05642 { 05643 int oldval = autofallthrough; 05644 autofallthrough = newval; 05645 return oldval; 05646 }
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 5648 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05649 { 05650 int oldval = extenpatternmatchnew; 05651 extenpatternmatchnew = newval; 05652 return oldval; 05653 }
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.
Definition at line 5655 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05656 { 05657 if (overrideswitch) { 05658 ast_free(overrideswitch); 05659 } 05660 if (!ast_strlen_zero(newval)) { 05661 overrideswitch = ast_strdup(newval); 05662 } else { 05663 overrideswitch = NULL; 05664 } 05665 }
static void pbx_shutdown | ( | void | ) | [static] |
static void pbx_substitute_variables | ( | char * | passdata, | |
int | datalen, | |||
struct ast_channel * | c, | |||
struct ast_exten * | e | |||
) | [static] |
Definition at line 4388 of file pbx.c.
References ast_copy_string(), ast_exten::data, and pbx_substitute_variables_helper().
Referenced by pbx_extension_helper().
04389 { 04390 const char *tmp; 04391 04392 /* Nothing more to do */ 04393 if (!e->data) { 04394 *passdata = '\0'; 04395 return; 04396 } 04397 04398 /* No variables or expressions in e->data, so why scan it? */ 04399 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) { 04400 ast_copy_string(passdata, e->data, datalen); 04401 return; 04402 } 04403 04404 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1); 04405 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4376 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by add_extensions(), ast_add_extension2_lockopt(), function_eval(), get_manager_event_info(), get_mapping_weight(), import_helper(), launch_monitor_thread(), manager_log(), pbx_builtin_importvar(), pbx_find_extension(), pbx_load_config(), pbx_substitute_variables(), realtime_exec(), rotate_file(), substituted(), try_calling(), and write_cdr().
04377 { 04378 size_t used; 04379 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 04380 }
void pbx_substitute_variables_helper_full | ( | struct ast_channel * | c, | |
struct varshead * | headp, | |||
const char * | cp1, | |||
char * | cp2, | |||
int | count, | |||
size_t * | used | |||
) |
Definition at line 4180 of file pbx.c.
References ast_alloca, ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc, ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full(), substring(), var, VAR_BUF_SIZE, and ast_channel::varshead.
Referenced by pbx_substitute_variables_helper(), pbx_substitute_variables_helper_full(), and pbx_substitute_variables_varshead().
04181 { 04182 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 04183 char *cp4 = NULL; 04184 const char *tmp, *whereweare, *orig_cp2 = cp2; 04185 int length, offset, offset2, isfunction; 04186 char *workspace = NULL; 04187 char *ltmp = NULL, *var = NULL; 04188 char *nextvar, *nextexp, *nextthing; 04189 char *vars, *vare; 04190 int pos, brackets, needsub, len; 04191 04192 *cp2 = 0; /* just in case nothing ends up there */ 04193 whereweare=tmp=cp1; 04194 while (!ast_strlen_zero(whereweare) && count) { 04195 /* Assume we're copying the whole remaining string */ 04196 pos = strlen(whereweare); 04197 nextvar = NULL; 04198 nextexp = NULL; 04199 nextthing = strchr(whereweare, '$'); 04200 if (nextthing) { 04201 switch (nextthing[1]) { 04202 case '{': 04203 nextvar = nextthing; 04204 pos = nextvar - whereweare; 04205 break; 04206 case '[': 04207 nextexp = nextthing; 04208 pos = nextexp - whereweare; 04209 break; 04210 default: 04211 pos = 1; 04212 } 04213 } 04214 04215 if (pos) { 04216 /* Can't copy more than 'count' bytes */ 04217 if (pos > count) 04218 pos = count; 04219 04220 /* Copy that many bytes */ 04221 memcpy(cp2, whereweare, pos); 04222 04223 count -= pos; 04224 cp2 += pos; 04225 whereweare += pos; 04226 *cp2 = 0; 04227 } 04228 04229 if (nextvar) { 04230 /* We have a variable. Find the start and end, and determine 04231 if we are going to have to recursively call ourselves on the 04232 contents */ 04233 vars = vare = nextvar + 2; 04234 brackets = 1; 04235 needsub = 0; 04236 04237 /* Find the end of it */ 04238 while (brackets && *vare) { 04239 if ((vare[0] == '$') && (vare[1] == '{')) { 04240 needsub++; 04241 } else if (vare[0] == '{') { 04242 brackets++; 04243 } else if (vare[0] == '}') { 04244 brackets--; 04245 } else if ((vare[0] == '$') && (vare[1] == '[')) 04246 needsub++; 04247 vare++; 04248 } 04249 if (brackets) 04250 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04251 len = vare - vars - 1; 04252 04253 /* Skip totally over variable string */ 04254 whereweare += (len + 3); 04255 04256 if (!var) 04257 var = ast_alloca(VAR_BUF_SIZE); 04258 04259 /* Store variable name (and truncate) */ 04260 ast_copy_string(var, vars, len + 1); 04261 04262 /* Substitute if necessary */ 04263 if (needsub) { 04264 size_t used; 04265 if (!ltmp) 04266 ltmp = ast_alloca(VAR_BUF_SIZE); 04267 04268 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04269 vars = ltmp; 04270 } else { 04271 vars = var; 04272 } 04273 04274 if (!workspace) 04275 workspace = ast_alloca(VAR_BUF_SIZE); 04276 04277 workspace[0] = '\0'; 04278 04279 parse_variable_name(vars, &offset, &offset2, &isfunction); 04280 if (isfunction) { 04281 /* Evaluate function */ 04282 if (c || !headp) 04283 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04284 else { 04285 struct varshead old; 04286 struct ast_channel *c = ast_dummy_channel_alloc(); 04287 if (c) { 04288 memcpy(&old, &c->varshead, sizeof(old)); 04289 memcpy(&c->varshead, headp, sizeof(c->varshead)); 04290 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04291 /* Don't deallocate the varshead that was passed in */ 04292 memcpy(&c->varshead, &old, sizeof(c->varshead)); 04293 c = ast_channel_unref(c); 04294 } else { 04295 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04296 } 04297 } 04298 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 04299 } else { 04300 /* Retrieve variable value */ 04301 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 04302 } 04303 if (cp4) { 04304 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 04305 04306 length = strlen(cp4); 04307 if (length > count) 04308 length = count; 04309 memcpy(cp2, cp4, length); 04310 count -= length; 04311 cp2 += length; 04312 *cp2 = 0; 04313 } 04314 } else if (nextexp) { 04315 /* We have an expression. Find the start and end, and determine 04316 if we are going to have to recursively call ourselves on the 04317 contents */ 04318 vars = vare = nextexp + 2; 04319 brackets = 1; 04320 needsub = 0; 04321 04322 /* Find the end of it */ 04323 while (brackets && *vare) { 04324 if ((vare[0] == '$') && (vare[1] == '[')) { 04325 needsub++; 04326 brackets++; 04327 vare++; 04328 } else if (vare[0] == '[') { 04329 brackets++; 04330 } else if (vare[0] == ']') { 04331 brackets--; 04332 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04333 needsub++; 04334 vare++; 04335 } 04336 vare++; 04337 } 04338 if (brackets) 04339 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04340 len = vare - vars - 1; 04341 04342 /* Skip totally over expression */ 04343 whereweare += (len + 3); 04344 04345 if (!var) 04346 var = ast_alloca(VAR_BUF_SIZE); 04347 04348 /* Store variable name (and truncate) */ 04349 ast_copy_string(var, vars, len + 1); 04350 04351 /* Substitute if necessary */ 04352 if (needsub) { 04353 size_t used; 04354 if (!ltmp) 04355 ltmp = ast_alloca(VAR_BUF_SIZE); 04356 04357 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04358 vars = ltmp; 04359 } else { 04360 vars = var; 04361 } 04362 04363 length = ast_expr(vars, cp2, count, c); 04364 04365 if (length) { 04366 ast_debug(1, "Expression result is '%s'\n", cp2); 04367 count -= length; 04368 cp2 += length; 04369 *cp2 = 0; 04370 } 04371 } 04372 } 04373 *used = cp2 - orig_cp2; 04374 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4382 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by do_say(), dundi_lookup_local(), and loopback_subst().
04383 { 04384 size_t used; 04385 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 04386 }
static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 5559 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
05560 { 05561 /* Oh joyeous kernel, we're a new thread, with nothing to do but 05562 answer this channel and get it going. 05563 */ 05564 /* NOTE: 05565 The launcher of this function _MUST_ increment 'countcalls' 05566 before invoking the function; it will be decremented when the 05567 PBX has finished running on the channel 05568 */ 05569 struct ast_channel *c = data; 05570 05571 __ast_pbx_run(c, NULL); 05572 decrease_call_count(); 05573 05574 pthread_exit(NULL); 05575 05576 return NULL; 05577 }
static void print_app_docs | ( | struct ast_app * | aa, | |
int | fd | |||
) | [static] |
Definition at line 6171 of file pbx.c.
References ast_app::arguments, ast_cli(), ast_free, ast_malloc, AST_MAX_APP, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, ast_xmldoc_printable(), COLOR_CYAN, COLOR_MAGENTA, ast_app::description, ast_switch::description, ast_app::docsrc, ast_app::name, S_OR, ast_app::seealso, ast_app::synopsis, synopsis, ast_app::syntax, and term_color().
Referenced by handle_show_application().
06172 { 06173 /* Maximum number of characters added by terminal coloring is 22 */ 06174 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40]; 06175 char seealsotitle[40]; 06176 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL; 06177 char *seealso = NULL; 06178 int syntax_size, synopsis_size, description_size, arguments_size, seealso_size; 06179 06180 snprintf(info, sizeof(info), "\n -= Info about application '%s' =- \n\n", aa->name); 06181 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 06182 06183 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 06184 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 06185 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 06186 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 06187 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 06188 06189 #ifdef AST_XML_DOCS 06190 if (aa->docsrc == AST_XML_DOC) { 06191 description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1); 06192 arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1); 06193 synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1); 06194 seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1); 06195 06196 if (!synopsis || !description || !arguments || !seealso) { 06197 goto return_cleanup; 06198 } 06199 } else 06200 #endif 06201 { 06202 synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06203 synopsis = ast_malloc(synopsis_size); 06204 06205 description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06206 description = ast_malloc(description_size); 06207 06208 arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06209 arguments = ast_malloc(arguments_size); 06210 06211 seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06212 seealso = ast_malloc(seealso_size); 06213 06214 if (!synopsis || !description || !arguments || !seealso) { 06215 goto return_cleanup; 06216 } 06217 06218 term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 06219 term_color(description, S_OR(aa->description, "Not available"), COLOR_CYAN, 0, description_size); 06220 term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 06221 term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 06222 } 06223 06224 /* Handle the syntax the same for both XML and raw docs */ 06225 syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06226 if (!(syntax = ast_malloc(syntax_size))) { 06227 goto return_cleanup; 06228 } 06229 term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 06230 06231 ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 06232 infotitle, syntitle, synopsis, destitle, description, 06233 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 06234 06235 return_cleanup: 06236 ast_free(description); 06237 ast_free(arguments); 06238 ast_free(synopsis); 06239 ast_free(seealso); 06240 ast_free(syntax); 06241 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 6597 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), ast_get_extension_priority(), ast_strlen_zero(), and PRIORITY_HINT.
Referenced by show_dialplan_helper().
06598 { 06599 int prio = ast_get_extension_priority(e); 06600 if (prio == PRIORITY_HINT) { 06601 snprintf(buf, buflen, "hint: %s", 06602 ast_get_extension_app(e)); 06603 } else { 06604 snprintf(buf, buflen, "%d. %s(%s)", 06605 prio, ast_get_extension_app(e), 06606 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 06607 } 06608 }
static int raise_exception | ( | struct ast_channel * | chan, | |
const char * | reason, | |||
int | priority | |||
) | [static] |
Definition at line 3519 of file pbx.c.
References ast_calloc_with_stringfields, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), ast_string_field_set, ast_channel::context, ast_datastore::data, exception_store_info, ast_channel::exten, exten, ast_channel::priority, pbx_exception::priority, and set_ext_pri().
Referenced by __ast_pbx_run(), pbx_builtin_raise_exception(), and pbx_builtin_waitexten().
03520 { 03521 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03522 struct pbx_exception *exception = NULL; 03523 03524 if (!ds) { 03525 ds = ast_datastore_alloc(&exception_store_info, NULL); 03526 if (!ds) 03527 return -1; 03528 if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) { 03529 ast_datastore_free(ds); 03530 return -1; 03531 } 03532 ds->data = exception; 03533 ast_channel_datastore_add(chan, ds); 03534 } else 03535 exception = ds->data; 03536 03537 ast_string_field_set(exception, reason, reason); 03538 ast_string_field_set(exception, context, chan->context); 03539 ast_string_field_set(exception, exten, chan->exten); 03540 exception->priority = chan->priority; 03541 set_ext_pri(chan, "e", priority); 03542 return 0; 03543 }
static void set_ext_pri | ( | struct ast_channel * | c, | |
const char * | exten, | |||
int | pri | |||
) | [static] |
helper function to set extension and priority
Definition at line 5131 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_channel::exten, and ast_channel::priority.
Referenced by __ast_pbx_run(), ast_pbx_outgoing_exten(), pbx_builtin_waitexten(), and raise_exception().
05132 { 05133 ast_channel_lock(c); 05134 ast_copy_string(c->exten, exten, sizeof(c->exten)); 05135 c->priority = pri; 05136 ast_channel_unlock(c); 05137 }
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 6762 of file pbx.c.
References ast_cli(), ast_exists_extension(), ast_get_context_name(), ast_get_context_registrar(), ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_contexts(), cli_match_char_tree(), dialplan_counters::context_existence, ast_context::name, ast_context::pattern_tree, dialplan_counters::total_context, and dialplan_counters::total_exten.
Referenced by handle_debug_dialplan().
06763 { 06764 struct ast_context *c = NULL; 06765 int res = 0, old_total_exten = dpc->total_exten; 06766 06767 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n"); 06768 06769 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n"); 06770 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n"); 06771 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n"); 06772 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n"); 06773 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n"); 06774 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n"); 06775 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n"); 06776 ast_rdlock_contexts(); 06777 06778 /* walk all contexts ... */ 06779 while ( (c = ast_walk_contexts(c)) ) { 06780 int context_info_printed = 0; 06781 06782 if (context && strcmp(ast_get_context_name(c), context)) 06783 continue; /* skip this one, name doesn't match */ 06784 06785 dpc->context_existence = 1; 06786 06787 if (!c->pattern_tree) { 06788 /* Ignore check_return warning from Coverity for ast_exists_extension below */ 06789 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */ 06790 } 06791 06792 ast_rdlock_context(c); 06793 06794 dpc->total_context++; 06795 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06796 ast_get_context_name(c), ast_get_context_registrar(c)); 06797 context_info_printed = 1; 06798 06799 if (c->pattern_tree) 06800 { 06801 cli_match_char_tree(c->pattern_tree, " ", fd); 06802 } else { 06803 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n"); 06804 } 06805 06806 ast_unlock_context(c); 06807 06808 /* if we print something in context, make an empty line */ 06809 if (context_info_printed) 06810 ast_cli(fd, "\n"); 06811 } 06812 ast_unlock_contexts(); 06813 06814 return (dpc->total_exten == old_total_exten) ? -1 : res; 06815 }
static int show_dialplan_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 6611 of file pbx.c.
References ast_cli(), ast_extension_match(), ast_get_context_name(), ast_get_context_registrar(), ast_get_extension_label(), ast_get_extension_name(), 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_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), ast_walk_contexts(), ast_walk_extension_priorities(), ast_exten::cidmatch, dialplan_counters::context_existence, el, dialplan_counters::extension_existence, LOG_WARNING, ast_exten::matchcid, print_ext(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.
Referenced by handle_show_dialplan().
06612 { 06613 struct ast_context *c = NULL; 06614 int res = 0, old_total_exten = dpc->total_exten; 06615 06616 ast_rdlock_contexts(); 06617 06618 /* walk all contexts ... */ 06619 while ( (c = ast_walk_contexts(c)) ) { 06620 struct ast_exten *e; 06621 struct ast_include *i; 06622 struct ast_ignorepat *ip; 06623 char buf[256], buf2[256]; 06624 int context_info_printed = 0; 06625 06626 if (context && strcmp(ast_get_context_name(c), context)) 06627 continue; /* skip this one, name doesn't match */ 06628 06629 dpc->context_existence = 1; 06630 06631 ast_rdlock_context(c); 06632 06633 /* are we looking for exten too? if yes, we print context 06634 * only if we find our extension. 06635 * Otherwise print context even if empty ? 06636 * XXX i am not sure how the rinclude is handled. 06637 * I think it ought to go inside. 06638 */ 06639 if (!exten) { 06640 dpc->total_context++; 06641 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06642 ast_get_context_name(c), ast_get_context_registrar(c)); 06643 context_info_printed = 1; 06644 } 06645 06646 /* walk extensions ... */ 06647 e = NULL; 06648 while ( (e = ast_walk_context_extensions(c, e)) ) { 06649 struct ast_exten *p; 06650 06651 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 06652 continue; /* skip, extension match failed */ 06653 06654 dpc->extension_existence = 1; 06655 06656 /* may we print context info? */ 06657 if (!context_info_printed) { 06658 dpc->total_context++; 06659 if (rinclude) { /* TODO Print more info about rinclude */ 06660 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 06661 ast_get_context_name(c), ast_get_context_registrar(c)); 06662 } else { 06663 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06664 ast_get_context_name(c), ast_get_context_registrar(c)); 06665 } 06666 context_info_printed = 1; 06667 } 06668 dpc->total_prio++; 06669 06670 /* write extension name and first peer */ 06671 if (e->matchcid) 06672 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch); 06673 else 06674 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 06675 06676 print_ext(e, buf2, sizeof(buf2)); 06677 06678 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 06679 ast_get_extension_registrar(e)); 06680 06681 dpc->total_exten++; 06682 /* walk next extension peers */ 06683 p = e; /* skip the first one, we already got it */ 06684 while ( (p = ast_walk_extension_priorities(e, p)) ) { 06685 const char *el = ast_get_extension_label(p); 06686 dpc->total_prio++; 06687 if (el) 06688 snprintf(buf, sizeof(buf), " [%s]", el); 06689 else 06690 buf[0] = '\0'; 06691 print_ext(p, buf2, sizeof(buf2)); 06692 06693 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 06694 ast_get_extension_registrar(p)); 06695 } 06696 } 06697 06698 /* walk included and write info ... */ 06699 i = NULL; 06700 while ( (i = ast_walk_context_includes(c, i)) ) { 06701 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 06702 if (exten) { 06703 /* Check all includes for the requested extension */ 06704 if (includecount >= AST_PBX_MAX_STACK) { 06705 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n"); 06706 } else { 06707 int dupe = 0; 06708 int x; 06709 for (x = 0; x < includecount; x++) { 06710 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 06711 dupe++; 06712 break; 06713 } 06714 } 06715 if (!dupe) { 06716 includes[includecount] = ast_get_include_name(i); 06717 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 06718 } else { 06719 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 06720 } 06721 } 06722 } else { 06723 ast_cli(fd, " Include => %-45s [%s]\n", 06724 buf, ast_get_include_registrar(i)); 06725 } 06726 } 06727 06728 /* walk ignore patterns and write info ... */ 06729 ip = NULL; 06730 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 06731 const char *ipname = ast_get_ignorepat_name(ip); 06732 char ignorepat[AST_MAX_EXTENSION]; 06733 snprintf(buf, sizeof(buf), "'%s'", ipname); 06734 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 06735 if (!exten || ast_extension_match(ignorepat, exten)) { 06736 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 06737 buf, ast_get_ignorepat_registrar(ip)); 06738 } 06739 } 06740 if (!rinclude) { 06741 struct ast_sw *sw = NULL; 06742 while ( (sw = ast_walk_context_switches(c, sw)) ) { 06743 snprintf(buf, sizeof(buf), "'%s/%s'", 06744 ast_get_switch_name(sw), 06745 ast_get_switch_data(sw)); 06746 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 06747 buf, ast_get_switch_registrar(sw)); 06748 } 06749 } 06750 06751 ast_unlock_context(c); 06752 06753 /* if we print something in context, make an empty line */ 06754 if (context_info_printed) 06755 ast_cli(fd, "\n"); 06756 } 06757 ast_unlock_contexts(); 06758 06759 return (dpc->total_exten == old_total_exten) ? -1 : res; 06760 }
static int statecbs_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 10963 of file pbx.c.
References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.
Referenced by ast_pbx_init().
10964 { 10965 const struct ast_state_cb *state_cb = obj; 10966 ast_state_cb_type change_cb = arg; 10967 10968 return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0; 10969 }
static char* substring | ( | const char * | value, | |
int | offset, | |||
int | length, | |||
char * | workspace, | |||
size_t | workspace_len | |||
) | [static] |
takes a substring. It is ok to call with value == workspace.
value | ||
offset | < 0 means start from the end of the string and set the beginning to be that many characters back. | |
length | is the length of the substring, a value less than 0 means to leave that many off the end. | |
workspace | ||
workspace_len | Always return a copy in workspace. |
Definition at line 3269 of file pbx.c.
References ast_copy_string().
Referenced by pbx_substitute_variables_helper_full().
03270 { 03271 char *ret = workspace; 03272 int lr; /* length of the input string after the copy */ 03273 03274 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 03275 03276 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 03277 03278 /* Quick check if no need to do anything */ 03279 if (offset == 0 && length >= lr) /* take the whole string */ 03280 return ret; 03281 03282 if (offset < 0) { /* translate negative offset into positive ones */ 03283 offset = lr + offset; 03284 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 03285 offset = 0; 03286 } 03287 03288 /* too large offset result in empty string so we know what to return */ 03289 if (offset >= lr) 03290 return ret + lr; /* the final '\0' */ 03291 03292 ret += offset; /* move to the start position */ 03293 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 03294 ret[length] = '\0'; 03295 else if (length < 0) { 03296 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 03297 ret[lr + length - offset] = '\0'; 03298 else 03299 ret[0] = '\0'; 03300 } 03301 03302 return ret; 03303 }
static struct ast_exten* trie_find_next_match | ( | struct match_char * | node | ) | [static, read] |
Definition at line 1673 of file pbx.c.
References match_char::alt_char, match_char::exten, match_char::next_char, and match_char::x.
Referenced by pbx_find_extension().
01674 { 01675 struct match_char *m3; 01676 struct match_char *m4; 01677 struct ast_exten *e3; 01678 01679 if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */ 01680 return node->exten; 01681 } 01682 01683 if (node && node->x[0] == '!' && !node->x[1]) { 01684 return node->exten; 01685 } 01686 01687 if (!node || !node->next_char) { 01688 return NULL; 01689 } 01690 01691 m3 = node->next_char; 01692 01693 if (m3->exten) { 01694 return m3->exten; 01695 } 01696 for (m4 = m3->alt_char; m4; m4 = m4->alt_char) { 01697 if (m4->exten) { 01698 return m4->exten; 01699 } 01700 } 01701 for (m4 = m3; m4; m4 = m4->alt_char) { 01702 e3 = trie_find_next_match(m3); 01703 if (e3) { 01704 return e3; 01705 } 01706 } 01707 01708 return NULL; 01709 }
static void unload_pbx | ( | void | ) | [static] |
Definition at line 10553 of file pbx.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_data_unregister, ast_event_unsubscribe(), ast_manager_unregister(), ast_taskprocessor_unreference(), ast_unregister_application(), builtins, device_state_sub, exception_function, pbx_cli, and testtime_function.
Referenced by load_pbx().
10554 { 10555 int x; 10556 10557 if (device_state_sub) { 10558 device_state_sub = ast_event_unsubscribe(device_state_sub); 10559 } 10560 if (device_state_tps) { 10561 ast_taskprocessor_unreference(device_state_tps); 10562 device_state_tps = NULL; 10563 } 10564 10565 /* Unregister builtin applications */ 10566 for (x = 0; x < ARRAY_LEN(builtins); x++) { 10567 ast_unregister_application(builtins[x].name); 10568 } 10569 ast_manager_unregister("ShowDialPlan"); 10570 ast_cli_unregister_multiple(pbx_cli, ARRAY_LEN(pbx_cli)); 10571 ast_custom_function_unregister(&exception_function); 10572 ast_custom_function_unregister(&testtime_function); 10573 ast_data_unregister(NULL); 10574 }
static void unreference_cached_app | ( | struct ast_app * | app | ) | [static] |
Definition at line 7374 of file pbx.c.
References ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_contexts(), and ast_walk_extension_priorities().
Referenced by ast_unregister_application().
07375 { 07376 struct ast_context *context = NULL; 07377 struct ast_exten *eroot = NULL, *e = NULL; 07378 07379 ast_rdlock_contexts(); 07380 while ((context = ast_walk_contexts(context))) { 07381 while ((eroot = ast_walk_context_extensions(context, eroot))) { 07382 while ((e = ast_walk_extension_priorities(eroot, e))) { 07383 if (e->cached_app == app) 07384 e->cached_app = NULL; 07385 } 07386 } 07387 } 07388 ast_unlock_contexts(); 07389 07390 return; 07391 }
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 1577 of file pbx.c.
References ast_log(), ast_exten::exten, scoreboard::exten, scoreboard::last_char, LOG_NOTICE, scoreboard::node, scoreboard::total_length, and scoreboard::total_specificity.
Referenced by new_find_extension().
01578 { 01579 /* if this extension is marked as deleted, then skip this -- if it never shows 01580 on the scoreboard, it will never be found, nor will halt the traversal. */ 01581 if (deleted) 01582 return; 01583 board->total_specificity = spec; 01584 board->total_length = length; 01585 board->exten = exten; 01586 board->last_char = last; 01587 board->node = node; 01588 #ifdef NEED_DEBUG_HERE 01589 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec); 01590 #endif 01591 }
static void wait_for_hangup | ( | struct ast_channel * | chan, | |
const void * | data | |||
) | [static] |
Definition at line 9555 of file pbx.c.
References ast_frfree, ast_read(), ast_safe_sleep(), ast_strlen_zero(), ast_waitfor(), and f.
Referenced by pbx_builtin_busy(), and pbx_builtin_congestion().
09556 { 09557 int res; 09558 struct ast_frame *f; 09559 double waitsec; 09560 int waittime; 09561 09562 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0)) 09563 waitsec = -1; 09564 if (waitsec > -1) { 09565 waittime = waitsec * 1000.0; 09566 ast_safe_sleep(chan, waittime); 09567 } else do { 09568 res = ast_waitfor(chan, -1); 09569 if (res < 0) 09570 return; 09571 f = ast_read(chan); 09572 if (f) 09573 ast_frfree(f); 09574 } while(f); 09575 }
int autofallthrough = 1 [static] |
Definition at line 1156 of file pbx.c.
Referenced by __ast_pbx_run(), and pbx_set_autofallthrough().
struct ast_app_option background_opts[128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },} [static] |
Definition at line 807 of file pbx.c.
Referenced by pbx_builtin_background().
struct pbx_builtin builtins[] [static] |
Declaration of builtin applications.
Referenced by load_pbx(), and unload_pbx().
ast_mutex_t conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Lock for the ast_context list.
Definition at line 1215 of file pbx.c.
Referenced by ast_rdlock_contexts(), ast_unlock_contexts(), and ast_wrlock_contexts().
ast_mutex_t context_merge_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
Definition at line 1220 of file pbx.c.
Referenced by ast_merge_contexts_and_delete(), and handle_statechange().
struct ast_context* contexts [static] |
Definition at line 1206 of file pbx.c.
Referenced by __ast_context_destroy(), ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and ast_walk_contexts().
struct ast_hashtab* contexts_table = NULL [static] |
Definition at line 1207 of file pbx.c.
Referenced by ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), find_context(), and find_context_locked().
int countcalls [static] |
Definition at line 1164 of file pbx.c.
Referenced by ast_active_calls(), decrease_call_count(), and increase_call_count().
const char* const days[] [static] |
Definition at line 7958 of file pbx.c.
Referenced by ast_build_timing().
struct ast_event_sub* device_state_sub [static] |
Subscription for device state change events.
Definition at line 1161 of file pbx.c.
Referenced by load_pbx(), and unload_pbx().
struct ast_taskprocessor* device_state_tps [static] |
struct ast_custom_function exception_function [static] |
{ .name = "EXCEPTION", .read = acf_exception_read, }
Definition at line 3571 of file pbx.c.
Referenced by load_pbx(), and unload_pbx().
struct ast_datastore_info exception_store_info [static] |
{ .type = "EXCEPTION", .destroy = exception_store_free, }
Definition at line 3503 of file pbx.c.
Referenced by acf_exception_read(), and raise_exception().
int extenpatternmatchnew = 0 [static] |
Definition at line 1157 of file pbx.c.
Referenced by pbx_find_extension(), and pbx_set_extenpatternmatchnew().
struct cfextension_states extension_states[] [static] |
Referenced by ast_extension_state2str().
struct ast_threadstorage extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , } [static] |
Definition at line 823 of file pbx.c.
Referenced by ast_extension_state2().
struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static] |
Definition at line 1154 of file pbx.c.
Referenced by ast_str_retrieve_variable(), handle_show_globals(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
ast_rwlock_t globalslock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } [static] |
Definition at line 1153 of file pbx.c.
Referenced by ast_str_retrieve_variable(), handle_show_globals(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
struct ao2_container* hints [static] |
Definition at line 1235 of file pbx.c.
Referenced by ast_add_hint(), ast_change_hint(), ast_extension_state_add_destroy(), ast_extension_state_del(), ast_merge_contexts_and_delete(), ast_pbx_init(), ast_remove_hint(), complete_core_show_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), and pbx_shutdown().
struct ast_data_handler hints_data_provider [static] |
{ .version = AST_DATA_HANDLER_VERSION, .get = hints_data_provider_get }
ast_mutex_t maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 1163 of file pbx.c.
Referenced by decrease_call_count(), and increase_call_count().
const char* const months[] [static] |
Definition at line 7970 of file pbx.c.
Referenced by ast_build_timing().
char* overrideswitch = NULL [static] |
Definition at line 1158 of file pbx.c.
Referenced by handle_cli_dialplan_save(), pbx_find_extension(), and pbx_set_overrideswitch().
struct ast_cli_entry pbx_cli[] [static] |
Definition at line 7353 of file pbx.c.
Referenced by load_pbx(), and unload_pbx().
struct ast_data_entry pbx_data_providers[] [static] |
{ AST_DATA_ENTRY("asterisk/core/hints", &hints_data_provider), }
Definition at line 10547 of file pbx.c.
Referenced by load_pbx().
struct ast_app_option resetcdr_opts[128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },} [static] |
Definition at line 9696 of file pbx.c.
Referenced by pbx_builtin_resetcdr().
struct ao2_container* statecbs [static] |
Definition at line 1237 of file pbx.c.
Referenced by ast_extension_state_add_destroy(), ast_extension_state_del(), ast_pbx_init(), handle_statechange(), and pbx_shutdown().
int stateid = 1 [static] |
Definition at line 1226 of file pbx.c.
Referenced by ast_extension_state_add_destroy().
struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , } [static] |
Definition at line 822 of file pbx.c.
Referenced by pbx_find_extension().
struct ast_custom_function testtime_function [static] |
{ .name = "TESTTIME", .write = testtime_write, }
Definition at line 9787 of file pbx.c.
Referenced by load_pbx(), and unload_pbx().
int totalcalls [static] |
Definition at line 1165 of file pbx.c.
Referenced by ast_processed_calls(), increase_call_count(), and timing_read().
struct ast_app_option waitexten_opts[128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },} [static] |
Definition at line 815 of file pbx.c.
Referenced by pbx_builtin_waitexten().