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 "asterisk/lock.h"#include "asterisk/cli.h"#include "asterisk/pbx.h"#include "asterisk/channel.h"#include "asterisk/file.h"#include "asterisk/callerid.h"#include "asterisk/cdr.h"#include "asterisk/config.h"#include "asterisk/term.h"#include "asterisk/manager.h"#include "asterisk/ast_expr.h"#include "asterisk/linkedlists.h"#include "asterisk/say.h"#include "asterisk/utils.h"#include "asterisk/causes.h"#include "asterisk/musiconhold.h"#include "asterisk/app.h"#include "asterisk/devicestate.h"#include "asterisk/stringfields.h"#include "asterisk/event.h"#include "asterisk/hashtab.h"#include "asterisk/module.h"#include "asterisk/indications.h"#include "asterisk/taskprocessor.h"
Go to the source code of this file.
Data Structures | |
| struct | app_tmp |
| 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 | pbx_builtin |
| Declaration of builtin applications. More... | |
| struct | pbx_exception |
| struct | scoreboard |
| struct | statechange |
| struct | store_hint |
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 | EXT_DATA_SIZE 8192 |
| #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 int | _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
| static int | acf_exception_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen) |
| static struct match_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, char *pattern, int is_pattern, int already, int specificity, struct match_char **parent) |
| static int | add_pri (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 int | add_pri_lockopt (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace, int lockhints) |
| add the extension in the priority chain. | |
| static struct match_char * | already_in_tree (struct match_char *current, char *pat) |
| 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 lockconts, int lockhints) |
| Does all the work of ast_add_extension2, but adds two args, to determine if context and hint locking should be done. In merge_and_delete, we need to do this without locking, as the locks are already held. | |
| 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. | |
| static int | ast_add_hint_nolock (struct ast_exten *e) |
| Add hint to hint list, check initial extension state; the hints had better be WRLOCKED already! | |
| AST_APP_OPTIONS (resetcdr_opts,{AST_APP_OPTION('w', AST_CDR_FLAG_POSTED), AST_APP_OPTION('a', AST_CDR_FLAG_LOCKED), AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS), AST_APP_OPTION('e', AST_CDR_FLAG_POST_ENABLE),}) | |
| AST_APP_OPTIONS (waitexten_opts,{AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 0), AST_APP_OPTION_ARG('d', WAITEXTEN_DIALTONE, 0),}) | |
| AST_APP_OPTIONS (background_opts,{AST_APP_OPTION('s', BACKGROUND_SKIP), AST_APP_OPTION('n', BACKGROUND_NOANSWER), AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN), AST_APP_OPTION('p', BACKGROUND_PLAYBACK),}) | |
| int | ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority) |
| 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) |
| 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) |
| 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. | |
| 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. | |
| int | ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data) |
| Add watcher for extension states. | |
| int | ast_extension_state_del (int id, ast_state_cb_type callback) |
| 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_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) |
| 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. | |
| AST_LIST_HEAD (store_hints, store_hint) | |
| static | AST_LIST_HEAD_NOLOCK_STATIC (statecbs, ast_state_cb) |
| 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. | |
| AST_MUTEX_DEFINE_STATIC (maxcalllock) | |
| int | ast_parseable_goto (struct ast_channel *chan, const char *goto_string) |
| int | ast_pbx_outgoing_app (const char *type, int 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, int 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 () |
| Read locks the context list. | |
| int | ast_register_application2 (const char *app, int(*execute)(struct ast_channel *, void *), 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. | |
| static | AST_RWLIST_HEAD_STATIC (hints, ast_hint) |
| static | AST_RWLIST_HEAD_STATIC (switches, ast_switch) |
| static | AST_RWLIST_HEAD_STATIC (apps, ast_app) |
| static | AST_RWLIST_HEAD_STATIC (acf_root, ast_custom_function) |
| AST_RWLOCK_DEFINE_STATIC (conlock) | |
| AST_RWLOCK_DEFINE_STATIC (globalslock) | |
| 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). | |
| AST_THREADSTORAGE (switch_data) | |
| int | ast_unlock_context (struct ast_context *con) |
| int | ast_unlock_contexts () |
| 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 () |
| Write locks the context list. | |
| int | ast_wrlock_contexts_version (void) |
| 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_pattern_tree (struct match_char *pattern_tree) |
| 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 *a, const char *b) |
| the full routine to compare extensions in rules. | |
| static int | ext_cmp1 (const char **p, unsigned char *bitwise) |
| helper functions to sort extensions and 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 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 unsigned | get_range (char *src, int max, 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 2 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_chanvar_deprecated (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_set_global_deprecated (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_globals_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_show_hint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| handle_show_hint: CLI support for listing registered dial plan hint | |
| static char * | handle_show_hints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| handle_show_hints: CLI support for listing registered dial plan hints | |
| static char * | handle_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 | 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) |
| void | log_match_char_tree (struct match_char *node, char *prefix) |
| static int | lookup_name (const char *s, 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 *, void *) |
| static int | pbx_builtin_background (struct ast_channel *, void *) |
| static int | pbx_builtin_busy (struct ast_channel *, void *) |
| void | pbx_builtin_clear_globals (void) |
| static int | pbx_builtin_congestion (struct ast_channel *, void *) |
| static int | pbx_builtin_execiftime (struct ast_channel *, void *) |
| const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
| static int | pbx_builtin_goto (struct ast_channel *, void *) |
| static int | pbx_builtin_gotoif (struct ast_channel *, void *) |
| static int | pbx_builtin_gotoiftime (struct ast_channel *, void *) |
| static int | pbx_builtin_hangup (struct ast_channel *, void *) |
| static int | pbx_builtin_importvar (struct ast_channel *, void *) |
| static int | pbx_builtin_incomplete (struct ast_channel *, void *) |
| static int | pbx_builtin_noop (struct ast_channel *, void *) |
| static int | pbx_builtin_proceeding (struct ast_channel *, void *) |
| static int | pbx_builtin_progress (struct ast_channel *, void *) |
| void | pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value) |
| int | pbx_builtin_raise_exception (struct ast_channel *chan, void *vreason) |
| static int | pbx_builtin_resetcdr (struct ast_channel *, void *) |
| static int | pbx_builtin_ringing (struct ast_channel *, void *) |
| static int | pbx_builtin_saycharacters (struct ast_channel *, void *) |
| static int | pbx_builtin_saydigits (struct ast_channel *, void *) |
| static int | pbx_builtin_saynumber (struct ast_channel *, void *) |
| static int | pbx_builtin_sayphonetic (struct ast_channel *, void *) |
| int | pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf) |
| static int | pbx_builtin_setamaflags (struct ast_channel *, void *) |
| int | pbx_builtin_setvar (struct ast_channel *, void *) |
| void | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
| int | pbx_builtin_setvar_multiple (struct ast_channel *, void *) |
| static int | pbx_builtin_wait (struct ast_channel *, void *) |
| static int | pbx_builtin_waitexten (struct ast_channel *, void *) |
| 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, void *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_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) |
| static void | pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count) |
| void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
| static void * | pbx_thread (void *data) |
| static void | print_ext (struct ast_exten *e, char *buf, int buflen) |
| helper function to print an extension | |
| 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 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 struct ast_exten * | trie_find_next_match (struct match_char *node) |
| 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, void *data) |
Variables | |
| static int | autofallthrough = 1 |
| static struct pbx_builtin | builtins [] |
| Declaration of builtin applications. | |
| static struct ast_cli_entry | cli_set_chanvar_deprecated = AST_CLI_DEFINE(handle_set_chanvar_deprecated, "Set a channel variable.") |
| static struct ast_cli_entry | cli_set_global_deprecated = AST_CLI_DEFINE(handle_set_global_deprecated, "Set global dialplan variable.") |
| static struct ast_cli_entry | cli_show_globals_deprecated = AST_CLI_DEFINE(handle_show_globals_deprecated, "Show global dialplan variables.") |
| static int | conlock_wrlock_version = 0 |
| static struct ast_context * | contexts |
| static struct ast_hashtab * | contexts_table = NULL |
| static int | countcalls |
| static char * | 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 varshead | globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE |
| static char | mandescr_show_dialplan [] |
| static char * | months [] |
| static char * | overrideswitch = NULL |
| static struct ast_cli_entry | pbx_cli [] |
| static int | stateid = 1 |
| static int | totalcalls |
Core PBX routines.
Definition in file pbx.c.
| #define AST_PBX_MAX_STACK 128 |
Go no deeper than this through includes (not counting loops)
Definition at line 971 of file pbx.c.
Referenced by handle_debug_dialplan(), handle_show_dialplan(), pbx_find_extension(), and show_dialplan_helper().
| #define BACKGROUND_MATCHEXTEN (1 << 2) |
Definition at line 105 of file pbx.c.
Referenced by pbx_builtin_background().
| #define BACKGROUND_NOANSWER (1 << 1) |
Definition at line 104 of file pbx.c.
Referenced by pbx_builtin_background().
| #define BACKGROUND_PLAYBACK (1 << 3) |
Definition at line 106 of file pbx.c.
Referenced by pbx_builtin_background().
| #define BACKGROUND_SKIP (1 << 0) |
Definition at line 103 of file pbx.c.
Referenced by pbx_builtin_background().
| #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 92 of file pbx.c.
Referenced by pbx_extension_helper(), and realtime_exec().
| #define NEW_MATCHER_CHK_MATCH |
Referenced by new_find_extension().
| #define NEW_MATCHER_RECURSE |
Referenced by new_find_extension().
| #define STATUS_NO_CONTEXT 1 |
Definition at line 2051 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
| #define STATUS_NO_EXTENSION 2 |
Definition at line 2052 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
| #define STATUS_NO_LABEL 4 |
Definition at line 2054 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
| #define STATUS_NO_PRIORITY 3 |
Definition at line 2053 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
| #define STATUS_SUCCESS 5 |
Definition at line 2055 of file pbx.c.
Referenced by pbx_find_extension().
| #define VAR_BUF_SIZE 4096 |
Definition at line 97 of file pbx.c.
Referenced by add_user_extension(), ast_add_extension2_lockopt(), build_user_routes(), pbx_builtin_importvar(), pbx_substitute_variables_helper_full(), phoneprov_callback(), pp_each_extension_exec(), and pp_each_user_exec().
| #define WAITEXTEN_DIALTONE (1 << 1) |
Definition at line 116 of file pbx.c.
Referenced by pbx_builtin_waitexten().
| #define WAITEXTEN_MOH (1 << 0) |
Definition at line 115 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 7718 of file pbx.c.
References __ast_internal_context_destroy(), ast_context_remove_extension_callerid2(), 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_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, ast_exten::exten, ast_context::ignorepats, ast_context::includes, ast_include::next, ast_ignorepat::next, ast_context::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().
07719 { 07720 struct ast_context *tmp, *tmpl=NULL; 07721 struct ast_exten *exten_item, *prio_item; 07722 07723 for (tmp = list; tmp; ) { 07724 struct ast_context *next = NULL; /* next starting point */ 07725 /* The following code used to skip forward to the next 07726 context with matching registrar, but this didn't 07727 make sense; individual priorities registrar'd to 07728 the matching registrar could occur in any context! */ 07729 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar); 07730 if (con) { 07731 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */ 07732 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar); 07733 if ( !strcasecmp(tmp->name, con->name) ) { 07734 break; /* found it */ 07735 } 07736 } 07737 } 07738 07739 if (!tmp) /* not found, we are done */ 07740 break; 07741 ast_wrlock_context(tmp); 07742 07743 if (registrar) { 07744 /* then search thru and remove any extens that match registrar. */ 07745 struct ast_hashtab_iter *exten_iter; 07746 struct ast_hashtab_iter *prio_iter; 07747 struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL; 07748 struct ast_include *i, *pi = NULL, *ni = NULL; 07749 struct ast_sw *sw = NULL; 07750 07751 /* remove any ignorepats whose registrar matches */ 07752 for (ip = tmp->ignorepats; ip; ip = ipn) { 07753 ipn = ip->next; 07754 if (!strcmp(ip->registrar, registrar)) { 07755 if (ipl) { 07756 ipl->next = ip->next; 07757 ast_free(ip); 07758 continue; /* don't change ipl */ 07759 } else { 07760 tmp->ignorepats = ip->next; 07761 ast_free(ip); 07762 continue; /* don't change ipl */ 07763 } 07764 } 07765 ipl = ip; 07766 } 07767 /* remove any includes whose registrar matches */ 07768 for (i = tmp->includes; i; i = ni) { 07769 ni = i->next; 07770 if (strcmp(i->registrar, registrar) == 0) { 07771 /* remove from list */ 07772 if (pi) { 07773 pi->next = i->next; 07774 /* free include */ 07775 ast_free(i); 07776 continue; /* don't change pi */ 07777 } else { 07778 tmp->includes = i->next; 07779 /* free include */ 07780 ast_free(i); 07781 continue; /* don't change pi */ 07782 } 07783 } 07784 pi = i; 07785 } 07786 /* remove any switches whose registrar matches */ 07787 AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) { 07788 if (strcmp(sw->registrar,registrar) == 0) { 07789 AST_LIST_REMOVE_CURRENT(list); 07790 ast_free(sw); 07791 } 07792 } 07793 AST_LIST_TRAVERSE_SAFE_END; 07794 07795 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */ 07796 exten_iter = ast_hashtab_start_traversal(tmp->root_table); 07797 while ((exten_item=ast_hashtab_next(exten_iter))) { 07798 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 07799 while ((prio_item=ast_hashtab_next(prio_iter))) { 07800 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) { 07801 continue; 07802 } 07803 ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n", 07804 tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL); 07805 /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */ 07806 ast_context_remove_extension_callerid2(tmp, prio_item->exten, prio_item->priority, prio_item->cidmatch, 1, NULL, 1); 07807 } 07808 ast_hashtab_end_traversal(prio_iter); 07809 } 07810 ast_hashtab_end_traversal(exten_iter); 07811 } 07812 07813 /* delete the context if it's registrar matches, is empty, has refcount of 1, */ 07814 /* it's not empty, if it has includes, ignorepats, or switches that are registered from 07815 another registrar. It's not empty if there are any extensions */ 07816 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) { 07817 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 07818 ast_hashtab_remove_this_object(contexttab, tmp); 07819 07820 next = tmp->next; 07821 if (tmpl) 07822 tmpl->next = next; 07823 else 07824 contexts = next; 07825 /* Okay, now we're safe to let it go -- in a sense, we were 07826 ready to let it go as soon as we locked it. */ 07827 ast_unlock_context(tmp); 07828 __ast_internal_context_destroy(tmp); 07829 } else { 07830 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar, 07831 tmp->refcount, tmp->root); 07832 ast_unlock_context(tmp); 07833 next = tmp->next; 07834 tmpl = tmp; 07835 } 07836 } else if (con) { 07837 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar); 07838 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 07839 ast_hashtab_remove_this_object(contexttab, tmp); 07840 07841 next = tmp->next; 07842 if (tmpl) 07843 tmpl->next = next; 07844 else 07845 contexts = next; 07846 /* Okay, now we're safe to let it go -- in a sense, we were 07847 ready to let it go as soon as we locked it. */ 07848 ast_unlock_context(tmp); 07849 __ast_internal_context_destroy(tmp); 07850 } 07851 07852 /* if we have a specific match, we are done, otherwise continue */ 07853 tmp = con ? NULL : next; 07854 } 07855 }
| int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
| struct ast_module * | mod | |||
| ) |
Register a custom function.
Definition at line 2811 of file pbx.c.
References 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_verb, COLOR_BRCYAN, LOG_ERROR, ast_custom_function::mod, ast_custom_function::name, and term_color().
Referenced by load_pbx().
02812 { 02813 struct ast_custom_function *cur; 02814 char tmps[80]; 02815 02816 if (!acf) 02817 return -1; 02818 02819 acf->mod = mod; 02820 02821 AST_RWLIST_WRLOCK(&acf_root); 02822 02823 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 02824 if (!strcmp(acf->name, cur->name)) { 02825 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 02826 AST_RWLIST_UNLOCK(&acf_root); 02827 return -1; 02828 } 02829 } 02830 02831 /* Store in alphabetical order */ 02832 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 02833 if (strcasecmp(acf->name, cur->name) < 0) { 02834 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 02835 break; 02836 } 02837 } 02838 AST_RWLIST_TRAVERSE_SAFE_END; 02839 if (!cur) 02840 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 02841 02842 AST_RWLIST_UNLOCK(&acf_root); 02843 02844 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 02845 02846 return 0; 02847 }
| static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| int | async | |||
| ) | [static] |
Definition at line 8968 of file pbx.c.
References ast_async_goto(), ast_exists_extension(), ast_explicit_goto(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, and ast_channel::exten.
Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().
08969 { 08970 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 08971 08972 if (!chan) 08973 return -2; 08974 08975 if (context == NULL) 08976 context = chan->context; 08977 if (exten == NULL) 08978 exten = chan->exten; 08979 08980 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 08981 if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num)) 08982 return goto_func(chan, context, exten, priority); 08983 else 08984 return -3; 08985 }
| static void __ast_internal_context_destroy | ( | struct ast_context * | con | ) | [static] |
Definition at line 7671 of file pbx.c.
References 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().
07672 { 07673 struct ast_include *tmpi; 07674 struct ast_sw *sw; 07675 struct ast_exten *e, *el, *en; 07676 struct ast_ignorepat *ipi; 07677 struct ast_context *tmp = con; 07678 07679 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 07680 struct ast_include *tmpil = tmpi; 07681 tmpi = tmpi->next; 07682 ast_free(tmpil); 07683 } 07684 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 07685 struct ast_ignorepat *ipl = ipi; 07686 ipi = ipi->next; 07687 ast_free(ipl); 07688 } 07689 if (tmp->registrar) 07690 ast_free(tmp->registrar); 07691 07692 /* destroy the hash tabs */ 07693 if (tmp->root_table) { 07694 ast_hashtab_destroy(tmp->root_table, 0); 07695 } 07696 /* and destroy the pattern tree */ 07697 if (tmp->pattern_tree) 07698 destroy_pattern_tree(tmp->pattern_tree); 07699 07700 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 07701 ast_free(sw); 07702 for (e = tmp->root; e;) { 07703 for (en = e->peer; en;) { 07704 el = en; 07705 en = en->peer; 07706 destroy_exten(el); 07707 } 07708 el = e; 07709 e = e->next; 07710 destroy_exten(el); 07711 } 07712 tmp->root = NULL; 07713 ast_rwlock_destroy(&tmp->lock); 07714 ast_free(tmp); 07715 }
| static enum ast_pbx_result __ast_pbx_run | ( | struct ast_channel * | c, | |
| struct ast_pbx_args * | args | |||
| ) | [static] |
Definition at line 3716 of file pbx.c.
References ast_channel::_softhangup, ast_calloc, ast_cdr_end(), ast_cdr_update(), 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, ast_channel::cdr, ast_channel::cid, ast_callerid::cid_num, collect_digits(), ast_channel::context, ast_pbx::dtimeoutms, ast_channel::exten, LOG_WARNING, ast_pbx_args::no_hangup_chan, ast_channel::pbx, pbx_builtin_busy(), pbx_builtin_congestion(), pbx_builtin_getvar_helper(), pbx_builtin_raise_exception(), pbx_builtin_setvar_helper(), pbx_destroy(), ast_channel::priority, ast_pbx::rtimeoutms, set_ext_pri(), status, and ast_channel::whentohangup.
Referenced by ast_pbx_run_args(), and pbx_thread().
03718 { 03719 int found = 0; /* set if we find at least one match */ 03720 int res = 0; 03721 int autoloopflag; 03722 int error = 0; /* set an error conditions */ 03723 03724 /* A little initial setup here */ 03725 if (c->pbx) { 03726 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 03727 /* XXX and now what ? */ 03728 ast_free(c->pbx); 03729 } 03730 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 03731 return -1; 03732 /* Set reasonable defaults */ 03733 c->pbx->rtimeoutms = 10000; 03734 c->pbx->dtimeoutms = 5000; 03735 03736 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 03737 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 03738 03739 /* Start by trying whatever the channel is set to */ 03740 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 03741 /* If not successful fall back to 's' */ 03742 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); 03743 /* XXX the original code used the existing priority in the call to 03744 * ast_exists_extension(), and reset it to 1 afterwards. 03745 * I believe the correct thing is to set it to 1 immediately. 03746 */ 03747 set_ext_pri(c, "s", 1); 03748 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 03749 /* JK02: And finally back to default if everything else failed */ 03750 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); 03751 ast_copy_string(c->context, "default", sizeof(c->context)); 03752 } 03753 } 03754 for (;;) { 03755 char dst_exten[256]; /* buffer to accumulate digits */ 03756 int pos = 0; /* XXX should check bounds */ 03757 int digit = 0; 03758 int invalid = 0; 03759 int timeout = 0; 03760 03761 /* loop on priorities in this context/exten */ 03762 while ( !(res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found,1))) { 03763 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) { 03764 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */ 03765 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 03766 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 03767 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 03768 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03769 pbx_builtin_raise_exception(c, "ABSOLUTETIMEOUT"); 03770 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 03771 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 03772 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 03773 } else if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 03774 c->_softhangup = 0; 03775 continue; 03776 } else if (ast_check_hangup(c)) { 03777 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n", 03778 c->exten, c->priority); 03779 error = 1; 03780 break; 03781 } 03782 c->priority++; 03783 } /* end while - from here on we can use 'break' to go out */ 03784 if (found && res) { 03785 /* Something bad happened, or a hangup has been requested. */ 03786 if (strchr("0123456789ABCDEF*#", res)) { 03787 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res); 03788 pos = 0; 03789 dst_exten[pos++] = digit = res; 03790 dst_exten[pos] = '\0'; 03791 } else if (res == AST_PBX_INCOMPLETE) { 03792 ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 03793 ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 03794 03795 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */ 03796 if (!ast_matchmore_extension(c, c->context, c->exten, 1, c->cid.cid_num)) { 03797 invalid = 1; 03798 } else { 03799 ast_copy_string(dst_exten, c->exten, sizeof(dst_exten)); 03800 digit = 1; 03801 pos = strlen(dst_exten); 03802 } 03803 } else { 03804 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 03805 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 03806 03807 if ((res == AST_PBX_ERROR) && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03808 /* if we are already on the 'e' exten, don't jump to it again */ 03809 if (!strcmp(c->exten, "e")) { 03810 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); 03811 error = 1; 03812 } else { 03813 pbx_builtin_raise_exception(c, "ERROR"); 03814 continue; 03815 } 03816 } 03817 03818 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 03819 c->_softhangup = 0; 03820 continue; 03821 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) { 03822 set_ext_pri(c, "T", 1); 03823 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 03824 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 03825 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 03826 continue; 03827 } else { 03828 if (c->cdr) 03829 ast_cdr_update(c); 03830 error = 1; 03831 break; 03832 } 03833 } 03834 } 03835 if (error) 03836 break; 03837 03838 /*!\note 03839 * We get here on a failure of some kind: non-existing extension or 03840 * hangup. We have options, here. We can either catch the failure 03841 * and continue, or we can drop out entirely. */ 03842 03843 if (invalid || !ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) { 03844 /*!\note 03845 * If there is no match at priority 1, it is not a valid extension anymore. 03846 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if 03847 * neither exist. 03848 */ 03849 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 03850 ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 03851 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 03852 set_ext_pri(c, "i", 1); 03853 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03854 pbx_builtin_raise_exception(c, "INVALID"); 03855 } else { 03856 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 03857 c->name, c->exten, c->context); 03858 error = 1; /* we know what to do with it */ 03859 break; 03860 } 03861 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 03862 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 03863 c->_softhangup = 0; 03864 } else { /* keypress received, get more digits for a full extension */ 03865 int waittime = 0; 03866 if (digit) 03867 waittime = c->pbx->dtimeoutms; 03868 else if (!autofallthrough) 03869 waittime = c->pbx->rtimeoutms; 03870 if (!waittime) { 03871 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 03872 if (!status) 03873 status = "UNKNOWN"; 03874 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 03875 if (!strcasecmp(status, "CONGESTION")) 03876 res = pbx_builtin_congestion(c, "10"); 03877 else if (!strcasecmp(status, "CHANUNAVAIL")) 03878 res = pbx_builtin_congestion(c, "10"); 03879 else if (!strcasecmp(status, "BUSY")) 03880 res = pbx_builtin_busy(c, "10"); 03881 error = 1; /* XXX disable message */ 03882 break; /* exit from the 'for' loop */ 03883 } 03884 03885 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 03886 break; 03887 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos])) 03888 timeout = 1; 03889 if (!timeout && ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */ 03890 set_ext_pri(c, dst_exten, 1); 03891 else { 03892 /* No such extension */ 03893 if (!timeout && !ast_strlen_zero(dst_exten)) { 03894 /* An invalid extension */ 03895 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 03896 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 03897 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 03898 set_ext_pri(c, "i", 1); 03899 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03900 pbx_builtin_raise_exception(c, "INVALID"); 03901 } else { 03902 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context); 03903 found = 1; /* XXX disable message */ 03904 break; 03905 } 03906 } else { 03907 /* A simple timeout */ 03908 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) { 03909 ast_verb(3, "Timeout on %s\n", c->name); 03910 set_ext_pri(c, "t", 1); 03911 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03912 pbx_builtin_raise_exception(c, "RESPONSETIMEOUT"); 03913 } else { 03914 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); 03915 found = 1; /* XXX disable message */ 03916 break; 03917 } 03918 } 03919 } 03920 if (c->cdr) { 03921 ast_verb(2, "CDR updated on %s\n",c->name); 03922 ast_cdr_update(c); 03923 } 03924 } 03925 } 03926 03927 if (!found && !error) { 03928 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 03929 } 03930 03931 if (!args || !args->no_hangup_chan) { 03932 ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD); 03933 } 03934 03935 if ((!args || !args->no_hangup_chan) && 03936 !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) && 03937 ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) { 03938 set_ext_pri(c, "h", 1); 03939 if (c->cdr && ast_opt_end_cdr_before_h_exten) { 03940 ast_cdr_end(c->cdr); 03941 } 03942 while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found, 1)) == 0) { 03943 c->priority++; 03944 } 03945 if (found && res) { 03946 /* Something bad happened, or a hangup has been requested. */ 03947 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 03948 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 03949 } 03950 } 03951 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 03952 ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */ 03953 pbx_destroy(c->pbx); 03954 c->pbx = NULL; 03955 03956 if (!args || !args->no_hangup_chan) { 03957 ast_hangup(c); 03958 } 03959 03960 return 0; 03961 }
| static int _extension_match_core | ( | const char * | pattern, | |
| const char * | data, | |||
| enum ext_match_t | mode | |||
| ) | [static] |
Definition at line 1827 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, LOG_NOTICE, and LOG_WARNING.
Referenced by extension_match_core().
01828 { 01829 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 01830 01831 #ifdef NEED_DEBUG_HERE 01832 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode); 01833 #endif 01834 01835 if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */ 01836 #ifdef NEED_DEBUG_HERE 01837 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n"); 01838 #endif 01839 return 1; 01840 } 01841 01842 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 01843 int ld = strlen(data), lp = strlen(pattern); 01844 01845 if (lp < ld) { /* pattern too short, cannot match */ 01846 #ifdef NEED_DEBUG_HERE 01847 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n"); 01848 #endif 01849 return 0; 01850 } 01851 /* depending on the mode, accept full or partial match or both */ 01852 if (mode == E_MATCH) { 01853 #ifdef NEED_DEBUG_HERE 01854 ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data); 01855 #endif 01856 return !strcmp(pattern, data); /* 1 on match, 0 on fail */ 01857 } 01858 if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */ 01859 #ifdef NEED_DEBUG_HERE 01860 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld); 01861 #endif 01862 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 01863 } else { 01864 #ifdef NEED_DEBUG_HERE 01865 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data); 01866 #endif 01867 return 0; 01868 } 01869 } 01870 pattern++; /* skip leading _ */ 01871 /* 01872 * XXX below we stop at '/' which is a separator for the CID info. However we should 01873 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 01874 */ 01875 while (*data && *pattern && *pattern != '/') { 01876 const char *end; 01877 01878 if (*data == '-') { /* skip '-' in data (just a separator) */ 01879 data++; 01880 continue; 01881 } 01882 switch (toupper(*pattern)) { 01883 case '[': /* a range */ 01884 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */ 01885 if (end == NULL) { 01886 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 01887 return 0; /* unconditional failure */ 01888 } 01889 for (pattern++; pattern != end; pattern++) { 01890 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 01891 if (*data >= pattern[0] && *data <= pattern[2]) 01892 break; /* match found */ 01893 else { 01894 pattern += 2; /* skip a total of 3 chars */ 01895 continue; 01896 } 01897 } else if (*data == pattern[0]) 01898 break; /* match found */ 01899 } 01900 if (pattern == end) { 01901 #ifdef NEED_DEBUG_HERE 01902 ast_log(LOG_NOTICE,"return (0) when pattern==end\n"); 01903 #endif 01904 return 0; 01905 } 01906 pattern = end; /* skip and continue */ 01907 break; 01908 case 'N': 01909 if (*data < '2' || *data > '9') { 01910 #ifdef NEED_DEBUG_HERE 01911 ast_log(LOG_NOTICE,"return (0) N is matched\n"); 01912 #endif 01913 return 0; 01914 } 01915 break; 01916 case 'X': 01917 if (*data < '0' || *data > '9') { 01918 #ifdef NEED_DEBUG_HERE 01919 ast_log(LOG_NOTICE,"return (0) X is matched\n"); 01920 #endif 01921 return 0; 01922 } 01923 break; 01924 case 'Z': 01925 if (*data < '1' || *data > '9') { 01926 #ifdef NEED_DEBUG_HERE 01927 ast_log(LOG_NOTICE,"return (0) Z is matched\n"); 01928 #endif 01929 return 0; 01930 } 01931 break; 01932 case '.': /* Must match, even with more digits */ 01933 #ifdef NEED_DEBUG_HERE 01934 ast_log(LOG_NOTICE,"return (1) when '.' is matched\n"); 01935 #endif 01936 return 1; 01937 case '!': /* Early match */ 01938 #ifdef NEED_DEBUG_HERE 01939 ast_log(LOG_NOTICE,"return (2) when '!' is matched\n"); 01940 #endif 01941 return 2; 01942 case ' ': 01943 case '-': /* Ignore these in patterns */ 01944 data--; /* compensate the final data++ */ 01945 break; 01946 default: 01947 if (*data != *pattern) { 01948 #ifdef NEED_DEBUG_HERE 01949 ast_log(LOG_NOTICE,"return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern); 01950 #endif 01951 return 0; 01952 } 01953 01954 } 01955 data++; 01956 pattern++; 01957 } 01958 if (*data) /* data longer than pattern, no match */ { 01959 #ifdef NEED_DEBUG_HERE 01960 ast_log(LOG_NOTICE,"return (0) when data longer than pattern\n"); 01961 #endif 01962 return 0; 01963 } 01964 01965 /* 01966 * match so far, but ran off the end of the data. 01967 * Depending on what is next, determine match or not. 01968 */ 01969 if (*pattern == '\0' || *pattern == '/') { /* exact match */ 01970 #ifdef NEED_DEBUG_HERE 01971 ast_log(LOG_NOTICE,"at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1); 01972 #endif 01973 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 01974 } else if (*pattern == '!') { /* early match */ 01975 #ifdef NEED_DEBUG_HERE 01976 ast_log(LOG_NOTICE,"at end, return (2) when '!' is matched\n"); 01977 #endif 01978 return 2; 01979 } else { /* partial match */ 01980 #ifdef NEED_DEBUG_HERE 01981 ast_log(LOG_NOTICE,"at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1); 01982 #endif 01983 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 01984 } 01985 }
| static int acf_exception_read | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | buflen | |||
| ) | [static] |
Definition at line 2628 of file pbx.c.
References ast_channel_datastore_find(), ast_copy_string(), ast_datastore::data, exception_store_info, and pbx_exception::priority.
02629 { 02630 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 02631 struct pbx_exception *exception = NULL; 02632 if (!ds || !ds->data) 02633 return -1; 02634 exception = ds->data; 02635 if (!strcasecmp(data, "REASON")) 02636 ast_copy_string(buf, exception->reason, buflen); 02637 else if (!strcasecmp(data, "CONTEXT")) 02638 ast_copy_string(buf, exception->context, buflen); 02639 else if (!strncasecmp(data, "EXTEN", 5)) 02640 ast_copy_string(buf, exception->exten, buflen); 02641 else if (!strcasecmp(data, "PRIORITY")) 02642 snprintf(buf, buflen, "%d", exception->priority); 02643 else 02644 return -1; 02645 return 0; 02646 }
| static struct match_char * add_exten_to_pattern_tree | ( | struct ast_context * | con, | |
| struct ast_exten * | e1, | |||
| int | findonly | |||
| ) | [static, read] |
Definition at line 1478 of file pbx.c.
References add_pattern_node(), already_in_tree(), ast_copy_string(), ast_log(), buf, ast_exten::cidmatch, compare_char(), match_char::deleted, match_char::exten, ast_exten::exten, LOG_DEBUG, LOG_ERROR, LOG_WARNING, m1, m2, ast_exten::matchcid, match_char::next_char, and ast_context::pattern_tree.
Referenced by add_pri_lockopt(), ast_add_extension2_lockopt(), ast_context_remove_extension_callerid2(), and create_match_char_tree().
01479 { 01480 struct match_char *m1 = NULL, *m2 = NULL, **m0; 01481 int specif; 01482 int already; 01483 int pattern = 0; 01484 char buf[256]; 01485 char extenbuf[512]; 01486 char *s1 = extenbuf; 01487 int l1 = strlen(e1->exten) + strlen(e1->cidmatch) + 2; 01488 01489 01490 ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf)); 01491 01492 if (e1->matchcid && l1 <= sizeof(extenbuf)) { 01493 strcat(extenbuf,"/"); 01494 strcat(extenbuf,e1->cidmatch); 01495 } else if (l1 > sizeof(extenbuf)) { 01496 ast_log(LOG_ERROR,"The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", e1->exten, e1->cidmatch); 01497 return 0; 01498 } 01499 #ifdef NEED_DEBUG 01500 ast_log(LOG_DEBUG,"Adding exten %s%c%s to tree\n", s1, e1->matchcid? '/':' ', e1->matchcid? e1->cidmatch : ""); 01501 #endif 01502 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */ 01503 m0 = &con->pattern_tree; 01504 already = 1; 01505 01506 if ( *s1 == '_') { 01507 pattern = 1; 01508 s1++; 01509 } 01510 while( *s1 ) { 01511 if (pattern && *s1 == '[' && *(s1-1) != '\\') { 01512 char *s2 = buf; 01513 buf[0] = 0; 01514 s1++; /* get past the '[' */ 01515 while (*s1 != ']' && *(s1-1) != '\\' ) { 01516 if (*s1 == '\\') { 01517 if (*(s1+1) == ']') { 01518 *s2++ = ']'; 01519 s1++;s1++; 01520 } else if (*(s1+1) == '\\') { 01521 *s2++ = '\\'; 01522 s1++;s1++; 01523 } else if (*(s1+1) == '-') { 01524 *s2++ = '-'; 01525 s1++; s1++; 01526 } else if (*(s1+1) == '[') { 01527 *s2++ = '['; 01528 s1++; s1++; 01529 } 01530 } else if (*s1 == '-') { /* remember to add some error checking to all this! */ 01531 char s3 = *(s1-1); 01532 char s4 = *(s1+1); 01533 for (s3++; s3 <= s4; s3++) { 01534 *s2++ = s3; 01535 } 01536 s1++; s1++; 01537 } else if (*s1 == '\0') { 01538 ast_log(LOG_WARNING, "A matching ']' was not found for '[' in pattern string '%s'\n", extenbuf); 01539 break; 01540 } else { 01541 *s2++ = *s1++; 01542 } 01543 } 01544 *s2 = 0; /* null terminate the exploded range */ 01545 /* sort the characters */ 01546 01547 specif = strlen(buf); 01548 qsort(buf, specif, 1, compare_char); 01549 specif <<= 8; 01550 specif += buf[0]; 01551 } else { 01552 01553 if (*s1 == '\\') { 01554 s1++; 01555 buf[0] = *s1; 01556 } else { 01557 if (pattern) { 01558 if (*s1 == 'n') /* make sure n,x,z patterns are canonicalized to N,X,Z */ 01559 *s1 = 'N'; 01560 else if (*s1 == 'x') 01561 *s1 = 'X'; 01562 else if (*s1 == 'z') 01563 *s1 = 'Z'; 01564 } 01565 buf[0] = *s1; 01566 } 01567 buf[1] = 0; 01568 specif = 1; 01569 } 01570 m2 = 0; 01571 if (already && (m2=already_in_tree(m1,buf)) && m2->next_char) { 01572 if (!(*(s1+1))) { /* if this is the end of the pattern, but not the end of the tree, then mark this node with the exten... 01573 a shorter pattern might win if the longer one doesn't match */ 01574 m2->exten = e1; 01575 m2->deleted = 0; 01576 } 01577 m1 = m2->next_char; /* m1 points to the node to compare against */ 01578 m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */ 01579 } else { /* not already OR not m2 OR nor m2->next_char */ 01580 if (m2) { 01581 if (findonly) 01582 return m2; 01583 m1 = m2; /* while m0 stays the same */ 01584 } else { 01585 if (findonly) 01586 return m1; 01587 m1 = add_pattern_node(con, m1, buf, pattern, already,specif, m0); /* m1 is the node just added */ 01588 m0 = &m1->next_char; 01589 } 01590 01591 if (!(*(s1+1))) { 01592 m1->deleted = 0; 01593 m1->exten = e1; 01594 } 01595 01596 already = 0; 01597 } 01598 s1++; /* advance to next char */ 01599 } 01600 return m1; 01601 }
| static struct match_char * add_pattern_node | ( | struct ast_context * | con, | |
| struct match_char * | current, | |||
| char * | pattern, | |||
| int | is_pattern, | |||
| int | already, | |||
| int | specificity, | |||
| struct match_char ** | parent | |||
| ) | [static, read] |
Definition at line 1437 of file pbx.c.
References ast_calloc, ast_free, ast_strdup, insert_in_next_chars_alt_char_list(), match_char::is_pattern, match_char::next_char, ast_context::pattern_tree, match_char::specificity, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01438 { 01439 struct match_char *m; 01440 01441 if (!(m = ast_calloc(1, sizeof(*m)))) 01442 return NULL; 01443 01444 if (!(m->x = ast_strdup(pattern))) { 01445 ast_free(m); 01446 return NULL; 01447 } 01448 01449 /* the specificity scores are the same as used in the old 01450 pattern matcher. */ 01451 m->is_pattern = is_pattern; 01452 if (specificity == 1 && is_pattern && pattern[0] == 'N') 01453 m->specificity = 0x0802; 01454 else if (specificity == 1 && is_pattern && pattern[0] == 'Z') 01455 m->specificity = 0x0901; 01456 else if (specificity == 1 && is_pattern && pattern[0] == 'X') 01457 m->specificity = 0x0a00; 01458 else if (specificity == 1 && is_pattern && pattern[0] == '.') 01459 m->specificity = 0x10000; 01460 else if (specificity == 1 && is_pattern && pattern[0] == '!') 01461 m->specificity = 0x20000; 01462 else 01463 m->specificity = specificity; 01464 01465 if (!con->pattern_tree) { 01466 insert_in_next_chars_alt_char_list(&con->pattern_tree, m); 01467 } else { 01468 if (already) { /* switch to the new regime (traversing vs appending)*/ 01469 insert_in_next_chars_alt_char_list(nextcharptr, m); 01470 } else { 01471 insert_in_next_chars_alt_char_list(¤t->next_char, m); 01472 } 01473 } 01474 01475 return m; 01476 }
| static int add_pri | ( | 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 6884 of file pbx.c.
References add_pri_lockopt().
Referenced by ast_add_extension2_lockopt().
06886 { 06887 return add_pri_lockopt(con, tmp, el, e, replace, 1); 06888 }
| static int add_pri_lockopt | ( | struct ast_context * | con, | |
| struct ast_exten * | tmp, | |||
| struct ast_exten * | el, | |||
| struct ast_exten * | e, | |||
| int | replace, | |||
| int | lockhints | |||
| ) | [static] |
add the extension in the priority chain.
| 0 | on success. | |
| -1 | on failure. |
Definition at line 6895 of file pbx.c.
References add_exten_to_pattern_tree(), ast_add_hint(), ast_add_hint_nolock(), 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_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 add_pri().
06897 { 06898 struct ast_exten *ep; 06899 struct ast_exten *eh=e; 06900 06901 for (ep = NULL; e ; ep = e, e = e->peer) { 06902 if (e->priority >= tmp->priority) 06903 break; 06904 } 06905 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 06906 ast_hashtab_insert_safe(eh->peer_table, tmp); 06907 06908 if (tmp->label) { 06909 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 06910 } 06911 ep->peer = tmp; 06912 return 0; /* success */ 06913 } 06914 if (e->priority == tmp->priority) { 06915 /* Can't have something exactly the same. Is this a 06916 replacement? If so, replace, otherwise, bonk. */ 06917 if (!replace) { 06918 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 06919 if (tmp->datad) { 06920 tmp->datad(tmp->data); 06921 /* if you free this, null it out */ 06922 tmp->data = NULL; 06923 } 06924 06925 ast_free(tmp); 06926 return -1; 06927 } 06928 /* we are replacing e, so copy the link fields and then update 06929 * whoever pointed to e to point to us 06930 */ 06931 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 06932 tmp->peer = e->peer; /* always meaningful */ 06933 if (ep) { /* We're in the peer list, just insert ourselves */ 06934 ast_hashtab_remove_object_via_lookup(eh->peer_table,e); 06935 06936 if (e->label) { 06937 ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e); 06938 } 06939 06940 ast_hashtab_insert_safe(eh->peer_table,tmp); 06941 if (tmp->label) { 06942 ast_hashtab_insert_safe(eh->peer_label_table,tmp); 06943 } 06944 06945 ep->peer = tmp; 06946 } else if (el) { /* We're the first extension. Take over e's functions */ 06947 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 06948 tmp->peer_table = e->peer_table; 06949 tmp->peer_label_table = e->peer_label_table; 06950 ast_hashtab_remove_object_via_lookup(tmp->peer_table,e); 06951 ast_hashtab_insert_safe(tmp->peer_table,tmp); 06952 if (e->label) { 06953 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 06954 } 06955 if (tmp->label) { 06956 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 06957 } 06958 06959 ast_hashtab_remove_object_via_lookup(con->root_table, e); 06960 ast_hashtab_insert_safe(con->root_table, tmp); 06961 el->next = tmp; 06962 /* The pattern trie points to this exten; replace the pointer, 06963 and all will be well */ 06964 if (x) { /* if the trie isn't formed yet, don't sweat this */ 06965 if (x->exten) { /* this test for safety purposes */ 06966 x->exten = tmp; /* replace what would become a bad pointer */ 06967 } else { 06968 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 06969 } 06970 } 06971 } else { /* We're the very first extension. */ 06972 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 06973 ast_hashtab_remove_object_via_lookup(con->root_table, e); 06974 ast_hashtab_insert_safe(con->root_table, tmp); 06975 tmp->peer_table = e->peer_table; 06976 tmp->peer_label_table = e->peer_label_table; 06977 ast_hashtab_remove_object_via_lookup(tmp->peer_table, e); 06978 ast_hashtab_insert_safe(tmp->peer_table, tmp); 06979 if (e->label) { 06980 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 06981 } 06982 if (tmp->label) { 06983 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 06984 } 06985 06986 ast_hashtab_remove_object_via_lookup(con->root_table, e); 06987 ast_hashtab_insert_safe(con->root_table, tmp); 06988 con->root = tmp; 06989 /* The pattern trie points to this exten; replace the pointer, 06990 and all will be well */ 06991 if (x) { /* if the trie isn't formed yet; no problem */ 06992 if (x->exten) { /* this test for safety purposes */ 06993 x->exten = tmp; /* replace what would become a bad pointer */ 06994 } else { 06995 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 06996 } 06997 } 06998 } 06999 if (tmp->priority == PRIORITY_HINT) 07000 ast_change_hint(e,tmp); 07001 /* Destroy the old one */ 07002 if (e->datad) 07003 e->datad(e->data); 07004 ast_free(e); 07005 } else { /* Slip ourselves in just before e */ 07006 tmp->peer = e; 07007 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 07008 if (ep) { /* Easy enough, we're just in the peer list */ 07009 if (tmp->label) { 07010 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 07011 } 07012 ast_hashtab_insert_safe(eh->peer_table, tmp); 07013 ep->peer = tmp; 07014 } else { /* we are the first in some peer list, so link in the ext list */ 07015 tmp->peer_table = e->peer_table; 07016 tmp->peer_label_table = e->peer_label_table; 07017 e->peer_table = 0; 07018 e->peer_label_table = 0; 07019 ast_hashtab_insert_safe(tmp->peer_table, tmp); 07020 if (tmp->label) { 07021 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 07022 } 07023 ast_hashtab_remove_object_via_lookup(con->root_table, e); 07024 ast_hashtab_insert_safe(con->root_table, tmp); 07025 if (el) 07026 el->next = tmp; /* in the middle... */ 07027 else 07028 con->root = tmp; /* ... or at the head */ 07029 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 07030 } 07031 /* And immediately return success. */ 07032 if (tmp->priority == PRIORITY_HINT) { 07033 if (lockhints) { 07034 ast_add_hint(tmp); 07035 } else { 07036 ast_add_hint_nolock(tmp); 07037 } 07038 } 07039 } 07040 return 0; 07041 }
| static struct match_char * already_in_tree | ( | struct match_char * | current, | |
| char * | pat | |||
| ) | [static, read] |
Definition at line 1385 of file pbx.c.
References match_char::alt_char, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01386 { 01387 struct match_char *t; 01388 01389 if (!current) 01390 return 0; 01391 01392 for (t = current; t; t = t->alt_char) { 01393 if (!strcmp(pat, t->x)) /* uh, we may want to sort exploded [] contents to make matching easy */ 01394 return t; 01395 } 01396 01397 return 0; 01398 }
| int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 4099 of file pbx.c.
Referenced by handle_chanlist(), handle_showcalls(), and sysinfo_helper().
04100 { 04101 return countcalls; 04102 }
| 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 6750 of file pbx.c.
References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_extension_state_add(), handle_cli_dialplan_add_extension(), park_add_hints(), register_exten(), register_peer_exten(), and RegisterExtension().
06753 { 06754 int ret = -1; 06755 struct ast_context *c = find_context_locked(context); 06756 06757 if (c) { 06758 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 06759 application, data, datad, registrar); 06760 ast_unlock_contexts(); 06761 } 06762 06763 return ret; 06764 }
| 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 7068 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by ast_add_extension(), ast_park_call_full(), build_parkinglot(), context_merge(), load_config(), load_module(), manage_parkinglot(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().
07072 { 07073 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1); 07074 }
| 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 | lockconts, | |||
| int | lockhints | |||
| ) | [static] |
Does all the work of ast_add_extension2, but adds two args, to determine if context and hint locking should be done. In merge_and_delete, we need to do this without locking, as the locks are already held.
Definition at line 7081 of file pbx.c.
References add_exten_to_pattern_tree(), add_pri(), ast_exten::app, ast_add_hint(), ast_add_hint_nolock(), ast_calloc, ast_copy_string(), ast_debug, 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_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().
07085 { 07086 /* 07087 * Sort extensions (or patterns) according to the rules indicated above. 07088 * These are implemented by the function ext_cmp()). 07089 * All priorities for the same ext/pattern/cid are kept in a list, 07090 * using the 'peer' field as a link field.. 07091 */ 07092 struct ast_exten *tmp, *tmp2, *e, *el = NULL; 07093 int res; 07094 int length; 07095 char *p; 07096 char expand_buf[VAR_BUF_SIZE]; 07097 struct ast_exten dummy_exten = {0}; 07098 char dummy_name[1024]; 07099 07100 if (ast_strlen_zero(extension)) { 07101 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", 07102 con->name); 07103 return -1; 07104 } 07105 07106 /* If we are adding a hint evalulate in variables and global variables */ 07107 if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) { 07108 struct ast_channel c = {0, }; 07109 07110 ast_copy_string(c.exten, extension, sizeof(c.exten)); 07111 ast_copy_string(c.context, con->name, sizeof(c.context)); 07112 pbx_substitute_variables_helper(&c, application, expand_buf, sizeof(expand_buf)); 07113 application = expand_buf; 07114 } 07115 07116 length = sizeof(struct ast_exten); 07117 length += strlen(extension) + 1; 07118 length += strlen(application) + 1; 07119 if (label) 07120 length += strlen(label) + 1; 07121 if (callerid) 07122 length += strlen(callerid) + 1; 07123 else 07124 length ++; /* just the '\0' */ 07125 07126 /* Be optimistic: Build the extension structure first */ 07127 if (!(tmp = ast_calloc(1, length))) 07128 return -1; 07129 07130 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */ 07131 label = 0; 07132 07133 /* use p as dst in assignments, as the fields are const char * */ 07134 p = tmp->stuff; 07135 if (label) { 07136 tmp->label = p; 07137 strcpy(p, label); 07138 p += strlen(label) + 1; 07139 } 07140 tmp->exten = p; 07141 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 07142 tmp->priority = priority; 07143 tmp->cidmatch = p; /* but use p for assignments below */ 07144 if (!ast_strlen_zero(callerid)) { 07145 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 07146 tmp->matchcid = 1; 07147 } else { 07148 *p++ = '\0'; 07149 tmp->matchcid = 0; 07150 } 07151 tmp->app = p; 07152 strcpy(p, application); 07153 tmp->parent = con; 07154 tmp->data = data; 07155 tmp->datad = datad; 07156 tmp->registrar = registrar; 07157 07158 if (lockconts) { 07159 ast_wrlock_context(con); 07160 } 07161 07162 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding 07163 an extension, and the trie exists, then we need to incrementally add this pattern to it. */ 07164 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 07165 dummy_exten.exten = dummy_name; 07166 dummy_exten.matchcid = 0; 07167 dummy_exten.cidmatch = 0; 07168 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten); 07169 if (!tmp2) { 07170 /* hmmm, not in the trie; */ 07171 add_exten_to_pattern_tree(con, tmp, 0); 07172 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */ 07173 } 07174 } 07175 res = 0; /* some compilers will think it is uninitialized otherwise */ 07176 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 07177 res = ext_cmp(e->exten, tmp->exten); 07178 if (res == 0) { /* extension match, now look at cidmatch */ 07179 if (!e->matchcid && !tmp->matchcid) 07180 res = 0; 07181 else if (tmp->matchcid && !e->matchcid) 07182 res = 1; 07183 else if (e->matchcid && !tmp->matchcid) 07184 res = -1; 07185 else 07186 res = ext_cmp(e->cidmatch, tmp->cidmatch); 07187 } 07188 if (res >= 0) 07189 break; 07190 } 07191 if (e && res == 0) { /* exact match, insert in the pri chain */ 07192 res = add_pri(con, tmp, el, e, replace); 07193 if (lockconts) { 07194 ast_unlock_context(con); 07195 } 07196 if (res < 0) { 07197 errno = EEXIST; /* XXX do we care ? */ 07198 return 0; /* XXX should we return -1 maybe ? */ 07199 } 07200 } else { 07201 /* 07202 * not an exact match, this is the first entry with this pattern, 07203 * so insert in the main list right before 'e' (if any) 07204 */ 07205 tmp->next = e; 07206 if (el) { /* there is another exten already in this context */ 07207 el->next = tmp; 07208 tmp->peer_table = ast_hashtab_create(13, 07209 hashtab_compare_exten_numbers, 07210 ast_hashtab_resize_java, 07211 ast_hashtab_newsize_java, 07212 hashtab_hash_priority, 07213 0); 07214 tmp->peer_label_table = ast_hashtab_create(7, 07215 hashtab_compare_exten_labels, 07216 ast_hashtab_resize_java, 07217 ast_hashtab_newsize_java, 07218 hashtab_hash_labels, 07219 0); 07220 if (label) { 07221 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 07222 } 07223 ast_hashtab_insert_safe(tmp->peer_table, tmp); 07224 } else { /* this is the first exten in this context */ 07225 if (!con->root_table) 07226 con->root_table = ast_hashtab_create(27, 07227 hashtab_compare_extens, 07228 ast_hashtab_resize_java, 07229 ast_hashtab_newsize_java, 07230 hashtab_hash_extens, 07231 0); 07232 con->root = tmp; 07233 con->root->peer_table = ast_hashtab_create(13, 07234 hashtab_compare_exten_numbers, 07235 ast_hashtab_resize_java, 07236 ast_hashtab_newsize_java, 07237 hashtab_hash_priority, 07238 0); 07239 con->root->peer_label_table = ast_hashtab_create(7, 07240 hashtab_compare_exten_labels, 07241 ast_hashtab_resize_java, 07242 ast_hashtab_newsize_java, 07243 hashtab_hash_labels, 07244 0); 07245 if (label) { 07246 ast_hashtab_insert_safe(con->root->peer_label_table, tmp); 07247 } 07248 ast_hashtab_insert_safe(con->root->peer_table, tmp); 07249 07250 } 07251 ast_hashtab_insert_safe(con->root_table, tmp); 07252 if (lockconts) { 07253 ast_unlock_context(con); 07254 } 07255 if (tmp->priority == PRIORITY_HINT) { 07256 if (lockhints) { 07257 ast_add_hint(tmp); 07258 } else { 07259 ast_add_hint_nolock(tmp); 07260 } 07261 } 07262 } 07263 if (option_debug) { 07264 if (tmp->matchcid) { 07265 ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 07266 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 07267 } else { 07268 ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n", 07269 tmp->exten, tmp->priority, con->name, con); 07270 } 07271 } 07272 07273 if (tmp->matchcid) { 07274 ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 07275 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 07276 } else { 07277 ast_verb(3, "Added extension '%s' priority %d to %s (%p)\n", 07278 tmp->exten, tmp->priority, con->name, con); 07279 } 07280 07281 return 0; 07282 }
| 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 6731 of file pbx.c.
References ast_add_extension2_lockopt(), and find_context().
Referenced by ast_merge_contexts_and_delete().
06734 { 06735 int ret = -1; 06736 struct ast_context *c = find_context(context); 06737 06738 if (c) { 06739 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid, 06740 application, data, datad, registrar, 0, 0); 06741 } 06742 06743 return ret; 06744 }
| static int ast_add_hint | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state.
Definition at line 3563 of file pbx.c.
References ast_add_hint_nolock(), AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by add_pri_lockopt(), and ast_add_extension2_lockopt().
03564 { 03565 int ret; 03566 03567 AST_RWLIST_WRLOCK(&hints); 03568 ret = ast_add_hint_nolock(e); 03569 AST_RWLIST_UNLOCK(&hints); 03570 03571 return ret; 03572 }
| static int ast_add_hint_nolock | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state; the hints had better be WRLOCKED already!
Definition at line 3534 of file pbx.c.
References ast_calloc, ast_debug, ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, ast_hint::exten, and ast_hint::laststate.
Referenced by add_pri_lockopt(), ast_add_extension2_lockopt(), and ast_add_hint().
03535 { 03536 struct ast_hint *hint; 03537 03538 if (!e) 03539 return -1; 03540 03541 /* Search if hint exists, do nothing */ 03542 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03543 if (hint->exten == e) { 03544 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 03545 return -1; 03546 } 03547 } 03548 03549 ast_debug(2, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 03550 03551 if (!(hint = ast_calloc(1, sizeof(*hint)))) { 03552 return -1; 03553 } 03554 /* Initialize and insert new item at the top */ 03555 hint->exten = e; 03556 hint->laststate = ast_extension_state2(e); 03557 AST_RWLIST_INSERT_HEAD(&hints, hint, list); 03558 03559 return 0; 03560 }
| AST_APP_OPTIONS | ( | resetcdr_opts | ) |
| AST_APP_OPTIONS | ( | waitexten_opts | ) |
| AST_APP_OPTIONS | ( | background_opts | ) |
| int ast_async_goto | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 6789 of file pbx.c.
References ast_channel::_state, ast_channel::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_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_dtmfup(), handle_request_bye(), handle_request_refer(), pbx_parseable_goto(), process_ast_dsp(), sip_read(), and socket_process().
06790 { 06791 int res = 0; 06792 06793 ast_channel_lock(chan); 06794 06795 if (chan->pbx) { /* This channel is currently in the PBX */ 06796 ast_explicit_goto(chan, context, exten, priority + 1); 06797 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 06798 } else { 06799 /* In order to do it when the channel doesn't really exist within 06800 the PBX, we have to make a new channel, masquerade, and start the PBX 06801 at the new location */ 06802 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name); 06803 if (!tmpchan) { 06804 res = -1; 06805 } else { 06806 if (chan->cdr) { 06807 ast_cdr_discard(tmpchan->cdr); 06808 tmpchan->cdr = ast_cdr_dup(chan->cdr); /* share the love */ 06809 } 06810 /* Make formats okay */ 06811 tmpchan->readformat = chan->readformat; 06812 tmpchan->writeformat = chan->writeformat; 06813 /* Setup proper location */ 06814 ast_explicit_goto(tmpchan, 06815 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 06816 06817 /* Masquerade into temp channel */ 06818 if (ast_channel_masquerade(tmpchan, chan)) { 06819 /* Failed to set up the masquerade. It's probably chan_local 06820 * in the middle of optimizing itself out. Sad. :( */ 06821 ast_hangup(tmpchan); 06822 tmpchan = NULL; 06823 res = -1; 06824 } else { 06825 /* Grab the locks and get going */ 06826 ast_channel_lock(tmpchan); 06827 ast_do_masquerade(tmpchan); 06828 ast_channel_unlock(tmpchan); 06829 /* Start the PBX going on our stolen channel */ 06830 if (ast_pbx_start(tmpchan)) { 06831 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 06832 ast_hangup(tmpchan); 06833 res = -1; 06834 } 06835 } 06836 } 06837 } 06838 ast_channel_unlock(chan); 06839 return res; 06840 }
| int ast_async_goto_by_name | ( | const char * | channame, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 6842 of file pbx.c.
References ast_async_goto(), ast_channel_unlock, and ast_get_channel_by_name_locked().
06843 { 06844 struct ast_channel *chan; 06845 int res = -1; 06846 06847 chan = ast_get_channel_by_name_locked(channame); 06848 if (chan) { 06849 res = ast_async_goto(chan, context, exten, priority); 06850 ast_channel_unlock(chan); 06851 } 06852 return res; 06853 }
| int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 8992 of file pbx.c.
References __ast_goto_if_exists().
08993 { 08994 return __ast_goto_if_exists(chan, context, exten, priority, 1); 08995 }
| int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 9055 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec().
09056 { 09057 return pbx_parseable_goto(chan, goto_string, 1); 09058 }
| int ast_build_timing | ( | struct ast_timing * | i, | |
| const char * | info_in | |||
| ) |
Definition at line 6410 of file pbx.c.
References ast_copy_string(), ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, and strsep().
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
06411 { 06412 char info_save[256]; 06413 char *info; 06414 06415 /* Check for empty just in case */ 06416 if (ast_strlen_zero(info_in)) 06417 return 0; 06418 /* make a copy just in case we were passed a static string */ 06419 ast_copy_string(info_save, info_in, sizeof(info_save)); 06420 info = info_save; 06421 /* Assume everything except time */ 06422 i->monthmask = 0xfff; /* 12 bits */ 06423 i->daymask = 0x7fffffffU; /* 31 bits */ 06424 i->dowmask = 0x7f; /* 7 bits */ 06425 /* on each call, use strsep() to move info to the next argument */ 06426 get_timerange(i, strsep(&info, "|,")); 06427 if (info) 06428 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 06429 if (info) 06430 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 06431 if (info) 06432 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 06433 return 1; 06434 }
| 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 3661 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), handle_link_data(), handle_link_phone_dtmf(), leave_voicemail(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), pri_dchannel(), skinny_ss(), ss_thread(), and valid_exit().
03662 { 03663 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 03664 }
Change hint for an extension.
Definition at line 3575 of file pbx.c.
References AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and ast_hint::exten.
Referenced by add_pri_lockopt().
03576 { 03577 struct ast_hint *hint; 03578 int res = -1; 03579 03580 AST_RWLIST_WRLOCK(&hints); 03581 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03582 if (hint->exten == oe) { 03583 hint->exten = ne; 03584 res = 0; 03585 break; 03586 } 03587 } 03588 AST_RWLIST_UNLOCK(&hints); 03589 03590 return res; 03591 }
| int ast_check_timing | ( | const struct ast_timing * | i | ) |
Definition at line 6436 of file pbx.c.
References ast_localtime(), ast_log(), ast_tvnow(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, ast_timing::monthmask, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and ast_tm::tm_wday.
Referenced by iftime(), include_valid(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
06437 { 06438 struct ast_tm tm; 06439 struct timeval now = ast_tvnow(); 06440 06441 ast_localtime(&now, &tm, NULL); 06442 06443 /* If it's not the right month, return */ 06444 if (!(i->monthmask & (1 << tm.tm_mon))) 06445 return 0; 06446 06447 /* If it's not that time of the month.... */ 06448 /* Warning, tm_mday has range 1..31! */ 06449 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 06450 return 0; 06451 06452 /* If it's not the right day of the week */ 06453 if (!(i->dowmask & (1 << tm.tm_wday))) 06454 return 0; 06455 06456 /* Sanity check the hour just to be safe */ 06457 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 06458 ast_log(LOG_WARNING, "Insane time...\n"); 06459 return 0; 06460 } 06461 06462 /* Now the tough part, we calculate if it fits 06463 in the right time based on min/hour */ 06464 if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2)))) 06465 return 0; 06466 06467 /* If we got this far, then we're good */ 06468 return 1; 06469 }
| 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 6662 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
06663 { 06664 int ret = -1; 06665 struct ast_context *c = find_context_locked(context); 06666 06667 if (c) { 06668 ret = ast_context_add_ignorepat2(c, value, registrar); 06669 ast_unlock_contexts(); 06670 } 06671 return ret; 06672 }
| int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | value, | |||
| const char * | registrar | |||
| ) |
Definition at line 6674 of file pbx.c.
References ast_calloc, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_add_ignorepat(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
06675 { 06676 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 06677 int length; 06678 char *pattern; 06679 length = sizeof(struct ast_ignorepat); 06680 length += strlen(value) + 1; 06681 if (!(ignorepat = ast_calloc(1, length))) 06682 return -1; 06683 /* The cast to char * is because we need to write the initial value. 06684 * The field is not supposed to be modified otherwise. Also, gcc 4.2 06685 * sees the cast as dereferencing a type-punned pointer and warns about 06686 * it. This is the workaround (we're telling gcc, yes, that's really 06687 * what we wanted to do). 06688 */ 06689 pattern = (char *) ignorepat->pattern; 06690 strcpy(pattern, value); 06691 ignorepat->next = NULL; 06692 ignorepat->registrar = registrar; 06693 ast_wrlock_context(con); 06694 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 06695 ignorepatl = ignorepatc; 06696 if (!strcasecmp(ignorepatc->pattern, value)) { 06697 /* Already there */ 06698 ast_unlock_context(con); 06699 errno = EEXIST; 06700 return -1; 06701 } 06702 } 06703 if (ignorepatl) 06704 ignorepatl->next = ignorepat; 06705 else 06706 con->ignorepats = ignorepat; 06707 ast_unlock_context(con); 06708 return 0; 06709 06710 }
| 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 6216 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
06217 { 06218 int ret = -1; 06219 struct ast_context *c = find_context_locked(context); 06220 06221 if (c) { 06222 ret = ast_context_add_include2(c, include, registrar); 06223 ast_unlock_contexts(); 06224 } 06225 return ret; 06226 }
| 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 6478 of file pbx.c.
References ast_build_timing(), ast_calloc, 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_context_add_include(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
06480 { 06481 struct ast_include *new_include; 06482 char *c; 06483 struct ast_include *i, *il = NULL; /* include, include_last */ 06484 int length; 06485 char *p; 06486 06487 length = sizeof(struct ast_include); 06488 length += 2 * (strlen(value) + 1); 06489 06490 /* allocate new include structure ... */ 06491 if (!(new_include = ast_calloc(1, length))) 06492 return -1; 06493 /* Fill in this structure. Use 'p' for assignments, as the fields 06494 * in the structure are 'const char *' 06495 */ 06496 p = new_include->stuff; 06497 new_include->name = p; 06498 strcpy(p, value); 06499 p += strlen(value) + 1; 06500 new_include->rname = p; 06501 strcpy(p, value); 06502 /* Strip off timing info, and process if it is there */ 06503 if ( (c = strchr(p, ',')) ) { 06504 *c++ = '\0'; 06505 new_include->hastime = ast_build_timing(&(new_include->timing), c); 06506 } 06507 new_include->next = NULL; 06508 new_include->registrar = registrar; 06509 06510 ast_wrlock_context(con); 06511 06512 /* ... go to last include and check if context is already included too... */ 06513 for (i = con->includes; i; i = i->next) { 06514 if (!strcasecmp(i->name, new_include->name)) { 06515 ast_free(new_include); 06516 ast_unlock_context(con); 06517 errno = EEXIST; 06518 return -1; 06519 } 06520 il = i; 06521 } 06522 06523 /* ... include new context into context list, unlock, return */ 06524 if (il) 06525 il->next = new_include; 06526 else 06527 con->includes = new_include; 06528 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 06529 06530 ast_unlock_context(con); 06531 06532 return 0; 06533 }
| 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 6540 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
06541 { 06542 int ret = -1; 06543 struct ast_context *c = find_context_locked(context); 06544 06545 if (c) { /* found, add switch to this context */ 06546 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 06547 ast_unlock_contexts(); 06548 } 06549 return ret; 06550 }
| 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 6559 of file pbx.c.
References 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, and ast_sw::registrar.
Referenced by ast_context_add_switch(), context_merge_incls_swits_igps_other_registrars(), lua_register_switches(), and pbx_load_config().
06561 { 06562 struct ast_sw *new_sw; 06563 struct ast_sw *i; 06564 int length; 06565 char *p; 06566 06567 length = sizeof(struct ast_sw); 06568 length += strlen(value) + 1; 06569 if (data) 06570 length += strlen(data); 06571 length++; 06572 06573 /* allocate new sw structure ... */ 06574 if (!(new_sw = ast_calloc(1, length))) 06575 return -1; 06576 /* ... fill in this structure ... */ 06577 p = new_sw->stuff; 06578 new_sw->name = p; 06579 strcpy(new_sw->name, value); 06580 p += strlen(value) + 1; 06581 new_sw->data = p; 06582 if (data) { 06583 strcpy(new_sw->data, data); 06584 p += strlen(data) + 1; 06585 } else { 06586 strcpy(new_sw->data, ""); 06587 p++; 06588 } 06589 new_sw->eval = eval; 06590 new_sw->registrar = registrar; 06591 06592 /* ... try to lock this context ... */ 06593 ast_wrlock_context(con); 06594 06595 /* ... go to last sw and check if context is already swd too... */ 06596 AST_LIST_TRAVERSE(&con->alts, i, list) { 06597 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 06598 ast_free(new_sw); 06599 ast_unlock_context(con); 06600 errno = EEXIST; 06601 return -1; 06602 } 06603 } 06604 06605 /* ... sw new context into context list, unlock, return */ 06606 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 06607 06608 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 06609 06610 ast_unlock_context(con); 06611 06612 return 0; 06613 }
| 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 7857 of file pbx.c.
References __ast_context_destroy(), ast_unlock_contexts(), and ast_wrlock_contexts().
Referenced by __unload_module(), cleanup_stale_contexts(), parkinglot_destroy(), sla_destroy(), and unload_module().
07858 { 07859 ast_wrlock_contexts(); 07860 __ast_context_destroy(contexts, contexts_table, con,registrar); 07861 ast_unlock_contexts(); 07862 }
| 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 2031 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_ignore_pattern(), cleanup_stale_contexts(), isexten_function_read(), load_config(), manage_parkinglot(), park_exec_full(), parkinglot_destroy(), register_exten(), register_peer_exten(), unload_module(), and unregister_exten().
02032 { 02033 struct ast_context *tmp = NULL; 02034 struct fake_context item; 02035 02036 ast_copy_string(item.name, name, sizeof(item.name)); 02037 02038 ast_rdlock_contexts(); 02039 if( contexts_table ) { 02040 tmp = ast_hashtab_lookup(contexts_table,&item); 02041 } else { 02042 while ( (tmp = ast_walk_contexts(tmp)) ) { 02043 if (!name || !strcasecmp(name, tmp->name)) 02044 break; 02045 } 02046 } 02047 ast_unlock_contexts(); 02048 return tmp; 02049 }
| 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 5872 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(), ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by ast_park_call_full(), build_parkinglot(), context_merge(), load_config(), load_module(), lua_register_switches(), manage_parkinglot(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().
05873 { 05874 struct ast_context *tmp, **local_contexts; 05875 struct fake_context search; 05876 int length = sizeof(struct ast_context) + strlen(name) + 1; 05877 05878 if (!contexts_table) { 05879 contexts_table = ast_hashtab_create(17, 05880 ast_hashtab_compare_contexts, 05881 ast_hashtab_resize_java, 05882 ast_hashtab_newsize_java, 05883 ast_hashtab_hash_contexts, 05884 0); 05885 } 05886 05887 ast_copy_string(search.name, name, sizeof(search.name)); 05888 if (!extcontexts) { 05889 ast_rdlock_contexts(); 05890 local_contexts = &contexts; 05891 tmp = ast_hashtab_lookup(contexts_table, &search); 05892 ast_unlock_contexts(); 05893 if (tmp) { 05894 tmp->refcount++; 05895 return tmp; 05896 } 05897 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 05898 local_contexts = extcontexts; 05899 tmp = ast_hashtab_lookup(exttable, &search); 05900 if (tmp) { 05901 tmp->refcount++; 05902 return tmp; 05903 } 05904 } 05905 05906 if ((tmp = ast_calloc(1, length))) { 05907 ast_rwlock_init(&tmp->lock); 05908 ast_mutex_init(&tmp->macrolock); 05909 strcpy(tmp->name, name); 05910 tmp->root = NULL; 05911 tmp->root_table = NULL; 05912 tmp->registrar = ast_strdup(registrar); 05913 tmp->includes = NULL; 05914 tmp->ignorepats = NULL; 05915 tmp->refcount = 1; 05916 } else { 05917 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 05918 return NULL; 05919 } 05920 05921 if (!extcontexts) { 05922 ast_wrlock_contexts(); 05923 tmp->next = *local_contexts; 05924 *local_contexts = tmp; 05925 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 05926 ast_unlock_contexts(); 05927 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 05928 ast_verb(3, "Registered extension context '%s' (%p) in table %p; registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 05929 } else { 05930 tmp->next = *local_contexts; 05931 if (exttable) 05932 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 05933 05934 *local_contexts = tmp; 05935 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 05936 ast_verb(3, "Registered extension context '%s' (%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 05937 } 05938 return tmp; 05939 }
| int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 4486 of file pbx.c.
References ast_copy_string(), ast_get_context_name(), ast_hashtab_lookup(), ast_mutex_lock(), ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by _macro_exec().
04487 { 04488 struct ast_context *c = NULL; 04489 int ret = -1; 04490 struct fake_context item; 04491 04492 ast_rdlock_contexts(); 04493 04494 ast_copy_string(item.name, context, sizeof(item.name)); 04495 04496 c = ast_hashtab_lookup(contexts_table,&item); 04497 if (c) 04498 ret = 0; 04499 04500 04501 #ifdef NOTNOW 04502 04503 while ((c = ast_walk_contexts(c))) { 04504 if (!strcmp(ast_get_context_name(c), context)) { 04505 ret = 0; 04506 break; 04507 } 04508 } 04509 04510 #endif 04511 ast_unlock_contexts(); 04512 04513 /* if we found context, lock macrolock */ 04514 if (ret == 0) 04515 ret = ast_mutex_lock(&c->macrolock); 04516 04517 return ret; 04518 }
| int ast_context_remove_extension | ( | const char * | context, | |
| const char * | extension, | |||
| int | priority, | |||
| const char * | registrar | |||
| ) |
Simply remove extension from context.
| context | context to remove extension from | |
| extension | which extension to remove | |
| priority | priority of extension to remove (0 to remove all) | |
| callerid | NULL to remove all; non-NULL to match a single record per priority | |
| matchcid | non-zero to match callerid element (if non-NULL); 0 to match default case | |
| registrar | registrar of the extension |
This function removes an extension from a given context.
| 0 | on success | |
| -1 | on failure |
Definition at line 4293 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), unregister_exten(), and UnregisterExtension().
04294 { 04295 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 04296 }
| 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 4320 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by load_config(), manage_parkinglot(), park_exec_full(), and unload_module().
04321 { 04322 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 04323 }
| 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 4298 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().
04299 { 04300 int ret = -1; /* default error return */ 04301 struct ast_context *c = find_context_locked(context); 04302 04303 if (c) { /* ... remove extension ... */ 04304 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1); 04305 ast_unlock_contexts(); 04306 } 04307 return ret; 04308 }
| 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 4325 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, ast_exten::label, LOG_ERROR, log_match_char_tree(), LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, 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().
04326 { 04327 struct ast_exten *exten, *prev_exten = NULL; 04328 struct ast_exten *peer; 04329 struct ast_exten ex, *exten2, *exten3; 04330 char dummy_name[1024]; 04331 struct ast_exten *previous_peer = NULL; 04332 struct ast_exten *next_peer = NULL; 04333 int found = 0; 04334 04335 if (!already_locked) 04336 ast_wrlock_context(con); 04337 04338 /* Handle this is in the new world */ 04339 04340 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 04341 * peers, not just those matching the callerid. */ 04342 #ifdef NEED_DEBUG 04343 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 04344 #endif 04345 #ifdef CONTEXT_DEBUG 04346 check_contexts(__FILE__, __LINE__); 04347 #endif 04348 /* find this particular extension */ 04349 ex.exten = dummy_name; 04350 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 04351 ex.cidmatch = callerid; 04352 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 04353 exten = ast_hashtab_lookup(con->root_table, &ex); 04354 if (exten) { 04355 if (priority == 0) { 04356 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 04357 if (!exten2) 04358 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); 04359 if (con->pattern_tree) { 04360 04361 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 04362 04363 if (x->exten) { /* this test for safety purposes */ 04364 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 04365 x->exten = 0; /* get rid of what will become a bad pointer */ 04366 } else { 04367 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 04368 } 04369 } 04370 } else { 04371 ex.priority = priority; 04372 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 04373 if (exten2) { 04374 04375 if (exten2->label) { /* if this exten has a label, remove that, too */ 04376 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 04377 if (!exten3) 04378 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); 04379 } 04380 04381 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 04382 if (!exten3) 04383 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); 04384 if (exten2 == exten && exten2->peer) { 04385 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 04386 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 04387 } 04388 if (ast_hashtab_size(exten->peer_table) == 0) { 04389 /* well, if the last priority of an exten is to be removed, 04390 then, the extension is removed, too! */ 04391 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 04392 if (!exten3) 04393 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 04394 if (con->pattern_tree) { 04395 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 04396 if (x->exten) { /* this test for safety purposes */ 04397 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 04398 x->exten = 0; /* get rid of what will become a bad pointer */ 04399 } 04400 } 04401 } 04402 } else { 04403 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 04404 priority, exten->exten, con->name); 04405 } 04406 } 04407 } else { 04408 /* hmmm? this exten is not in this pattern tree? */ 04409 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 04410 extension, con->name); 04411 } 04412 #ifdef NEED_DEBUG 04413 if (con->pattern_tree) { 04414 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 04415 log_match_char_tree(con->pattern_tree, " "); 04416 } 04417 #endif 04418 04419 /* scan the extension list to find first matching extension-registrar */ 04420 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 04421 if (!strcmp(exten->exten, extension) && 04422 (!registrar || !strcmp(exten->registrar, registrar)) && 04423 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 04424 break; 04425 } 04426 if (!exten) { 04427 /* we can't find right extension */ 04428 if (!already_locked) 04429 ast_unlock_context(con); 04430 return -1; 04431 } 04432 04433 /* scan the priority list to remove extension with exten->priority == priority */ 04434 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 04435 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))); 04436 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 04437 if ((priority == 0 || peer->priority == priority) && 04438 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 04439 (!registrar || !strcmp(peer->registrar, registrar) )) { 04440 found = 1; 04441 04442 /* we are first priority extension? */ 04443 if (!previous_peer) { 04444 /* 04445 * We are first in the priority chain, so must update the extension chain. 04446 * The next node is either the next priority or the next extension 04447 */ 04448 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 04449 if (peer->peer) { 04450 /* move the peer_table and peer_label_table down to the next peer, if 04451 it is there */ 04452 peer->peer->peer_table = peer->peer_table; 04453 peer->peer->peer_label_table = peer->peer_label_table; 04454 peer->peer_table = NULL; 04455 peer->peer_label_table = NULL; 04456 } 04457 if (!prev_exten) { /* change the root... */ 04458 con->root = next_node; 04459 } else { 04460 prev_exten->next = next_node; /* unlink */ 04461 } 04462 if (peer->peer) { /* update the new head of the pri list */ 04463 peer->peer->next = peer->next; 04464 } 04465 } else { /* easy, we are not first priority in extension */ 04466 previous_peer->peer = peer->peer; 04467 } 04468 04469 /* now, free whole priority extension */ 04470 destroy_exten(peer); 04471 } else { 04472 previous_peer = peer; 04473 } 04474 } 04475 if (!already_locked) 04476 ast_unlock_context(con); 04477 return found ? 0 : -1; 04478 }
| int ast_context_remove_ignorepat | ( | const char * | context, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 6619 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
06620 { 06621 int ret = -1; 06622 struct ast_context *c = find_context_locked(context); 06623 06624 if (c) { 06625 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 06626 ast_unlock_contexts(); 06627 } 06628 return ret; 06629 }
| int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 6631 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().
06632 { 06633 struct ast_ignorepat *ip, *ipl = NULL; 06634 06635 ast_wrlock_context(con); 06636 06637 for (ip = con->ignorepats; ip; ip = ip->next) { 06638 if (!strcmp(ip->pattern, ignorepat) && 06639 (!registrar || (registrar == ip->registrar))) { 06640 if (ipl) { 06641 ipl->next = ip->next; 06642 ast_free(ip); 06643 } else { 06644 con->ignorepats = ip->next; 06645 ast_free(ip); 06646 } 06647 ast_unlock_context(con); 06648 return 0; 06649 } 06650 ipl = ip; 06651 } 06652 06653 ast_unlock_context(con); 06654 errno = EINVAL; 06655 return -1; 06656 }
| 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 4185 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
04186 { 04187 int ret = -1; 04188 struct ast_context *c = find_context_locked(context); 04189 04190 if (c) { 04191 /* found, remove include from this context ... */ 04192 ret = ast_context_remove_include2(c, include, registrar); 04193 ast_unlock_contexts(); 04194 } 04195 return ret; 04196 }
| 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 4207 of file pbx.c.
References ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_context::includes, ast_include::name, ast_include::next, and ast_include::registrar.
Referenced by ast_context_remove_include().
04208 { 04209 struct ast_include *i, *pi = NULL; 04210 int ret = -1; 04211 04212 ast_wrlock_context(con); 04213 04214 /* find our include */ 04215 for (i = con->includes; i; pi = i, i = i->next) { 04216 if (!strcmp(i->name, include) && 04217 (!registrar || !strcmp(i->registrar, registrar))) { 04218 /* remove from list */ 04219 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 04220 if (pi) 04221 pi->next = i->next; 04222 else 04223 con->includes = i->next; 04224 /* free include and return */ 04225 ast_free(i); 04226 ret = 0; 04227 break; 04228 } 04229 } 04230 04231 ast_unlock_context(con); 04232 04233 return ret; 04234 }
| int ast_context_remove_switch | ( | const char * | context, | |
| const char * | sw, | |||
| const char * | data, | |||
| const char * | registrar | |||
| ) |
Remove a switch.
Definition at line 4241 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
04242 { 04243 int ret = -1; /* default error return */ 04244 struct ast_context *c = find_context_locked(context); 04245 04246 if (c) { 04247 /* remove switch from this context ... */ 04248 ret = ast_context_remove_switch2(c, sw, data, registrar); 04249 ast_unlock_contexts(); 04250 } 04251 return ret; 04252 }
| 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 4262 of file pbx.c.
References 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().
04263 { 04264 struct ast_sw *i; 04265 int ret = -1; 04266 04267 ast_wrlock_context(con); 04268 04269 /* walk switches */ 04270 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 04271 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 04272 (!registrar || !strcmp(i->registrar, registrar))) { 04273 /* found, remove from list */ 04274 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 04275 AST_LIST_REMOVE_CURRENT(list); 04276 ast_free(i); /* free switch and return */ 04277 ret = 0; 04278 break; 04279 } 04280 } 04281 AST_LIST_TRAVERSE_SAFE_END; 04282 04283 ast_unlock_context(con); 04284 04285 return ret; 04286 }
| int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 4525 of file pbx.c.
References ast_copy_string(), ast_get_context_name(), ast_hashtab_lookup(), ast_mutex_unlock(), ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by _macro_exec().
04526 { 04527 struct ast_context *c = NULL; 04528 int ret = -1; 04529 struct fake_context item; 04530 04531 ast_rdlock_contexts(); 04532 04533 ast_copy_string(item.name, context, sizeof(item.name)); 04534 04535 c = ast_hashtab_lookup(contexts_table,&item); 04536 if (c) 04537 ret = 0; 04538 #ifdef NOTNOW 04539 04540 while ((c = ast_walk_contexts(c))) { 04541 if (!strcmp(ast_get_context_name(c), context)) { 04542 ret = 0; 04543 break; 04544 } 04545 } 04546 04547 #endif 04548 ast_unlock_contexts(); 04549 04550 /* if we found context, unlock macrolock */ 04551 if (ret == 0) 04552 ret = ast_mutex_unlock(&c->macrolock); 04553 04554 return ret; 04555 }
| 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 8949 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().
08950 { 08951 struct ast_include *inc = NULL; 08952 int res = 0; 08953 08954 while ( (inc = ast_walk_context_includes(con, inc)) ) { 08955 if (ast_context_find(inc->rname)) 08956 continue; 08957 08958 res = -1; 08959 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 08960 ast_get_context_name(con), inc->rname); 08961 break; 08962 } 08963 08964 return res; 08965 }
| struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 2782 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_func_read(), ast_func_write(), config_curl(), destroy_curl(), handle_show_function(), op_func(), realtime_curl(), realtime_multi_curl(), require_curl(), store_curl(), and update_curl().
02783 { 02784 struct ast_custom_function *acf = NULL; 02785 02786 AST_RWLIST_RDLOCK(&acf_root); 02787 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 02788 if (!strcmp(name, acf->name)) 02789 break; 02790 } 02791 AST_RWLIST_UNLOCK(&acf_root); 02792 02793 return acf; 02794 }
| int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 2796 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, and ast_custom_function::name.
Referenced by load_module(), reload(), and unload_module().
02797 { 02798 struct ast_custom_function *cur; 02799 02800 if (!acf) 02801 return -1; 02802 02803 AST_RWLIST_WRLOCK(&acf_root); 02804 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) 02805 ast_verb(2, "Unregistered custom function %s\n", cur->name); 02806 AST_RWLIST_UNLOCK(&acf_root); 02807 02808 return cur ? 0 : -1; 02809 }
| enum ast_extension_states ast_devstate_to_extenstate | ( | enum ast_device_state | devstate | ) |
Map devstate to an extension state.
| [in] | device | state |
Definition at line 3276 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_state2().
03277 { 03278 switch (devstate) { 03279 case AST_DEVICE_ONHOLD: 03280 return AST_EXTENSION_ONHOLD; 03281 case AST_DEVICE_BUSY: 03282 return AST_EXTENSION_BUSY; 03283 case AST_DEVICE_UNAVAILABLE: 03284 case AST_DEVICE_UNKNOWN: 03285 case AST_DEVICE_INVALID: 03286 return AST_EXTENSION_UNAVAILABLE; 03287 case AST_DEVICE_RINGINUSE: 03288 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 03289 case AST_DEVICE_RINGING: 03290 return AST_EXTENSION_RINGING; 03291 case AST_DEVICE_INUSE: 03292 return AST_EXTENSION_INUSE; 03293 case AST_DEVICE_NOT_INUSE: 03294 return AST_EXTENSION_NOT_INUSE; 03295 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 03296 break; 03297 } 03298 03299 return AST_EXTENSION_NOT_INUSE; 03300 }
| 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 3646 of file pbx.c.
References E_MATCH, and pbx_extension_helper().
Referenced by __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), answer_call(), ast_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), builtin_atxfer(), builtin_blindtransfer(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmfup(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), park_space_reserve(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), pri_dchannel(), privacy_exec(), process_ast_dsp(), readexten_exec(), register_peer_exten(), rpt_exec(), show_debug_helper(), sip_read(), skinny_ss(), socket_process(), ss7_linkset(), ss_thread(), and waitstream_core().
03647 { 03648 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 03649 }
| int ast_explicit_goto | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 6766 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().
06767 { 06768 if (!chan) 06769 return -1; 06770 06771 ast_channel_lock(chan); 06772 06773 if (!ast_strlen_zero(context)) 06774 ast_copy_string(chan->context, context, sizeof(chan->context)); 06775 if (!ast_strlen_zero(exten)) 06776 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06777 if (priority > -1) { 06778 chan->priority = priority; 06779 /* see flag description in channel.h for explanation */ 06780 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 06781 chan->priority--; 06782 } 06783 06784 ast_channel_unlock(chan); 06785 06786 return 0; 06787 }
| int ast_extension_close | ( | const char * | pattern, | |
| const char * | data, | |||
| int | needmore | |||
| ) |
Definition at line 2008 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().
02009 { 02010 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02011 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02012 return extension_match_core(pattern, data, needmore); 02013 }
| 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 1810 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
01811 { 01812 return ext_cmp(a, b); 01813 }
| 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 2003 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().
02004 { 02005 return extension_match_core(pattern, data, E_MATCH); 02006 }
| 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 3338 of file pbx.c.
References ast_extension_state2(), and ast_hint_extension().
Referenced by action_extensionstate(), extstate_read(), and handle_request_subscribe().
03339 { 03340 struct ast_exten *e; 03341 03342 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */ 03343 if (!e) 03344 return -1; /* No hint, return -1 */ 03345 03346 return ast_extension_state2(e); /* Check all devices in the hint */ 03347 }
| static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
Check state of extension by using hints.
Definition at line 3303 of file pbx.c.
References ast_copy_string(), ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_devstate_to_extenstate(), ast_get_extension_app(), AST_MAX_EXTENSION, and strsep().
Referenced by ast_add_hint_nolock(), ast_extension_state(), and handle_statechange().
03304 { 03305 char hint[AST_MAX_EXTENSION] = ""; 03306 char *cur, *rest; 03307 struct ast_devstate_aggregate agg; 03308 03309 if (!e) 03310 return -1; 03311 03312 ast_devstate_aggregate_init(&agg); 03313 03314 ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint)); 03315 03316 rest = hint; /* One or more devices separated with a & character */ 03317 03318 while ( (cur = strsep(&rest, "&")) ) { 03319 ast_devstate_aggregate_add(&agg, ast_device_state(cur)); 03320 } 03321 03322 return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg)); 03323 }
| 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 3326 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(), and show_channels_cb().
03327 { 03328 int i; 03329 03330 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 03331 if (extension_states[i].extension_state == extension_state) 03332 return extension_states[i].text; 03333 } 03334 return "Unknown"; 03335 }
| int ast_extension_state_add | ( | const char * | context, | |
| const char * | exten, | |||
| ast_state_cb_type | callback, | |||
| void * | data | |||
| ) |
Add watcher for extension states.
Registers a state change callback.
Definition at line 3399 of file pbx.c.
References ast_exten::app, ast_add_extension(), ast_calloc, ast_free_ptr(), ast_hint_extension(), AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_state_cb::callback, ast_exten::cidmatch, ast_exten::data, ast_state_cb::data, ast_hint::exten, ast_exten::exten, ast_state_cb::id, ast_exten::label, ast_exten::parent, ast_exten::priority, and ast_exten::registrar.
Referenced by __init_manager(), handle_request_subscribe(), and skinny_register().
03401 { 03402 struct ast_hint *hint; 03403 struct ast_state_cb *cblist; 03404 struct ast_exten *e; 03405 03406 /* If there's no context and extension: add callback to statecbs list */ 03407 if (!context && !exten) { 03408 AST_RWLIST_WRLOCK(&hints); 03409 03410 AST_LIST_TRAVERSE(&statecbs, cblist, entry) { 03411 if (cblist->callback == callback) { 03412 cblist->data = data; 03413 AST_RWLIST_UNLOCK(&hints); 03414 return 0; 03415 } 03416 } 03417 03418 /* Now insert the callback */ 03419 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 03420 AST_RWLIST_UNLOCK(&hints); 03421 return -1; 03422 } 03423 cblist->id = 0; 03424 cblist->callback = callback; 03425 cblist->data = data; 03426 03427 AST_LIST_INSERT_HEAD(&statecbs, cblist, entry); 03428 03429 AST_RWLIST_UNLOCK(&hints); 03430 03431 return 0; 03432 } 03433 03434 if (!context || !exten) 03435 return -1; 03436 03437 /* This callback type is for only one hint, so get the hint */ 03438 e = ast_hint_extension(NULL, context, exten); 03439 if (!e) { 03440 return -1; 03441 } 03442 03443 /* If this is a pattern, dynamically create a new extension for this 03444 * particular match. Note that this will only happen once for each 03445 * individual extension, because the pattern will no longer match first. 03446 */ 03447 if (e->exten[0] == '_') { 03448 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 03449 e->cidmatch, e->app, ast_strdup(e->data), ast_free_ptr, 03450 e->registrar); 03451 e = ast_hint_extension(NULL, context, exten); 03452 if (!e || e->exten[0] == '_') { 03453 return -1; 03454 } 03455 } 03456 03457 /* Find the hint in the list of hints */ 03458 AST_RWLIST_WRLOCK(&hints); 03459 03460 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03461 if (hint->exten == e) 03462 break; 03463 } 03464 03465 if (!hint) { 03466 /* We have no hint, sorry */ 03467 AST_RWLIST_UNLOCK(&hints); 03468 return -1; 03469 } 03470 03471 /* Now insert the callback in the callback list */ 03472 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 03473 AST_RWLIST_UNLOCK(&hints); 03474 return -1; 03475 } 03476 03477 cblist->id = stateid++; /* Unique ID for this callback */ 03478 cblist->callback = callback; /* Pointer to callback routine */ 03479 cblist->data = data; /* Data for the callback */ 03480 03481 AST_LIST_INSERT_HEAD(&hint->callbacks, cblist, entry); 03482 03483 AST_RWLIST_UNLOCK(&hints); 03484 03485 return cblist->id; 03486 }
| int ast_extension_state_del | ( | int | id, | |
| ast_state_cb_type | callback | |||
| ) |
Remove a watcher from the callback list.
Deletes a registered state change callback by ID.
Definition at line 3489 of file pbx.c.
References ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_state_cb::callback, and ast_state_cb::id.
Referenced by dialog_unlink_all(), handle_request_subscribe(), and skinny_unregister().
03490 { 03491 struct ast_state_cb *p_cur = NULL; 03492 int ret = -1; 03493 03494 if (!id && !callback) 03495 return -1; 03496 03497 AST_RWLIST_WRLOCK(&hints); 03498 03499 if (!id) { /* id == 0 is a callback without extension */ 03500 AST_LIST_TRAVERSE_SAFE_BEGIN(&statecbs, p_cur, entry) { 03501 if (p_cur->callback == callback) { 03502 AST_LIST_REMOVE_CURRENT(entry); 03503 break; 03504 } 03505 } 03506 AST_LIST_TRAVERSE_SAFE_END; 03507 } else { /* callback with extension, find the callback based on ID */ 03508 struct ast_hint *hint; 03509 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03510 AST_LIST_TRAVERSE_SAFE_BEGIN(&hint->callbacks, p_cur, entry) { 03511 if (p_cur->id == id) { 03512 AST_LIST_REMOVE_CURRENT(entry); 03513 break; 03514 } 03515 } 03516 AST_LIST_TRAVERSE_SAFE_END; 03517 03518 if (p_cur) 03519 break; 03520 } 03521 } 03522 03523 if (p_cur) { 03524 ast_free(p_cur); 03525 } 03526 03527 AST_RWLIST_UNLOCK(&hints); 03528 03529 return ret; 03530 }
| 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 3651 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().
03652 { 03653 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 03654 }
| 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 3656 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
03657 { 03658 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 03659 }
| 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.
Definition at line 2869 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_custom_function_find(), ast_log(), ast_strdupa, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::read.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
02870 { 02871 char *copy = ast_strdupa(function); 02872 char *args = func_args(copy); 02873 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 02874 02875 if (acfptr == NULL) 02876 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 02877 else if (!acfptr->read) 02878 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 02879 else { 02880 int res; 02881 struct ast_module_user *u = NULL; 02882 if (acfptr->mod) 02883 u = __ast_module_user_add(acfptr->mod, chan); 02884 res = acfptr->read(chan, copy, args, workspace, len); 02885 if (acfptr->mod && u) 02886 __ast_module_user_remove(acfptr->mod, u); 02887 return res; 02888 } 02889 return -1; 02890 }
| 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.
Definition at line 2892 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_custom_function_find(), ast_log(), ast_strdupa, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.
Referenced by pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
02893 { 02894 char *copy = ast_strdupa(function); 02895 char *args = func_args(copy); 02896 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 02897 02898 if (acfptr == NULL) 02899 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 02900 else if (!acfptr->write) 02901 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 02902 else { 02903 int res; 02904 struct ast_module_user *u = NULL; 02905 if (acfptr->mod) 02906 u = __ast_module_user_add(acfptr->mod, chan); 02907 res = acfptr->write(chan, copy, args, value); 02908 if (acfptr->mod && u) 02909 __ast_module_user_remove(acfptr->mod, u); 02910 return res; 02911 } 02912 02913 return -1; 02914 }
| const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 8801 of file pbx.c.
Referenced by _macro_exec(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_lockmacro(), ast_context_remove_include2(), ast_context_remove_switch2(), ast_context_unlockmacro(), ast_context_verify_includes(), 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(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
| const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 8839 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
08840 { 08841 return c ? c->registrar : NULL; 08842 }
| const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 8869 of file pbx.c.
References ast_exten::app.
Referenced by _macro_exec(), ast_add_hint_nolock(), ast_extension_state2(), ast_get_hint(), find_matching_endwhile(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), manager_show_dialplan_helper(), and print_ext().
08870 { 08871 return e ? e->app : NULL; 08872 }
| void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 8874 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().
08875 { 08876 return e ? e->data : NULL; 08877 }
| const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 8864 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
08865 { 08866 return e ? e->cidmatch : NULL; 08867 }
| struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 8806 of file pbx.c.
References ast_exten::parent.
Referenced by handle_show_hint(), and handle_show_hints().
08807 { 08808 return exten ? exten->parent : NULL; 08809 }
| const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 8816 of file pbx.c.
References ast_exten::label.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
08817 { 08818 return exten ? exten->label : NULL; 08819 }
| int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 8859 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
08860 { 08861 return e ? e->matchcid : 0; 08862 }
| const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 8811 of file pbx.c.
References ast_exten::exten.
Referenced by ast_add_hint_nolock(), complete_core_show_hint(), complete_dialplan_remove_extension(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), manager_show_dialplan_helper(), and show_dialplan_helper().
08812 { 08813 return exten ? exten->exten : NULL; 08814 }
| int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 8831 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().
08832 { 08833 return exten ? exten->priority : -1; 08834 }
| const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 8844 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
08845 { 08846 return e ? e->registrar : NULL; 08847 }
| 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 3629 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(), pbx_retrieve_variable(), skinny_extensionstate_cb(), and transmit_state_notify().
03630 { 03631 struct ast_exten *e = ast_hint_extension(c, context, exten); 03632 03633 if (e) { 03634 if (hint) 03635 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 03636 if (name) { 03637 const char *tmp = ast_get_extension_app_data(e); 03638 if (tmp) 03639 ast_copy_string(name, tmp, namesize); 03640 } 03641 return -1; 03642 } 03643 return 0; 03644 }
| const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 8826 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().
08827 { 08828 return ip ? ip->pattern : NULL; 08829 }
| const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 8854 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().
08855 { 08856 return ip ? ip->registrar : NULL; 08857 }
| const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 8821 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().
08822 { 08823 return inc ? inc->name : NULL; 08824 }
| const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 8849 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().
08850 { 08851 return i ? i->registrar : NULL; 08852 }
| const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 8884 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().
08885 { 08886 return sw ? sw->data : NULL; 08887 }
| int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 8889 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
08890 { 08891 return sw->eval; 08892 }
| const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 8879 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().
08880 { 08881 return sw ? sw->name : NULL; 08882 }
| const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 8894 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().
08895 { 08896 return sw ? sw->registrar : NULL; 08897 }
| int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 8987 of file pbx.c.
References __ast_goto_if_exists().
Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), goto_exten(), onedigit_goto(), priority_jump(), select_entry(), and valid_exit().
08988 { 08989 return __ast_goto_if_exists(chan, context, exten, priority, 0); 08990 }
| int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
| const void * | ah_b | |||
| ) |
Definition at line 351 of file pbx.c.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
00352 { 00353 const struct ast_context *ac = ah_a; 00354 const struct ast_context *bc = ah_b; 00355 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 00356 return 1; 00357 /* assume context names are registered in a string table! */ 00358 return strcmp(ac->name, bc->name); 00359 }
| unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 394 of file pbx.c.
References ast_hashtab_hash_string().
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
00395 { 00396 const struct ast_context *ac = obj; 00397 return ast_hashtab_hash_string(ac->name); 00398 }
| static struct ast_exten* ast_hint_extension | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten | |||
| ) | [static, read] |
Definition at line 3267 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(), and ast_get_hint().
03268 { 03269 struct ast_exten *e; 03270 ast_rdlock_contexts(); 03271 e = ast_hint_extension_nolock(c, context, exten); 03272 ast_unlock_contexts(); 03273 return e; 03274 }
| 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 3261 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().
03262 { 03263 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 03264 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 03265 }
| 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 6712 of file pbx.c.
References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.
Referenced by ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_enbloc_call_message(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), skinny_ss(), and ss_thread().
06713 { 06714 struct ast_context *con = ast_context_find(context); 06715 if (con) { 06716 struct ast_ignorepat *pat; 06717 for (pat = con->ignorepats; pat; pat = pat->next) { 06718 if (ast_extension_match(pat->pattern, pattern)) 06719 return 1; 06720 } 06721 } 06722 06723 return 0; 06724 }
| AST_LIST_HEAD | ( | store_hints | , | |
| store_hint | ||||
| ) |
| static AST_LIST_HEAD_NOLOCK_STATIC | ( | statecbs | , | |
| ast_state_cb | ||||
| ) | [static] |
| 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 3666 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by __ast_pbx_run(), ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), pri_dchannel(), readexten_exec(), skinny_ss(), and ss_thread().
03667 { 03668 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 03669 }
| 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 6071 of file pbx.c.
References __ast_internal_context_destroy(), 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_APPEND_LIST, AST_LIST_EMPTY, AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_log(), ast_rdlock_contexts(), AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), ast_wrlock_contexts_version(), ast_state_cb::callback, context_merge(), ast_state_cb::data, ast_exten::data, E_MATCH, ast_exten::exten, ast_hint::exten, ast_hint::laststate, LOG_WARNING, ast_context::next, 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().
06072 { 06073 double ft; 06074 struct ast_context *tmp, *oldcontextslist; 06075 struct ast_hashtab *oldtable; 06076 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 06077 struct store_hint *this; 06078 struct ast_hint *hint; 06079 struct ast_exten *exten; 06080 int length; 06081 struct ast_state_cb *thiscb; 06082 struct ast_hashtab_iter *iter; 06083 06084 /* it is very important that this function hold the hint list lock _and_ the conlock 06085 during its operation; not only do we need to ensure that the list of contexts 06086 and extensions does not change, but also that no hint callbacks (watchers) are 06087 added or removed during the merge/delete process 06088 06089 in addition, the locks _must_ be taken in this order, because there are already 06090 other code paths that use this order 06091 */ 06092 06093 struct timeval begintime, writelocktime, endlocktime, enddeltime; 06094 int wrlock_ver; 06095 06096 begintime = ast_tvnow(); 06097 ast_rdlock_contexts(); 06098 iter = ast_hashtab_start_traversal(contexts_table); 06099 while ((tmp = ast_hashtab_next(iter))) { 06100 context_merge(extcontexts, exttable, tmp, registrar); 06101 } 06102 ast_hashtab_end_traversal(iter); 06103 wrlock_ver = ast_wrlock_contexts_version(); 06104 06105 ast_unlock_contexts(); /* this feels real retarded, but you must do 06106 what you must do If this isn't done, the following 06107 wrlock is a guraranteed deadlock */ 06108 ast_wrlock_contexts(); 06109 if (ast_wrlock_contexts_version() > wrlock_ver+1) { 06110 ast_log(LOG_WARNING,"==================!!!!!!!!!!!!!!!Something changed the contexts in the middle of merging contexts!\n"); 06111 } 06112 06113 AST_RWLIST_WRLOCK(&hints); 06114 writelocktime = ast_tvnow(); 06115 06116 /* preserve all watchers for hints */ 06117 AST_RWLIST_TRAVERSE(&hints, hint, list) { 06118 if (!AST_LIST_EMPTY(&hint->callbacks)) { 06119 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 06120 if (!(this = ast_calloc(1, length))) 06121 continue; 06122 /* this removes all the callbacks from the hint into this. */ 06123 AST_LIST_APPEND_LIST(&this->callbacks, &hint->callbacks, entry); 06124 this->laststate = hint->laststate; 06125 this->context = this->data; 06126 strcpy(this->data, hint->exten->parent->name); 06127 this->exten = this->data + strlen(this->context) + 1; 06128 strcpy(this->exten, hint->exten->exten); 06129 AST_LIST_INSERT_HEAD(&store, this, list); 06130 } 06131 } 06132 06133 /* save the old table and list */ 06134 oldtable = contexts_table; 06135 oldcontextslist = contexts; 06136 06137 /* move in the new table and list */ 06138 contexts_table = exttable; 06139 contexts = *extcontexts; 06140 06141 /* restore the watchers for hints that can be found; notify those that 06142 cannot be restored 06143 */ 06144 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 06145 struct pbx_find_info q = { .stacklen = 0 }; 06146 exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH); 06147 /* If this is a pattern, dynamically create a new extension for this 06148 * particular match. Note that this will only happen once for each 06149 * individual extension, because the pattern will no longer match first. 06150 */ 06151 if (exten && exten->exten[0] == '_') { 06152 ast_add_extension_nolock(exten->parent->name, 0, this->exten, PRIORITY_HINT, NULL, 06153 0, exten->app, ast_strdup(exten->data), ast_free_ptr, exten->registrar); 06154 /* rwlocks are not recursive locks */ 06155 exten = ast_hint_extension_nolock(NULL, this->context, this->exten); 06156 } 06157 06158 /* Find the hint in the list of hints */ 06159 AST_RWLIST_TRAVERSE(&hints, hint, list) { 06160 if (hint->exten == exten) 06161 break; 06162 } 06163 if (!exten || !hint) { 06164 /* this hint has been removed, notify the watchers */ 06165 while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) { 06166 thiscb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, thiscb->data); 06167 ast_free(thiscb); 06168 } 06169 } else { 06170 AST_LIST_APPEND_LIST(&hint->callbacks, &this->callbacks, entry); 06171 hint->laststate = this->laststate; 06172 } 06173 ast_free(this); 06174 } 06175 06176 AST_RWLIST_UNLOCK(&hints); 06177 ast_unlock_contexts(); 06178 endlocktime = ast_tvnow(); 06179 06180 /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk 06181 is now freely using the new stuff instead */ 06182 06183 ast_hashtab_destroy(oldtable, NULL); 06184 06185 for (tmp = oldcontextslist; tmp; ) { 06186 struct ast_context *next; /* next starting point */ 06187 next = tmp->next; 06188 __ast_internal_context_destroy(tmp); 06189 tmp = next; 06190 } 06191 enddeltime = ast_tvnow(); 06192 06193 ft = ast_tvdiff_us(writelocktime, begintime); 06194 ft /= 1000000.0; 06195 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 06196 06197 ft = ast_tvdiff_us(endlocktime, writelocktime); 06198 ft /= 1000000.0; 06199 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 06200 06201 ft = ast_tvdiff_us(enddeltime, endlocktime); 06202 ft /= 1000000.0; 06203 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 06204 06205 ft = ast_tvdiff_us(enddeltime, begintime); 06206 ft /= 1000000.0; 06207 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 06208 return; 06209 }
| AST_MUTEX_DEFINE_STATIC | ( | maxcalllock | ) |
| int ast_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 9050 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().
09051 { 09052 return pbx_parseable_goto(chan, goto_string, 0); 09053 }
| int ast_pbx_outgoing_app | ( | const char * | type, | |
| int | 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 7548 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, app_tmp::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_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, app_tmp::data, 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(), and orig_app().
07549 { 07550 struct ast_channel *chan; 07551 struct app_tmp *tmp; 07552 int res = -1, cdr_res = -1; 07553 struct outgoing_helper oh; 07554 07555 memset(&oh, 0, sizeof(oh)); 07556 oh.vars = vars; 07557 oh.account = account; 07558 07559 if (locked_channel) 07560 *locked_channel = NULL; 07561 if (ast_strlen_zero(app)) { 07562 res = -1; 07563 goto outgoing_app_cleanup; 07564 } 07565 if (synchronous) { 07566 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07567 if (chan) { 07568 ast_set_variables(chan, vars); 07569 if (account) 07570 ast_cdr_setaccount(chan, account); 07571 if (chan->_state == AST_STATE_UP) { 07572 res = 0; 07573 ast_verb(4, "Channel %s was answered.\n", chan->name); 07574 tmp = ast_calloc(1, sizeof(*tmp)); 07575 if (!tmp) 07576 res = -1; 07577 else { 07578 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 07579 if (appdata) 07580 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 07581 tmp->chan = chan; 07582 if (synchronous > 1) { 07583 if (locked_channel) 07584 ast_channel_unlock(chan); 07585 ast_pbx_run_app(tmp); 07586 } else { 07587 if (locked_channel) 07588 ast_channel_lock(chan); 07589 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 07590 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 07591 ast_free(tmp); 07592 if (locked_channel) 07593 ast_channel_unlock(chan); 07594 ast_hangup(chan); 07595 res = -1; 07596 } else { 07597 if (locked_channel) 07598 *locked_channel = chan; 07599 } 07600 } 07601 } 07602 } else { 07603 ast_verb(4, "Channel %s was never answered.\n", chan->name); 07604 if (chan->cdr) { /* update the cdr */ 07605 /* here we update the status of the call, which sould be busy. 07606 * if that fails then we set the status to failed */ 07607 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 07608 ast_cdr_failed(chan->cdr); 07609 } 07610 ast_hangup(chan); 07611 } 07612 } 07613 07614 if (res < 0) { /* the call failed for some reason */ 07615 if (*reason == 0) { /* if the call failed (not busy or no answer) 07616 * update the cdr with the failed message */ 07617 cdr_res = ast_pbx_outgoing_cdr_failed(); 07618 if (cdr_res != 0) { 07619 res = cdr_res; 07620 goto outgoing_app_cleanup; 07621 } 07622 } 07623 } 07624 07625 } else { 07626 struct async_stat *as; 07627 if (!(as = ast_calloc(1, sizeof(*as)))) { 07628 res = -1; 07629 goto outgoing_app_cleanup; 07630 } 07631 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07632 if (!chan) { 07633 ast_free(as); 07634 res = -1; 07635 goto outgoing_app_cleanup; 07636 } 07637 as->chan = chan; 07638 ast_copy_string(as->app, app, sizeof(as->app)); 07639 if (appdata) 07640 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 07641 as->timeout = timeout; 07642 ast_set_variables(chan, vars); 07643 if (account) 07644 ast_cdr_setaccount(chan, account); 07645 /* Start a new thread, and get something handling this channel. */ 07646 if (locked_channel) 07647 ast_channel_lock(chan); 07648 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 07649 ast_log(LOG_WARNING, "Failed to start async wait\n"); 07650 ast_free(as); 07651 if (locked_channel) 07652 ast_channel_unlock(chan); 07653 ast_hangup(chan); 07654 res = -1; 07655 goto outgoing_app_cleanup; 07656 } else { 07657 if (locked_channel) 07658 *locked_channel = chan; 07659 } 07660 res = 0; 07661 } 07662 outgoing_app_cleanup: 07663 ast_variables_destroy(vars); 07664 return res; 07665 }
| static int ast_pbx_outgoing_cdr_failed | ( | void | ) | [static] |
Function to post an empty cdr after a spool call fails.
Definition at line 7356 of file pbx.c.
References ast_cdr_detach(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_start(), ast_channel_alloc, ast_channel_free(), AST_STATE_DOWN, and ast_channel::cdr.
Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
07357 { 07358 /* allocate a channel */ 07359 struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", ""); 07360 07361 if (!chan) 07362 return -1; /* failure */ 07363 07364 if (!chan->cdr) { 07365 /* allocation of the cdr failed */ 07366 ast_channel_free(chan); /* free the channel */ 07367 return -1; /* return failure */ 07368 } 07369 07370 /* allocation of the cdr was successful */ 07371 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 07372 ast_cdr_start(chan->cdr); /* record the start and stop time */ 07373 ast_cdr_end(chan->cdr); 07374 ast_cdr_failed(chan->cdr); /* set the status to failed */ 07375 ast_cdr_detach(chan->cdr); /* post and free the record */ 07376 chan->cdr = NULL; 07377 ast_channel_free(chan); /* free the channel */ 07378 07379 return 0; /* success */ 07380 }
| int ast_pbx_outgoing_exten | ( | const char * | type, | |
| int | 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 7382 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(), and orig_exten().
07383 { 07384 struct ast_channel *chan; 07385 struct async_stat *as; 07386 int res = -1, cdr_res = -1; 07387 struct outgoing_helper oh; 07388 07389 if (synchronous) { 07390 oh.context = context; 07391 oh.exten = exten; 07392 oh.priority = priority; 07393 oh.cid_num = cid_num; 07394 oh.cid_name = cid_name; 07395 oh.account = account; 07396 oh.vars = vars; 07397 oh.parent_channel = NULL; 07398 07399 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07400 if (channel) { 07401 *channel = chan; 07402 if (chan) 07403 ast_channel_lock(chan); 07404 } 07405 if (chan) { 07406 if (chan->_state == AST_STATE_UP) { 07407 res = 0; 07408 ast_verb(4, "Channel %s was answered.\n", chan->name); 07409 07410 if (synchronous > 1) { 07411 if (channel) 07412 ast_channel_unlock(chan); 07413 if (ast_pbx_run(chan)) { 07414 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 07415 if (channel) 07416 *channel = NULL; 07417 ast_hangup(chan); 07418 chan = NULL; 07419 res = -1; 07420 } 07421 } else { 07422 if (ast_pbx_start(chan)) { 07423 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 07424 if (channel) { 07425 *channel = NULL; 07426 ast_channel_unlock(chan); 07427 } 07428 ast_hangup(chan); 07429 res = -1; 07430 } 07431 chan = NULL; 07432 } 07433 } else { 07434 ast_verb(4, "Channel %s was never answered.\n", chan->name); 07435 07436 if (chan->cdr) { /* update the cdr */ 07437 /* here we update the status of the call, which sould be busy. 07438 * if that fails then we set the status to failed */ 07439 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 07440 ast_cdr_failed(chan->cdr); 07441 } 07442 07443 if (channel) { 07444 *channel = NULL; 07445 ast_channel_unlock(chan); 07446 } 07447 ast_hangup(chan); 07448 chan = NULL; 07449 } 07450 } 07451 07452 if (res < 0) { /* the call failed for some reason */ 07453 if (*reason == 0) { /* if the call failed (not busy or no answer) 07454 * update the cdr with the failed message */ 07455 cdr_res = ast_pbx_outgoing_cdr_failed(); 07456 if (cdr_res != 0) { 07457 res = cdr_res; 07458 goto outgoing_exten_cleanup; 07459 } 07460 } 07461 07462 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 07463 /* check if "failed" exists */ 07464 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 07465 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed"); 07466 if (chan) { 07467 char failed_reason[4] = ""; 07468 if (!ast_strlen_zero(context)) 07469 ast_copy_string(chan->context, context, sizeof(chan->context)); 07470 set_ext_pri(chan, "failed", 1); 07471 ast_set_variables(chan, vars); 07472 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 07473 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 07474 if (account) 07475 ast_cdr_setaccount(chan, account); 07476 if (ast_pbx_run(chan)) { 07477 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 07478 ast_hangup(chan); 07479 } 07480 chan = NULL; 07481 } 07482 } 07483 } 07484 } else { 07485 if (!(as = ast_calloc(1, sizeof(*as)))) { 07486 res = -1; 07487 goto outgoing_exten_cleanup; 07488 } 07489 chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name); 07490 if (channel) { 07491 *channel = chan; 07492 if (chan) 07493 ast_channel_lock(chan); 07494 } 07495 if (!chan) { 07496 ast_free(as); 07497 res = -1; 07498 goto outgoing_exten_cleanup; 07499 } 07500 as->chan = chan; 07501 ast_copy_string(as->context, context, sizeof(as->context)); 07502 set_ext_pri(as->chan, exten, priority); 07503 as->timeout = timeout; 07504 ast_set_variables(chan, vars); 07505 if (account) 07506 ast_cdr_setaccount(chan, account); 07507 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 07508 ast_log(LOG_WARNING, "Failed to start async wait\n"); 07509 ast_free(as); 07510 if (channel) { 07511 *channel = NULL; 07512 ast_channel_unlock(chan); 07513 } 07514 ast_hangup(chan); 07515 res = -1; 07516 goto outgoing_exten_cleanup; 07517 } 07518 res = 0; 07519 } 07520 outgoing_exten_cleanup: 07521 ast_variables_destroy(vars); 07522 return res; 07523 }
| 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 4094 of file pbx.c.
References ast_pbx_run_args().
Referenced by ast_pbx_outgoing_exten(), async_wait(), do_idle_thread(), mgcp_ss(), skinny_newcall(), ss_thread(), and unistim_ss().
04095 { 04096 return ast_pbx_run_args(c, NULL); 04097 }
| static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 7533 of file pbx.c.
References app_tmp::app, ast_free, ast_hangup(), ast_log(), ast_verb, app_tmp::chan, app_tmp::data, LOG_WARNING, pbx_exec(), and pbx_findapp().
Referenced by ast_pbx_outgoing_app().
07534 { 07535 struct app_tmp *tmp = data; 07536 struct ast_app *app; 07537 app = pbx_findapp(tmp->app); 07538 if (app) { 07539 ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 07540 pbx_exec(tmp->chan, app, tmp->data); 07541 } else 07542 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 07543 ast_hangup(tmp->chan); 07544 ast_free(tmp); 07545 return NULL; 07546 }
| 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 4079 of file pbx.c.
References __ast_pbx_run(), AST_PBX_CALL_LIMIT, AST_PBX_SUCCESS, decrease_call_count(), and increase_call_count().
Referenced by ast_pbx_run(), dial_exec_full(), handle_gosub(), and try_calling().
04080 { 04081 enum ast_pbx_result res = AST_PBX_SUCCESS; 04082 04083 if (increase_call_count(c)) { 04084 return AST_PBX_CALL_LIMIT; 04085 } 04086 04087 res = __ast_pbx_run(c, args); 04088 04089 decrease_call_count(); 04090 04091 return res; 04092 }
| 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 4057 of file pbx.c.
References ast_log(), AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, decrease_call_count(), increase_call_count(), LOG_WARNING, and pbx_thread().
Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_bridge_call_thread(), ast_iax2_new(), ast_pbx_outgoing_exten(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), manage_parkinglot(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), pri_dchannel(), rpt_call(), sip_new(), skinny_new(), unistim_new(), and usbradio_new().
04058 { 04059 pthread_t t; 04060 04061 if (!c) { 04062 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 04063 return AST_PBX_FAILED; 04064 } 04065 04066 if (increase_call_count(c)) 04067 return AST_PBX_CALL_LIMIT; 04068 04069 /* Start a new thread, and get something handling this channel. */ 04070 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 04071 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 04072 decrease_call_count(); 04073 return AST_PBX_FAILED; 04074 } 04075 04076 return AST_PBX_SUCCESS; 04077 }
| int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 4104 of file pbx.c.
Referenced by handle_chanlist(), and handle_showcalls().
04105 { 04106 return totalcalls; 04107 }
| 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 8788 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().
08789 { 08790 return ast_rwlock_rdlock(&con->lock); 08791 }
| int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 8770 of file pbx.c.
References ast_rwlock_rdlock().
Referenced by _macro_exec(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), 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(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
08771 { 08772 return ast_rwlock_rdlock(&conlock); 08773 }
| int ast_register_application2 | ( | const char * | app, | |
| int(*)(struct ast_channel *, void *) | execute, | |||
| const char * | synopsis, | |||
| const char * | description, | |||
| void * | mod | |||
| ) |
Dynamically register a new dial plan application.
Register an application.
Definition at line 4558 of file pbx.c.
References ast_calloc, 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_verb, COLOR_BRCYAN, ast_app::description, ast_app::execute, LOG_WARNING, ast_app::synopsis, and term_color().
Referenced by ast_features_init(), and load_pbx().
04559 { 04560 struct ast_app *tmp, *cur = NULL; 04561 char tmps[80]; 04562 int length, res; 04563 04564 AST_RWLIST_WRLOCK(&apps); 04565 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 04566 if (!(res = strcasecmp(app, tmp->name))) { 04567 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 04568 AST_RWLIST_UNLOCK(&apps); 04569 return -1; 04570 } else if (res < 0) 04571 break; 04572 } 04573 04574 length = sizeof(*tmp) + strlen(app) + 1; 04575 04576 if (!(tmp = ast_calloc(1, length))) { 04577 AST_RWLIST_UNLOCK(&apps); 04578 return -1; 04579 } 04580 04581 strcpy(tmp->name, app); 04582 tmp->execute = execute; 04583 tmp->synopsis = synopsis; 04584 tmp->description = description; 04585 tmp->module = mod; 04586 04587 /* Store in alphabetical order */ 04588 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 04589 if (strcasecmp(tmp->name, cur->name) < 0) { 04590 AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list); 04591 break; 04592 } 04593 } 04594 AST_RWLIST_TRAVERSE_SAFE_END; 04595 if (!cur) 04596 AST_RWLIST_INSERT_TAIL(&apps, tmp, list); 04597 04598 ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 04599 04600 AST_RWLIST_UNLOCK(&apps); 04601 04602 return 0; 04603 }
| 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.
Definition at line 4609 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().
04610 { 04611 struct ast_switch *tmp; 04612 04613 AST_RWLIST_WRLOCK(&switches); 04614 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 04615 if (!strcasecmp(tmp->name, sw->name)) { 04616 AST_RWLIST_UNLOCK(&switches); 04617 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 04618 return -1; 04619 } 04620 } 04621 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 04622 AST_RWLIST_UNLOCK(&switches); 04623 04624 return 0; 04625 }
| static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
Remove hint from extension.
Definition at line 3594 of file pbx.c.
References AST_EXTENSION_DEACTIVATED, ast_free, AST_LIST_REMOVE_HEAD, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, ast_state_cb::callback, ast_state_cb::data, ast_exten::exten, ast_hint::exten, and ast_exten::parent.
Referenced by destroy_exten().
03595 { 03596 /* Cleanup the Notifys if hint is removed */ 03597 struct ast_hint *hint; 03598 struct ast_state_cb *cblist; 03599 int res = -1; 03600 03601 if (!e) 03602 return -1; 03603 03604 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) { 03605 if (hint->exten != e) 03606 continue; 03607 03608 while ((cblist = AST_LIST_REMOVE_HEAD(&hint->callbacks, entry))) { 03609 /* Notify with -1 and remove all callbacks */ 03610 cblist->callback(hint->exten->parent->name, hint->exten->exten, 03611 AST_EXTENSION_DEACTIVATED, cblist->data); 03612 ast_free(cblist); 03613 } 03614 03615 AST_RWLIST_REMOVE_CURRENT(list); 03616 ast_free(hint); 03617 03618 res = 0; 03619 03620 break; 03621 } 03622 AST_RWLIST_TRAVERSE_SAFE_END; 03623 03624 return res; 03625 }
| static AST_RWLIST_HEAD_STATIC | ( | hints | , | |
| ast_hint | ||||
| ) | [static] |
| static AST_RWLIST_HEAD_STATIC | ( | switches | , | |
| ast_switch | ||||
| ) | [static] |
| static AST_RWLIST_HEAD_STATIC | ( | apps | , | |
| ast_app | ||||
| ) | [static] |
| static AST_RWLIST_HEAD_STATIC | ( | acf_root | , | |
| ast_custom_function | ||||
| ) | [static] |
| AST_RWLOCK_DEFINE_STATIC | ( | conlock | ) |
Lock for the ast_context list
| AST_RWLOCK_DEFINE_STATIC | ( | globalslock | ) |
| 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 3671 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().
03672 { 03673 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 03674 }
| AST_THREADSTORAGE | ( | switch_data | ) |
| 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 8793 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().
08794 { 08795 return ast_rwlock_unlock(&con->lock); 08796 }
| int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
| 0 | on success | |
| -1 | on failure |
Definition at line 8775 of file pbx.c.
References ast_rwlock_unlock().
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(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
08776 { 08777 return ast_rwlock_unlock(&conlock); 08778 }
| 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 5852 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_verb, and unreference_cached_app().
Referenced by __unload_module(), load_module(), and unload_module().
05853 { 05854 struct ast_app *tmp; 05855 05856 AST_RWLIST_WRLOCK(&apps); 05857 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 05858 if (!strcasecmp(app, tmp->name)) { 05859 unreference_cached_app(tmp); 05860 AST_RWLIST_REMOVE_CURRENT(list); 05861 ast_verb(2, "Unregistered application '%s'\n", tmp->name); 05862 ast_free(tmp); 05863 break; 05864 } 05865 } 05866 AST_RWLIST_TRAVERSE_SAFE_END; 05867 AST_RWLIST_UNLOCK(&apps); 05868 05869 return tmp ? 0 : -1; 05870 }
| void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
| sw | switch to unregister |
Unregisters a switch from asterisk.
Definition at line 4627 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
04628 { 04629 AST_RWLIST_WRLOCK(&switches); 04630 AST_RWLIST_REMOVE(&switches, sw, list); 04631 AST_RWLIST_UNLOCK(&switches); 04632 }
| struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
| struct ast_exten * | exten | |||
| ) | [read] |
Definition at line 8907 of file pbx.c.
References ast_exten::next, and ast_context::root.
Referenced by complete_dialplan_remove_extension(), 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 8940 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(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
08942 { 08943 if (!ip) 08944 return con ? con->ignorepats : NULL; 08945 else 08946 return ip->next; 08947 }
| struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
| struct ast_include * | inc | |||
| ) | [read] |
Definition at line 8931 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(), 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 8916 of file pbx.c.
References AST_LIST_FIRST, and AST_LIST_NEXT.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
08918 { 08919 if (!sw) 08920 return con ? AST_LIST_FIRST(&con->alts) : NULL; 08921 else 08922 return AST_LIST_NEXT(sw, list); 08923 }
| struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 8902 of file pbx.c.
References ast_context::next.
Referenced by _macro_exec(), ast_context_find(), ast_context_lockmacro(), ast_context_unlockmacro(), 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(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), 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 8925 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(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
08927 { 08928 return priority ? priority->peer : exten; 08929 }
| 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 8783 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().
08784 { 08785 return ast_rwlock_wrlock(&con->lock); 08786 }
| int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 8762 of file pbx.c.
References ast_atomic_fetchadd_int(), ast_rwlock_wrlock(), and conlock_wrlock_version.
Referenced by ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and complete_dialplan_remove_include().
08763 { 08764 int res = ast_rwlock_wrlock(&conlock); 08765 if (!res) 08766 ast_atomic_fetchadd_int(&conlock_wrlock_version, 1); 08767 return res; 08768 }
| int ast_wrlock_contexts_version | ( | void | ) |
Definition at line 8754 of file pbx.c.
References conlock_wrlock_version.
Referenced by ast_merge_contexts_and_delete().
08755 { 08756 return conlock_wrlock_version; 08757 }
| static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 7295 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_STATE_UP, ast_strlen_zero(), ast_verb, ast_waitfor(), async_stat::chan, ast_channel::context, async_stat::context, ast_channel::exten, async_stat::exten, f, ast_frame::frametype, 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().
07296 { 07297 struct async_stat *as = data; 07298 struct ast_channel *chan = as->chan; 07299 int timeout = as->timeout; 07300 int res; 07301 struct ast_frame *f; 07302 struct ast_app *app; 07303 07304 while (timeout && (chan->_state != AST_STATE_UP)) { 07305 res = ast_waitfor(chan, timeout); 07306 if (res < 1) 07307 break; 07308 if (timeout > -1) 07309 timeout = res; 07310 f = ast_read(chan); 07311 if (!f) 07312 break; 07313 if (f->frametype == AST_FRAME_CONTROL) { 07314 if ((f->subclass == AST_CONTROL_BUSY) || 07315 (f->subclass == AST_CONTROL_CONGESTION) ) { 07316 ast_frfree(f); 07317 break; 07318 } 07319 } 07320 ast_frfree(f); 07321 } 07322 if (chan->_state == AST_STATE_UP) { 07323 if (!ast_strlen_zero(as->app)) { 07324 app = pbx_findapp(as->app); 07325 if (app) { 07326 ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 07327 pbx_exec(chan, app, as->appdata); 07328 } else 07329 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 07330 } else { 07331 if (!ast_strlen_zero(as->context)) 07332 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 07333 if (!ast_strlen_zero(as->exten)) 07334 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 07335 if (as->priority > 0) 07336 chan->priority = as->priority; 07337 /* Run the PBX */ 07338 if (ast_pbx_run(chan)) { 07339 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 07340 } else { 07341 /* PBX will have taken care of this */ 07342 chan = NULL; 07343 } 07344 } 07345 } 07346 ast_free(as); 07347 if (chan) 07348 ast_hangup(chan); 07349 return NULL; 07350 }
| static void cli_match_char_tree | ( | struct match_char * | node, | |
| char * | prefix, | |||
| int | fd | |||
| ) | [static] |
Definition at line 1135 of file pbx.c.
References match_char::alt_char, ast_cli(), ast_str_alloca, ast_str_set(), match_char::deleted, ast_exten::exten, match_char::exten, match_char::is_pattern, match_char::next_char, match_char::specificity, ast_str::str, and match_char::x.
Referenced by show_debug_helper().
01136 { 01137 char extenstr[40]; 01138 struct ast_str *my_prefix = ast_str_alloca(1024); 01139 01140 extenstr[0] = '\0'; 01141 01142 if (node && node->exten && node->exten) 01143 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01144 01145 if (strlen(node->x) > 1) { 01146 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01147 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01148 node->exten ? node->exten->exten : "", extenstr); 01149 } else { 01150 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01151 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01152 node->exten ? node->exten->exten : "", extenstr); 01153 } 01154 01155 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01156 01157 if (node->next_char) 01158 cli_match_char_tree(node->next_char, my_prefix->str, fd); 01159 01160 if (node->alt_char) 01161 cli_match_char_tree(node->alt_char, prefix, fd); 01162 }
| 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.
| 0 | on timeout or done. | |
| -1 | on error. |
Definition at line 3690 of file pbx.c.
References ast_channel::_softhangup, ast_matchmore_extension(), AST_SOFTHANGUP_ASYNCGOTO, ast_waitfordigit(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_pbx::dtimeoutms, and ast_channel::pbx.
Referenced by __ast_pbx_run().
03691 { 03692 int digit; 03693 03694 buf[pos] = '\0'; /* make sure it is properly terminated */ 03695 while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) { 03696 /* As long as we're willing to wait, and as long as it's not defined, 03697 keep reading digits until we can't possibly get a right answer anymore. */ 03698 digit = ast_waitfordigit(c, waittime); 03699 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 03700 c->_softhangup = 0; 03701 } else { 03702 if (!digit) /* No entry */ 03703 break; 03704 if (digit < 0) /* Error, maybe a hangup */ 03705 return -1; 03706 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 03707 buf[pos++] = digit; 03708 buf[pos] = '\0'; 03709 } 03710 waittime = c->pbx->dtimeoutms; 03711 } 03712 } 03713 return 0; 03714 }
| static int compare_char | ( | const void * | a, | |
| const void * | b | |||
| ) | [static] |
Definition at line 338 of file pbx.c.
Referenced by add_exten_to_pattern_tree().
| 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 4787 of file pbx.c.
References ast_get_extension_name(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, and ast_hint::exten.
Referenced by handle_show_hint().
04788 { 04789 struct ast_hint *hint; 04790 char *ret = NULL; 04791 int which = 0; 04792 int wordlen; 04793 04794 if (pos != 3) 04795 return NULL; 04796 04797 wordlen = strlen(word); 04798 04799 AST_RWLIST_RDLOCK(&hints); 04800 /* walk through all hints */ 04801 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04802 if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) { 04803 ret = ast_strdup(ast_get_extension_name(hint->exten)); 04804 break; 04805 } 04806 } 04807 AST_RWLIST_UNLOCK(&hints); 04808 04809 return ret; 04810 }
| static char* complete_show_dialplan_context | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 4983 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().
04985 { 04986 struct ast_context *c = NULL; 04987 char *ret = NULL; 04988 int which = 0; 04989 int wordlen; 04990 04991 /* we are do completion of [exten@]context on second position only */ 04992 if (pos != 2) 04993 return NULL; 04994 04995 ast_rdlock_contexts(); 04996 04997 wordlen = strlen(word); 04998 04999 /* walk through all contexts and return the n-th match */ 05000 while ( (c = ast_walk_contexts(c)) ) { 05001 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 05002 ret = ast_strdup(ast_get_context_name(c)); 05003 break; 05004 } 05005 } 05006 05007 ast_unlock_contexts(); 05008 05009 return ret; 05010 }
| static void context_merge | ( | struct ast_context ** | extcontexts, | |
| struct ast_hashtab * | exttable, | |||
| struct ast_context * | context, | |||
| const char * | registrar | |||
| ) | [static] |
Definition at line 5987 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::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().
05988 { 05989 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */ 05990 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item; 05991 struct ast_hashtab_iter *exten_iter; 05992 struct ast_hashtab_iter *prio_iter; 05993 int insert_count = 0; 05994 int first = 1; 05995 05996 /* We'll traverse all the extensions/prios, and see which are not registrar'd with 05997 the current registrar, and copy them to the new context. If the new context does not 05998 exist, we'll create it "on demand". If no items are in this context to copy, then we'll 05999 only create the empty matching context if the old one meets the criteria */ 06000 06001 if (context->root_table) { 06002 exten_iter = ast_hashtab_start_traversal(context->root_table); 06003 while ((exten_item=ast_hashtab_next(exten_iter))) { 06004 if (new) { 06005 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item); 06006 } else { 06007 new_exten_item = NULL; 06008 } 06009 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 06010 while ((prio_item=ast_hashtab_next(prio_iter))) { 06011 int res1; 06012 char *dupdstr; 06013 06014 if (new_exten_item) { 06015 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item); 06016 } else { 06017 new_prio_item = NULL; 06018 } 06019 if (strcmp(prio_item->registrar,registrar) == 0) { 06020 continue; 06021 } 06022 /* make sure the new context exists, so we have somewhere to stick this exten/prio */ 06023 if (!new) { 06024 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 */ 06025 } 06026 06027 /* copy in the includes, switches, and ignorepats */ 06028 if (first) { /* but, only need to do this once */ 06029 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 06030 first = 0; 06031 } 06032 06033 if (!new) { 06034 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name); 06035 return; /* no sense continuing. */ 06036 } 06037 /* we will not replace existing entries in the new context with stuff from the old context. 06038 but, if this is because of some sort of registrar conflict, we ought to say something... */ 06039 06040 dupdstr = ast_strdup(prio_item->data); 06041 06042 res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 06043 prio_item->cidmatch, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar); 06044 if (!res1 && new_exten_item && new_prio_item){ 06045 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n", 06046 context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar); 06047 } else { 06048 /* 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, 06049 and no double frees take place, either! */ 06050 insert_count++; 06051 } 06052 } 06053 ast_hashtab_end_traversal(prio_iter); 06054 } 06055 ast_hashtab_end_traversal(exten_iter); 06056 } 06057 06058 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 || 06059 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) { 06060 /* we could have given it the registrar of the other module who incremented the refcount, 06061 but that's not available, so we give it the registrar we know about */ 06062 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar); 06063 06064 /* copy in the includes, switches, and ignorepats */ 06065 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 06066 } 06067 }
| static void context_merge_incls_swits_igps_other_registrars | ( | struct ast_context * | new, | |
| struct ast_context * | old, | |||
| const char * | registrar | |||
| ) | [static] |
Definition at line 5954 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().
05955 { 05956 struct ast_include *i; 05957 struct ast_ignorepat *ip; 05958 struct ast_sw *sw; 05959 05960 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); 05961 /* copy in the includes, switches, and ignorepats */ 05962 /* walk through includes */ 05963 for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) { 05964 if (strcmp(ast_get_include_registrar(i), registrar) == 0) 05965 continue; /* not mine */ 05966 ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i)); 05967 } 05968 05969 /* walk through switches */ 05970 for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) { 05971 if (strcmp(ast_get_switch_registrar(sw), registrar) == 0) 05972 continue; /* not mine */ 05973 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)); 05974 } 05975 05976 /* walk thru ignorepats ... */ 05977 for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) { 05978 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) 05979 continue; /* not mine */ 05980 ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip)); 05981 } 05982 }
| static void create_match_char_tree | ( | struct ast_context * | con | ) | [static] |
Definition at line 1603 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, and ast_context::root_table.
Referenced by pbx_find_extension().
01604 { 01605 struct ast_hashtab_iter *t1; 01606 struct ast_exten *e1; 01607 #ifdef NEED_DEBUG 01608 int biggest_bucket, resizes, numobjs, numbucks; 01609 01610 ast_log(LOG_DEBUG,"Creating Extension Trie for context %s\n", con->name); 01611 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks); 01612 ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n", 01613 numobjs, numbucks, biggest_bucket, resizes); 01614 #endif 01615 t1 = ast_hashtab_start_traversal(con->root_table); 01616 while( (e1 = ast_hashtab_next(t1)) ) { 01617 if (e1->exten) 01618 add_exten_to_pattern_tree(con, e1, 0); 01619 else 01620 ast_log(LOG_ERROR,"Attempt to create extension with no extension name.\n"); 01621 } 01622 ast_hashtab_end_traversal(t1); 01623 }
| static void decrease_call_count | ( | void | ) | [static] |
Definition at line 4015 of file pbx.c.
References ast_mutex_lock(), and ast_mutex_unlock().
Referenced by ast_pbx_run_args(), ast_pbx_start(), and pbx_thread().
04016 { 04017 ast_mutex_lock(&maxcalllock); 04018 if (countcalls > 0) 04019 countcalls--; 04020 ast_mutex_unlock(&maxcalllock); 04021 }
| static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 4023 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().
04024 { 04025 if (e->priority == PRIORITY_HINT) 04026 ast_remove_hint(e); 04027 04028 if (e->peer_table) 04029 ast_hashtab_destroy(e->peer_table,0); 04030 if (e->peer_label_table) 04031 ast_hashtab_destroy(e->peer_label_table, 0); 04032 if (e->datad) 04033 e->datad(e->data); 04034 ast_free(e); 04035 }
| static void destroy_pattern_tree | ( | struct match_char * | pattern_tree | ) | [static] |
Definition at line 1625 of file pbx.c.
References match_char::alt_char, match_char::exten, free, match_char::next_char, and match_char::x.
Referenced by __ast_internal_context_destroy().
01626 { 01627 /* destroy all the alternates */ 01628 if (pattern_tree->alt_char) { 01629 destroy_pattern_tree(pattern_tree->alt_char); 01630 pattern_tree->alt_char = 0; 01631 } 01632 /* destroy all the nexts */ 01633 if (pattern_tree->next_char) { 01634 destroy_pattern_tree(pattern_tree->next_char); 01635 pattern_tree->next_char = 0; 01636 } 01637 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */ 01638 if (pattern_tree->x) 01639 free(pattern_tree->x); 01640 free(pattern_tree); 01641 }
| static void device_state_cb | ( | const struct ast_event * | event, | |
| void * | unused | |||
| ) | [static] |
Definition at line 8700 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().
08701 { 08702 const char *device; 08703 struct statechange *sc; 08704 08705 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 08706 if (ast_strlen_zero(device)) { 08707 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n"); 08708 return; 08709 } 08710 08711 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1))) 08712 return; 08713 strcpy(sc->dev, device); 08714 if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) { 08715 ast_free(sc); 08716 } 08717 }
| static void exception_store_free | ( | void * | data | ) | [static] |
Definition at line 2583 of file pbx.c.
References ast_free, and ast_string_field_free_memory.
02584 { 02585 struct pbx_exception *exception = data; 02586 ast_string_field_free_memory(exception); 02587 ast_free(exception); 02588 }
| static int ext_cmp | ( | const char * | a, | |
| const char * | b | |||
| ) | [static] |
the full routine to compare extensions in rules.
Definition at line 1777 of file pbx.c.
References ext_cmp1().
Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().
01778 { 01779 /* make sure non-patterns come first. 01780 * If a is not a pattern, it either comes first or 01781 * we do a more complex pattern comparison. 01782 */ 01783 int ret = 0; 01784 01785 if (a[0] != '_') 01786 return (b[0] == '_') ? -1 : strcmp(a, b); 01787 01788 /* Now we know a is a pattern; if b is not, a comes first */ 01789 if (b[0] != '_') 01790 return 1; 01791 01792 /* ok we need full pattern sorting routine. 01793 * skip past the underscores */ 01794 ++a; ++b; 01795 do { 01796 unsigned char bitwise[2][32] = { { 0, } }; 01797 ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]); 01798 if (ret == 0) { 01799 /* Are the classes different, even though they score the same? */ 01800 ret = memcmp(bitwise[0], bitwise[1], 32); 01801 } 01802 } while (!ret && a && b); 01803 if (ret == 0) { 01804 return 0; 01805 } else { 01806 return (ret > 0) ? 1 : -1; 01807 } 01808 }
| static int ext_cmp1 | ( | const char ** | p, | |
| unsigned char * | bitwise | |||
| ) | [static] |
helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first.
ext_cmp1 compares individual characters (or sets of), returning an int where bits 0-7 are the ASCII code of the first char in the set, while bit 8-15 are the cardinality of the set minus 1. This way more specific patterns (smaller cardinality) appear first. Wildcards have a special value, so that we can directly compare them to sets by subtracting the two values. In particular: 0x000xx one character, xx 0x0yyxx yy character set starting with xx 0x10000 '.' (one or more of anything) 0x20000 '!' (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 equivalent to NUL. 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 1697 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ext_cmp().
01698 { 01699 int c, cmin = 0xff, count = 0; 01700 const char *end; 01701 01702 /* load value and advance pointer */ 01703 c = *(*p)++; 01704 01705 /* always return unless we have a set of chars */ 01706 switch (toupper(c)) { 01707 default: /* ordinary character */ 01708 bitwise[c / 8] = 1 << (c % 8); 01709 return 0x0100 | (c & 0xff); 01710 01711 case 'N': /* 2..9 */ 01712 bitwise[6] = 0xfc; 01713 bitwise[7] = 0x03; 01714 return 0x0800 | '2'; 01715 01716 case 'X': /* 0..9 */ 01717 bitwise[6] = 0xff; 01718 bitwise[7] = 0x03; 01719 return 0x0A00 | '0'; 01720 01721 case 'Z': /* 1..9 */ 01722 bitwise[6] = 0xfe; 01723 bitwise[7] = 0x03; 01724 return 0x0900 | '1'; 01725 01726 case '.': /* wildcard */ 01727 return 0x10000; 01728 01729 case '!': /* earlymatch */ 01730 return 0x20000; /* less specific than NULL */ 01731 01732 case '\0': /* empty string */ 01733 *p = NULL; 01734 return 0x30000; 01735 01736 case '[': /* pattern */ 01737 break; 01738 } 01739 /* locate end of set */ 01740 end = strchr(*p, ']'); 01741 01742 if (end == NULL) { 01743 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 01744 return 0x40000; /* XXX make this entry go last... */ 01745 } 01746 01747 for (; *p < end ; (*p)++) { 01748 unsigned char c1, c2; /* first-last char in range */ 01749 c1 = (unsigned char)((*p)[0]); 01750 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 01751 c2 = (unsigned char)((*p)[2]); 01752 *p += 2; /* skip a total of 3 chars */ 01753 } else { /* individual character */ 01754 c2 = c1; 01755 } 01756 if (c1 < cmin) { 01757 cmin = c1; 01758 } 01759 for (; c1 <= c2; c1++) { 01760 unsigned char mask = 1 << (c1 % 8); 01761 /*!\note If two patterns score the same, the one with the lowest 01762 * ascii values will compare as coming first. */ 01763 /* Flag the character as included (used) and count it. */ 01764 if (!(bitwise[ c1 / 8 ] & mask)) { 01765 bitwise[ c1 / 8 ] |= mask; 01766 count += 0x100; 01767 } 01768 } 01769 } 01770 (*p)++; 01771 return count == 0 ? 0x30000 : (count | cmin); 01772 }
| static int ext_strncpy | ( | char * | dst, | |
| const char * | src, | |||
| int | len | |||
| ) | [static] |
copy a string skipping whitespace
Definition at line 6856 of file pbx.c.
Referenced by ast_add_extension2_lockopt().
06857 { 06858 int count = 0; 06859 06860 while (*src && (count < len - 1)) { 06861 switch (*src) { 06862 case ' ': 06863 /* otherwise exten => [a-b],1,... doesn't work */ 06864 /* case '-': */ 06865 /* Ignore */ 06866 break; 06867 default: 06868 *dst = *src; 06869 dst++; 06870 } 06871 src++; 06872 count++; 06873 } 06874 *dst = '\0'; 06875 06876 return count; 06877 }
| static int extension_match_core | ( | const char * | pattern, | |
| const char * | data, | |||
| enum ext_match_t | mode | |||
| ) | [static] |
Definition at line 1991 of file pbx.c.
References _extension_match_core(), ast_add_profile(), and ast_mark().
Referenced by ast_extension_close(), ast_extension_match(), and pbx_find_extension().
01992 { 01993 int i; 01994 static int prof_id = -2; /* marker for 'unallocated' id */ 01995 if (prof_id == -2) 01996 prof_id = ast_add_profile("ext_match", 0); 01997 ast_mark(prof_id, 1); 01998 i = _extension_match_core(pattern, data, mode); 01999 ast_mark(prof_id, 0); 02000 return i; 02001 }
| 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 4139 of file pbx.c.
References ast_copy_string(), and ast_hashtab_lookup().
Referenced by ast_add_extension_nolock().
04140 { 04141 struct ast_context *c = NULL; 04142 struct fake_context item; 04143 04144 ast_copy_string(item.name, context, sizeof(item.name)); 04145 04146 c = ast_hashtab_lookup(contexts_table,&item); 04147 04148 return c; 04149 }
| 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 4156 of file pbx.c.
References ast_copy_string(), ast_get_context_name(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().
04157 { 04158 struct ast_context *c = NULL; 04159 struct fake_context item; 04160 04161 ast_copy_string(item.name, context, sizeof(item.name)); 04162 04163 ast_rdlock_contexts(); 04164 c = ast_hashtab_lookup(contexts_table,&item); 04165 04166 #ifdef NOTNOW 04167 04168 while ( (c = ast_walk_contexts(c)) ) { 04169 if (!strcmp(ast_get_context_name(c), context)) 04170 return c; 04171 } 04172 #endif 04173 if (!c) 04174 ast_unlock_contexts(); 04175 04176 return c; 04177 }
| 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 2852 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), and ast_func_write().
02853 { 02854 char *args = strchr(function, '('); 02855 02856 if (!args) 02857 ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function); 02858 else { 02859 char *p; 02860 *args++ = '\0'; 02861 if ((p = strrchr(args, ')')) ) 02862 *p = '\0'; 02863 else 02864 ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args); 02865 } 02866 return args; 02867 }
| static struct ast_exten * get_canmatch_exten | ( | struct match_char * | node | ) | [static, read] |
Definition at line 1164 of file pbx.c.
References ast_log(), ast_exten::exten, match_char::exten, LOG_NOTICE, match_char::next_char, and match_char::x.
01165 { 01166 /* find the exten at the end of the rope */ 01167 struct match_char *node2 = node; 01168 01169 for (node2 = node; node2; node2 = node2->next_char) { 01170 if (node2->exten) { 01171 #ifdef NEED_DEBUG_HERE 01172 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten); 01173 #endif 01174 return node2->exten; 01175 } 01176 } 01177 #ifdef NEED_DEBUG_HERE 01178 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x); 01179 #endif 01180 return 0; 01181 }
| static unsigned get_range | ( | char * | src, | |
| int | max, | |||
| 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 6250 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and s.
Referenced by ast_build_timing().
06251 { 06252 int s, e; /* start and ending position */ 06253 unsigned int mask = 0; 06254 06255 /* Check for whole range */ 06256 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 06257 s = 0; 06258 e = max - 1; 06259 } else { 06260 /* Get start and ending position */ 06261 char *c = strchr(src, '-'); 06262 if (c) 06263 *c++ = '\0'; 06264 /* Find the start */ 06265 s = lookup_name(src, names, max); 06266 if (!s) { 06267 ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src); 06268 return 0; 06269 } 06270 s--; 06271 if (c) { /* find end of range */ 06272 e = lookup_name(c, names, max); 06273 if (!e) { 06274 ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c); 06275 return 0; 06276 } 06277 e--; 06278 } else 06279 e = s; 06280 } 06281 /* Fill the mask. Remember that ranges are cyclic */ 06282 mask = 1 << e; /* initialize with last element */ 06283 while (s != e) { 06284 if (s >= max) { 06285 s = 0; 06286 mask |= (1 << s); 06287 } else { 06288 mask |= (1 << s); 06289 s++; 06290 } 06291 } 06292 return mask; 06293 }
| static void get_timerange | ( | struct ast_timing * | i, | |
| char * | times | |||
| ) | [static] |
store a bitmask of valid times, one bit each 2 minute
Definition at line 6296 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
06297 { 06298 char *e; 06299 int x; 06300 int s1, s2; 06301 int e1, e2; 06302 /* int cth, ctm; */ 06303 06304 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 06305 memset(i->minmask, 0, sizeof(i->minmask)); 06306 06307 /* 2-minutes per bit, since the mask has only 32 bits :( */ 06308 /* Star is all times */ 06309 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 06310 for (x = 0; x < 24; x++) 06311 i->minmask[x] = 0x3fffffff; /* 30 bits */ 06312 return; 06313 } 06314 /* Otherwise expect a range */ 06315 e = strchr(times, '-'); 06316 if (!e) { 06317 ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n"); 06318 return; 06319 } 06320 *e++ = '\0'; 06321 /* XXX why skip non digits ? */ 06322 while (*e && !isdigit(*e)) 06323 e++; 06324 if (!*e) { 06325 ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n"); 06326 return; 06327 } 06328 if (sscanf(times, "%2d:%2d", &s1, &s2) != 2) { 06329 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times); 06330 return; 06331 } 06332 if (sscanf(e, "%2d:%2d", &e1, &e2) != 2) { 06333 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e); 06334 return; 06335 } 06336 /* XXX this needs to be optimized */ 06337 #if 1 06338 s1 = s1 * 30 + s2/2; 06339 if ((s1 < 0) || (s1 >= 24*30)) { 06340 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times); 06341 return; 06342 } 06343 e1 = e1 * 30 + e2/2; 06344 if ((e1 < 0) || (e1 >= 24*30)) { 06345 ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e); 06346 return; 06347 } 06348 /* Go through the time and enable each appropriate bit */ 06349 for (x=s1;x != e1;x = (x + 1) % (24 * 30)) { 06350 i->minmask[x/30] |= (1 << (x % 30)); 06351 } 06352 /* Do the last one */ 06353 i->minmask[x/30] |= (1 << (x % 30)); 06354 #else 06355 for (cth = 0; cth < 24; cth++) { 06356 /* Initialize masks to blank */ 06357 i->minmask[cth] = 0; 06358 for (ctm = 0; ctm < 30; ctm++) { 06359 if ( 06360 /* First hour with more than one hour */ 06361 (((cth == s1) && (ctm >= s2)) && 06362 ((cth < e1))) 06363 /* Only one hour */ 06364 || (((cth == s1) && (ctm >= s2)) && 06365 ((cth == e1) && (ctm <= e2))) 06366 /* In between first and last hours (more than 2 hours) */ 06367 || ((cth > s1) && 06368 (cth < e1)) 06369 /* Last hour with more than one hour */ 06370 || ((cth > s1) && 06371 ((cth == e1) && (ctm <= e2))) 06372 ) 06373 i->minmask[cth] |= (1 << (ctm / 2)); 06374 } 06375 } 06376 #endif 06377 /* All done */ 06378 return; 06379 }
| static char* handle_debug_dialplan | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Send ack once.
Definition at line 5308 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), dialplan_counters::context_existence, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_debug_helper(), strsep(), dialplan_counters::total_context, ast_cli_entry::usage, and ast_cli_args::word.
05309 { 05310 char *exten = NULL, *context = NULL; 05311 /* Variables used for different counters */ 05312 struct dialplan_counters counters; 05313 const char *incstack[AST_PBX_MAX_STACK]; 05314 05315 switch (cmd) { 05316 case CLI_INIT: 05317 e->command = "dialplan debug"; 05318 e->usage = 05319 "Usage: dialplan debug [context]\n" 05320 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n"; 05321 return NULL; 05322 case CLI_GENERATE: 05323 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 05324 } 05325 05326 memset(&counters, 0, sizeof(counters)); 05327 05328 if (a->argc != 2 && a->argc != 3) 05329 return CLI_SHOWUSAGE; 05330 05331 /* we obtain [exten@]context? if yes, split them ... */ 05332 /* note: we ignore the exten totally here .... */ 05333 if (a->argc == 3) { 05334 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 05335 context = ast_strdupa(a->argv[2]); 05336 exten = strsep(&context, "@"); 05337 /* change empty strings to NULL */ 05338 if (ast_strlen_zero(exten)) 05339 exten = NULL; 05340 } else { /* no '@' char, only context given */ 05341 context = a->argv[2]; 05342 } 05343 if (ast_strlen_zero(context)) 05344 context = NULL; 05345 } 05346 /* else Show complete dial plan, context and exten are NULL */ 05347 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 05348 05349 /* check for input failure and throw some error messages */ 05350 if (context && !counters.context_existence) { 05351 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 05352 return CLI_FAILURE; 05353 } 05354 05355 05356 ast_cli(a->fd,"-= %d %s. =-\n", 05357 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 05358 05359 /* everything ok */ 05360 return CLI_SUCCESS; 05361 }
| static char* handle_set_chanvar | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5702 of file pbx.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_unlock, ast_cli(), ast_complete_channels(), ast_get_channel_by_name_locked(), 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.
Referenced by handle_set_chanvar_deprecated().
05703 { 05704 struct ast_channel *chan; 05705 const char *chan_name, *var_name, *var_value; 05706 05707 switch (cmd) { 05708 case CLI_INIT: 05709 e->command = "dialplan set chanvar"; 05710 e->usage = 05711 "Usage: dialplan set chanvar <channel> <varname> <value>\n" 05712 " Set channel variable <varname> to <value>\n"; 05713 return NULL; 05714 case CLI_GENERATE: 05715 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 05716 } 05717 05718 if (a->argc != e->args + 3) 05719 return CLI_SHOWUSAGE; 05720 05721 chan_name = a->argv[e->args]; 05722 var_name = a->argv[e->args + 1]; 05723 var_value = a->argv[e->args + 2]; 05724 05725 if (!(chan = ast_get_channel_by_name_locked(chan_name))) { 05726 ast_cli(a->fd, "Channel '%s' not found\n", chan_name); 05727 return CLI_FAILURE; 05728 } 05729 05730 pbx_builtin_setvar_helper(chan, var_name, var_value); 05731 ast_channel_unlock(chan); 05732 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name); 05733 05734 return CLI_SUCCESS; 05735 }
| static char* handle_set_chanvar_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5737 of file pbx.c.
References CLI_INIT, ast_cli_entry::command, and handle_set_chanvar().
05738 { 05739 char *res = handle_set_chanvar(e, cmd, a); 05740 if (cmd == CLI_INIT) 05741 e->command = "core set chanvar"; 05742 return res; 05743 }
| static char* handle_set_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5745 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.
05746 { 05747 int oldval = 0; 05748 05749 switch (cmd) { 05750 case CLI_INIT: 05751 e->command = "dialplan set extenpatternmatchnew true"; 05752 e->usage = 05753 "Usage: dialplan set extenpatternmatchnew true|false\n" 05754 " Use the NEW extension pattern matching algorithm, true or false.\n"; 05755 return NULL; 05756 case CLI_GENERATE: 05757 return NULL; 05758 } 05759 05760 if (a->argc != 4) 05761 return CLI_SHOWUSAGE; 05762 05763 oldval = pbx_set_extenpatternmatchnew(1); 05764 05765 if (oldval) 05766 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n"); 05767 else 05768 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n"); 05769 05770 return CLI_SUCCESS; 05771 }
| static char* handle_set_global | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5672 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.
Referenced by handle_set_global_deprecated().
05673 { 05674 switch (cmd) { 05675 case CLI_INIT: 05676 e->command = "dialplan set global"; 05677 e->usage = 05678 "Usage: dialplan set global <name> <value>\n" 05679 " Set global dialplan variable <name> to <value>\n"; 05680 return NULL; 05681 case CLI_GENERATE: 05682 return NULL; 05683 } 05684 05685 if (a->argc != e->args + 2) 05686 return CLI_SHOWUSAGE; 05687 05688 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]); 05689 ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]); 05690 05691 return CLI_SUCCESS; 05692 }
| static char* handle_set_global_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5694 of file pbx.c.
References CLI_INIT, ast_cli_entry::command, and handle_set_global().
05695 { 05696 char *res = handle_set_global(e, cmd, a); 05697 if (cmd == CLI_INIT) 05698 e->command = "core set global"; 05699 return res; 05700 }
| static char* handle_show_application | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4641 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_MAX_APP, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_CYAN, COLOR_MAGENTA, ast_cli_entry::command, ast_app::description, ast_cli_args::fd, ast_cli_args::n, ast_app::synopsis, term_color(), ast_cli_entry::usage, and ast_cli_args::word.
04642 { 04643 struct ast_app *aa; 04644 int app, no_registered_app = 1; 04645 char *ret = NULL; 04646 int which = 0; 04647 int wordlen; 04648 04649 switch (cmd) { 04650 case CLI_INIT: 04651 e->command = "core show application"; 04652 e->usage = 04653 "Usage: core show application <application> [<application> [<application> [...]]]\n" 04654 " Describes a particular application.\n"; 04655 return NULL; 04656 case CLI_GENERATE: 04657 /* 04658 * There is a possibility to show informations about more than one 04659 * application at one time. You can type 'show application Dial Echo' and 04660 * you will see informations about these two applications ... 04661 */ 04662 wordlen = strlen(a->word); 04663 /* return the n-th [partial] matching entry */ 04664 AST_RWLIST_RDLOCK(&apps); 04665 AST_RWLIST_TRAVERSE(&apps, aa, list) { 04666 if (!strncasecmp(a->word, aa->name, wordlen) && ++which > a->n) { 04667 ret = ast_strdup(aa->name); 04668 break; 04669 } 04670 } 04671 AST_RWLIST_UNLOCK(&apps); 04672 04673 return ret; 04674 } 04675 04676 if (a->argc < 4) 04677 return CLI_SHOWUSAGE; 04678 04679 /* ... go through all applications ... */ 04680 AST_RWLIST_RDLOCK(&apps); 04681 AST_RWLIST_TRAVERSE(&apps, aa, list) { 04682 /* ... compare this application name with all arguments given 04683 * to 'show application' command ... */ 04684 for (app = 3; app < a->argc; app++) { 04685 if (!strcasecmp(aa->name, a->argv[app])) { 04686 /* Maximum number of characters added by terminal coloring is 22 */ 04687 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 04688 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 04689 int synopsis_size, description_size; 04690 04691 no_registered_app = 0; 04692 04693 if (aa->synopsis) 04694 synopsis_size = strlen(aa->synopsis) + 23; 04695 else 04696 synopsis_size = strlen("Not available") + 23; 04697 synopsis = alloca(synopsis_size); 04698 04699 if (aa->description) 04700 description_size = strlen(aa->description) + 23; 04701 else 04702 description_size = strlen("Not available") + 23; 04703 description = alloca(description_size); 04704 04705 if (synopsis && description) { 04706 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", aa->name); 04707 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 04708 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 04709 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 04710 term_color(synopsis, 04711 aa->synopsis ? aa->synopsis : "Not available", 04712 COLOR_CYAN, 0, synopsis_size); 04713 term_color(description, 04714 aa->description ? aa->description : "Not available", 04715 COLOR_CYAN, 0, description_size); 04716 04717 ast_cli(a->fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 04718 } else { 04719 /* ... one of our applications, show info ...*/ 04720 ast_cli(a->fd,"\n -= Info about application '%s' =- \n\n" 04721 "[Synopsis]\n %s\n\n" 04722 "[Description]\n%s\n", 04723 aa->name, 04724 aa->synopsis ? aa->synopsis : "Not available", 04725 aa->description ? aa->description : "Not available"); 04726 } 04727 } 04728 } 04729 } 04730 AST_RWLIST_UNLOCK(&apps); 04731 04732 /* we found at least one app? no? */ 04733 if (no_registered_app) { 04734 ast_cli(a->fd, "Your application(s) is (are) not registered\n"); 04735 return CLI_FAILURE; 04736 } 04737 04738 return CLI_SUCCESS; 04739 }
| static char* handle_show_applications | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4897 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_cli_args::pos, strcasestr(), ast_app::synopsis, ast_cli_entry::usage, and ast_cli_args::word.
04898 { 04899 struct ast_app *aa; 04900 int like = 0, describing = 0; 04901 int total_match = 0; /* Number of matches in like clause */ 04902 int total_apps = 0; /* Number of apps registered */ 04903 static char* choices[] = { "like", "describing", NULL }; 04904 04905 switch (cmd) { 04906 case CLI_INIT: 04907 e->command = "core show applications [like|describing]"; 04908 e->usage = 04909 "Usage: core show applications [{like|describing} <text>]\n" 04910 " List applications which are currently available.\n" 04911 " If 'like', <text> will be a substring of the app name\n" 04912 " If 'describing', <text> will be a substring of the description\n"; 04913 return NULL; 04914 case CLI_GENERATE: 04915 return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n); 04916 } 04917 04918 AST_RWLIST_RDLOCK(&apps); 04919 04920 if (AST_RWLIST_EMPTY(&apps)) { 04921 ast_cli(a->fd, "There are no registered applications\n"); 04922 AST_RWLIST_UNLOCK(&apps); 04923 return CLI_SUCCESS; 04924 } 04925 04926 /* core list applications like <keyword> */ 04927 if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) { 04928 like = 1; 04929 } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) { 04930 describing = 1; 04931 } 04932 04933 /* core list applications describing <keyword1> [<keyword2>] [...] */ 04934 if ((!like) && (!describing)) { 04935 ast_cli(a->fd, " -= Registered Asterisk Applications =-\n"); 04936 } else { 04937 ast_cli(a->fd, " -= Matching Asterisk Applications =-\n"); 04938 } 04939 04940 AST_RWLIST_TRAVERSE(&apps, aa, list) { 04941 int printapp = 0; 04942 total_apps++; 04943 if (like) { 04944 if (strcasestr(aa->name, a->argv[4])) { 04945 printapp = 1; 04946 total_match++; 04947 } 04948 } else if (describing) { 04949 if (aa->description) { 04950 /* Match all words on command line */ 04951 int i; 04952 printapp = 1; 04953 for (i = 4; i < a->argc; i++) { 04954 if (!strcasestr(aa->description, a->argv[i])) { 04955 printapp = 0; 04956 } else { 04957 total_match++; 04958 } 04959 } 04960 } 04961 } else { 04962 printapp = 1; 04963 } 04964 04965 if (printapp) { 04966 ast_cli(a->fd," %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>"); 04967 } 04968 } 04969 if ((!like) && (!describing)) { 04970 ast_cli(a->fd, " -= %d Applications Registered =-\n",total_apps); 04971 } else { 04972 ast_cli(a->fd, " -= %d Applications Matching =-\n",total_match); 04973 } 04974 04975 AST_RWLIST_UNLOCK(&apps); 04976 04977 return CLI_SUCCESS; 04978 }
| 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 5640 of file pbx.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_unlock, ast_cli(), ast_complete_channels(), ast_get_channel_by_name_locked(), ast_str_alloca, 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_str::str, ast_cli_entry::usage, and ast_cli_args::word.
05641 { 05642 struct ast_channel *chan = NULL; 05643 struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */ 05644 05645 switch (cmd) { 05646 case CLI_INIT: 05647 e->command = "dialplan show chanvar"; 05648 e->usage = 05649 "Usage: dialplan show chanvar <channel>\n" 05650 " List current channel variables and their values\n"; 05651 return NULL; 05652 case CLI_GENERATE: 05653 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 05654 } 05655 05656 if (a->argc != e->args + 1) 05657 return CLI_SHOWUSAGE; 05658 05659 if (!(chan = ast_get_channel_by_name_locked(a->argv[e->args]))) { 05660 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]); 05661 return CLI_FAILURE; 05662 } 05663 05664 pbx_builtin_serialize_variables(chan, &vars); 05665 if (vars->str) { 05666 ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], vars->str); 05667 } 05668 ast_channel_unlock(chan); 05669 return CLI_SUCCESS; 05670 }
| static char* handle_show_dialplan | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5241 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, dialplan_counters::extension_existence, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_dialplan_helper(), strsep(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_prio, ast_cli_entry::usage, and ast_cli_args::word.
05242 { 05243 char *exten = NULL, *context = NULL; 05244 /* Variables used for different counters */ 05245 struct dialplan_counters counters; 05246 const char *incstack[AST_PBX_MAX_STACK]; 05247 05248 switch (cmd) { 05249 case CLI_INIT: 05250 e->command = "dialplan show"; 05251 e->usage = 05252 "Usage: dialplan show [[exten@]context]\n" 05253 " Show dialplan\n"; 05254 return NULL; 05255 case CLI_GENERATE: 05256 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 05257 } 05258 05259 memset(&counters, 0, sizeof(counters)); 05260 05261 if (a->argc != 2 && a->argc != 3) 05262 return CLI_SHOWUSAGE; 05263 05264 /* we obtain [exten@]context? if yes, split them ... */ 05265 if (a->argc == 3) { 05266 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 05267 context = ast_strdupa(a->argv[2]); 05268 exten = strsep(&context, "@"); 05269 /* change empty strings to NULL */ 05270 if (ast_strlen_zero(exten)) 05271 exten = NULL; 05272 } else { /* no '@' char, only context given */ 05273 context = a->argv[2]; 05274 } 05275 if (ast_strlen_zero(context)) 05276 context = NULL; 05277 } 05278 /* else Show complete dial plan, context and exten are NULL */ 05279 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 05280 05281 /* check for input failure and throw some error messages */ 05282 if (context && !counters.context_existence) { 05283 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 05284 return CLI_FAILURE; 05285 } 05286 05287 if (exten && !counters.extension_existence) { 05288 if (context) 05289 ast_cli(a->fd, "There is no existence of %s@%s extension\n", 05290 exten, context); 05291 else 05292 ast_cli(a->fd, 05293 "There is no existence of '%s' extension in all contexts\n", 05294 exten); 05295 return CLI_FAILURE; 05296 } 05297 05298 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n", 05299 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 05300 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 05301 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 05302 05303 /* everything ok */ 05304 return CLI_SUCCESS; 05305 }
| static char* handle_show_function | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2701 of file pbx.c.
References ast_custom_function::acflist, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_custom_function_find(), AST_MAX_APP, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_CYAN, COLOR_MAGENTA, ast_cli_entry::command, ast_custom_function::desc, ast_cli_args::fd, ast_cli_args::n, ast_custom_function::name, ast_custom_function::synopsis, ast_custom_function::syntax, term_color(), ast_cli_entry::usage, and ast_cli_args::word.
02702 { 02703 struct ast_custom_function *acf; 02704 /* Maximum number of characters added by terminal coloring is 22 */ 02705 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 02706 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 02707 char stxtitle[40], *syntax = NULL; 02708 int synopsis_size, description_size, syntax_size; 02709 char *ret = NULL; 02710 int which = 0; 02711 int wordlen; 02712 02713 switch (cmd) { 02714 case CLI_INIT: 02715 e->command = "core show function"; 02716 e->usage = 02717 "Usage: core show function <function>\n" 02718 " Describe a particular dialplan function.\n"; 02719 return NULL; 02720 case CLI_GENERATE: 02721 wordlen = strlen(a->word); 02722 /* case-insensitive for convenience in this 'complete' function */ 02723 AST_RWLIST_RDLOCK(&acf_root); 02724 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 02725 if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) { 02726 ret = ast_strdup(acf->name); 02727 break; 02728 } 02729 } 02730 AST_RWLIST_UNLOCK(&acf_root); 02731 02732 return ret; 02733 } 02734 02735 if (a->argc < 4) 02736 return CLI_SHOWUSAGE; 02737 02738 if (!(acf = ast_custom_function_find(a->argv[3]))) { 02739 ast_cli(a->fd, "No function by that name registered.\n"); 02740 return CLI_FAILURE; 02741 02742 } 02743 02744 if (acf->synopsis) 02745 synopsis_size = strlen(acf->synopsis) + 23; 02746 else 02747 synopsis_size = strlen("Not available") + 23; 02748 synopsis = alloca(synopsis_size); 02749 02750 if (acf->desc) 02751 description_size = strlen(acf->desc) + 23; 02752 else 02753 description_size = strlen("Not available") + 23; 02754 description = alloca(description_size); 02755 02756 if (acf->syntax) 02757 syntax_size = strlen(acf->syntax) + 23; 02758 else 02759 syntax_size = strlen("Not available") + 23; 02760 syntax = alloca(syntax_size); 02761 02762 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name); 02763 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 02764 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 02765 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 02766 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 02767 term_color(syntax, 02768 acf->syntax ? acf->syntax : "Not available", 02769 COLOR_CYAN, 0, syntax_size); 02770 term_color(synopsis, 02771 acf->synopsis ? acf->synopsis : "Not available", 02772 COLOR_CYAN, 0, synopsis_size); 02773 term_color(description, 02774 acf->desc ? acf->desc : "Not available", 02775 COLOR_CYAN, 0, description_size); 02776 02777 ast_cli(a->fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description); 02778 02779 return CLI_SUCCESS; 02780 }
| static char* handle_show_functions | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2662 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, ast_custom_function::synopsis, ast_custom_function::syntax, and ast_cli_entry::usage.
02663 { 02664 struct ast_custom_function *acf; 02665 int count_acf = 0; 02666 int like = 0; 02667 02668 switch (cmd) { 02669 case CLI_INIT: 02670 e->command = "core show functions [like]"; 02671 e->usage = 02672 "Usage: core show functions [like <text>]\n" 02673 " List builtin functions, optionally only those matching a given string\n"; 02674 return NULL; 02675 case CLI_GENERATE: 02676 return NULL; 02677 } 02678 02679 if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) { 02680 like = 1; 02681 } else if (a->argc != 3) { 02682 return CLI_SHOWUSAGE; 02683 } 02684 02685 ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 02686 02687 AST_RWLIST_RDLOCK(&acf_root); 02688 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 02689 if (!like || strstr(acf->name, a->argv[4])) { 02690 count_acf++; 02691 ast_cli(a->fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis); 02692 } 02693 } 02694 AST_RWLIST_UNLOCK(&acf_root); 02695 02696 ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 02697 02698 return CLI_SUCCESS; 02699 }
| 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 5573 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, and ast_cli_entry::usage.
Referenced by handle_show_globals_deprecated().
05574 { 05575 int i = 0; 05576 struct ast_var_t *newvariable; 05577 05578 switch (cmd) { 05579 case CLI_INIT: 05580 e->command = "dialplan show globals"; 05581 e->usage = 05582 "Usage: dialplan show globals\n" 05583 " List current global dialplan variables and their values\n"; 05584 return NULL; 05585 case CLI_GENERATE: 05586 return NULL; 05587 } 05588 05589 ast_rwlock_rdlock(&globalslock); 05590 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 05591 i++; 05592 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 05593 } 05594 ast_rwlock_unlock(&globalslock); 05595 ast_cli(a->fd, "\n -- %d variable(s)\n", i); 05596 05597 return CLI_SUCCESS; 05598 }
| static char* handle_show_globals_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5600 of file pbx.c.
References CLI_INIT, ast_cli_entry::command, and handle_show_globals().
05601 { 05602 05603 char *res = handle_show_globals(e, cmd, a); 05604 if (cmd == CLI_INIT) 05605 e->command = "core show globals"; 05606 return res; 05607 }
| 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 4813 of file pbx.c.
References 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_LIST_TRAVERSE, AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_core_show_hint(), ast_hint::exten, ast_cli_args::fd, ast_hint::laststate, ast_cli_args::line, ast_cli_args::n, num, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
04814 { 04815 struct ast_hint *hint; 04816 int watchers; 04817 int num = 0, extenlen; 04818 struct ast_state_cb *watcher; 04819 04820 switch (cmd) { 04821 case CLI_INIT: 04822 e->command = "core show hint"; 04823 e->usage = 04824 "Usage: core show hint <exten>\n" 04825 " List registered hint\n"; 04826 return NULL; 04827 case CLI_GENERATE: 04828 return complete_core_show_hint(a->line, a->word, a->pos, a->n); 04829 } 04830 04831 if (a->argc < 4) 04832 return CLI_SHOWUSAGE; 04833 04834 AST_RWLIST_RDLOCK(&hints); 04835 if (AST_RWLIST_EMPTY(&hints)) { 04836 ast_cli(a->fd, "There are no registered dialplan hints\n"); 04837 AST_RWLIST_UNLOCK(&hints); 04838 return CLI_SUCCESS; 04839 } 04840 extenlen = strlen(a->argv[3]); 04841 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04842 if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) { 04843 watchers = 0; 04844 AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) { 04845 watchers++; 04846 } 04847 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 04848 ast_get_extension_name(hint->exten), 04849 ast_get_context_name(ast_get_extension_context(hint->exten)), 04850 ast_get_extension_app(hint->exten), 04851 ast_extension_state2str(hint->laststate), watchers); 04852 num++; 04853 } 04854 } 04855 AST_RWLIST_UNLOCK(&hints); 04856 if (!num) 04857 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]); 04858 else 04859 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]); 04860 return CLI_SUCCESS; 04861 }
| 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 4742 of file pbx.c.
References ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_LIST_TRAVERSE, AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_hint::exten, ast_cli_args::fd, ast_hint::laststate, num, and ast_cli_entry::usage.
04743 { 04744 struct ast_hint *hint; 04745 int num = 0; 04746 int watchers; 04747 struct ast_state_cb *watcher; 04748 04749 switch (cmd) { 04750 case CLI_INIT: 04751 e->command = "core show hints"; 04752 e->usage = 04753 "Usage: core show hints\n" 04754 " List registered hints\n"; 04755 return NULL; 04756 case CLI_GENERATE: 04757 return NULL; 04758 } 04759 04760 AST_RWLIST_RDLOCK(&hints); 04761 if (AST_RWLIST_EMPTY(&hints)) { 04762 ast_cli(a->fd, "There are no registered dialplan hints\n"); 04763 AST_RWLIST_UNLOCK(&hints); 04764 return CLI_SUCCESS; 04765 } 04766 /* ... we have hints ... */ 04767 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 04768 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04769 watchers = 0; 04770 AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) { 04771 watchers++; 04772 } 04773 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 04774 ast_get_extension_name(hint->exten), 04775 ast_get_context_name(ast_get_extension_context(hint->exten)), 04776 ast_get_extension_app(hint->exten), 04777 ast_extension_state2str(hint->laststate), watchers); 04778 num++; 04779 } 04780 ast_cli(a->fd, "----------------\n"); 04781 ast_cli(a->fd, "- %d hints registered\n", num); 04782 AST_RWLIST_UNLOCK(&hints); 04783 return CLI_SUCCESS; 04784 }
| 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 4865 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.
04866 { 04867 struct ast_switch *sw; 04868 04869 switch (cmd) { 04870 case CLI_INIT: 04871 e->command = "core show switches"; 04872 e->usage = 04873 "Usage: core show switches\n" 04874 " List registered switches\n"; 04875 return NULL; 04876 case CLI_GENERATE: 04877 return NULL; 04878 } 04879 04880 AST_RWLIST_RDLOCK(&switches); 04881 04882 if (AST_RWLIST_EMPTY(&switches)) { 04883 AST_RWLIST_UNLOCK(&switches); 04884 ast_cli(a->fd, "There are no registered alternative switches\n"); 04885 return CLI_SUCCESS; 04886 } 04887 04888 ast_cli(a->fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 04889 AST_RWLIST_TRAVERSE(&switches, sw, list) 04890 ast_cli(a->fd, "%s: %s\n", sw->name, sw->description); 04891 04892 AST_RWLIST_UNLOCK(&switches); 04893 04894 return CLI_SUCCESS; 04895 }
| static int handle_statechange | ( | void * | datap | ) | [static] |
Definition at line 3349 of file pbx.c.
References ast_copy_string(), ast_extension_state2(), ast_free, ast_get_extension_app(), AST_LIST_TRAVERSE, AST_MAX_EXTENSION, ast_rdlock_contexts(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_unlock_contexts(), buf, ast_state_cb::callback, ast_state_cb::data, statechange::dev, ast_exten::exten, ast_hint::exten, ast_hint::laststate, ast_exten::parent, parse(), and strsep().
Referenced by device_state_cb().
03350 { 03351 struct ast_hint *hint; 03352 struct statechange *sc = datap; 03353 03354 ast_rdlock_contexts(); 03355 AST_RWLIST_RDLOCK(&hints); 03356 03357 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03358 struct ast_state_cb *cblist; 03359 char buf[AST_MAX_EXTENSION]; 03360 char *parse = buf; 03361 char *cur; 03362 int state; 03363 03364 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf)); 03365 while ( (cur = strsep(&parse, "&")) ) { 03366 if (!strcasecmp(cur, sc->dev)) 03367 break; 03368 } 03369 if (!cur) 03370 continue; 03371 03372 /* Get device state for this hint */ 03373 state = ast_extension_state2(hint->exten); 03374 03375 if ((state == -1) || (state == hint->laststate)) 03376 continue; 03377 03378 /* Device state changed since last check - notify the watchers */ 03379 03380 /* For general callbacks */ 03381 AST_LIST_TRAVERSE(&statecbs, cblist, entry) { 03382 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 03383 } 03384 03385 /* For extension callbacks */ 03386 AST_LIST_TRAVERSE(&hint->callbacks, cblist, entry) { 03387 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 03388 } 03389 03390 hint->laststate = state; /* record we saw the change */ 03391 } 03392 AST_RWLIST_UNLOCK(&hints); 03393 ast_unlock_contexts(); 03394 ast_free(sc); 03395 return 0; 03396 }
| static char* handle_unset_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5773 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.
05774 { 05775 int oldval = 0; 05776 05777 switch (cmd) { 05778 case CLI_INIT: 05779 e->command = "dialplan set extenpatternmatchnew false"; 05780 e->usage = 05781 "Usage: dialplan set extenpatternmatchnew true|false\n" 05782 " Use the NEW extension pattern matching algorithm, true or false.\n"; 05783 return NULL; 05784 case CLI_GENERATE: 05785 return NULL; 05786 } 05787 05788 if (a->argc != 4) 05789 return CLI_SHOWUSAGE; 05790 05791 oldval = pbx_set_extenpatternmatchnew(0); 05792 05793 if (!oldval) 05794 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n"); 05795 else 05796 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n"); 05797 05798 return CLI_SUCCESS; 05799 }
| 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 380 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 361 of file pbx.c.
References ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
00362 { 00363 const struct ast_exten *ac = ah_a; 00364 const struct ast_exten *bc = ah_b; 00365 int x = strcmp(ac->exten, bc->exten); 00366 if (x) { /* if exten names are diff, then return */ 00367 return x; 00368 } 00369 00370 /* but if they are the same, do the cidmatch values match? */ 00371 if (ac->matchcid && bc->matchcid) { 00372 return strcmp(ac->cidmatch,bc->cidmatch); 00373 } else if (!ac->matchcid && !bc->matchcid) { 00374 return 0; /* if there's no matchcid on either side, then this is a match */ 00375 } else { 00376 return 1; /* if there's matchcid on one but not the other, they are different */ 00377 } 00378 }
| static unsigned int hashtab_hash_extens | ( | const void * | obj | ) | [static] |
Definition at line 400 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().
00401 { 00402 const struct ast_exten *ac = obj; 00403 unsigned int x = ast_hashtab_hash_string(ac->exten); 00404 unsigned int y = 0; 00405 if (ac->matchcid) 00406 y = ast_hashtab_hash_string(ac->cidmatch); 00407 return x+y; 00408 }
| static unsigned int hashtab_hash_labels | ( | const void * | obj | ) | [static] |
Definition at line 416 of file pbx.c.
References ast_hashtab_hash_string(), ast_exten::label, and S_OR.
Referenced by ast_add_extension2_lockopt().
00417 { 00418 const struct ast_exten *ac = obj; 00419 return ast_hashtab_hash_string(S_OR(ac->label, "")); 00420 }
| static unsigned int hashtab_hash_priority | ( | const void * | obj | ) | [static] |
Definition at line 410 of file pbx.c.
References ast_hashtab_hash_int(), and ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
00411 { 00412 const struct ast_exten *ac = obj; 00413 return ast_hashtab_hash_int(ac->priority); 00414 }
| static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 1003 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
Referenced by pbx_find_extension().
01004 { 01005 if (!i->hastime) 01006 return 1; 01007 01008 return ast_check_timing(&(i->timing)); 01009 }
| 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 3968 of file pbx.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), getloadavg(), LOG_WARNING, option_maxcalls, option_maxload, and option_minmemfree.
Referenced by ast_pbx_run_args(), and ast_pbx_start().
03969 { 03970 int failed = 0; 03971 double curloadavg; 03972 #if defined(HAVE_SYSINFO) 03973 long curfreemem; 03974 struct sysinfo sys_info; 03975 #endif 03976 03977 ast_mutex_lock(&maxcalllock); 03978 if (option_maxcalls) { 03979 if (countcalls >= option_maxcalls) { 03980 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 03981 failed = -1; 03982 } 03983 } 03984 if (option_maxload) { 03985 getloadavg(&curloadavg, 1); 03986 if (curloadavg >= option_maxload) { 03987 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 03988 failed = -1; 03989 } 03990 } 03991 #if defined(HAVE_SYSINFO) 03992 if (option_minmemfree) { 03993 if (!sysinfo(&sys_info)) { 03994 /* make sure that the free system memory is above the configured low watermark 03995 * convert the amount of freeram from mem_units to MB */ 03996 curfreemem = sys_info.freeram / sys_info.mem_unit; 03997 curfreemem /= 1024*1024; 03998 if (curfreemem < option_minmemfree) { 03999 ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree); 04000 failed = -1; 04001 } 04002 } 04003 } 04004 #endif 04005 04006 if (!failed) { 04007 countcalls++; 04008 totalcalls++; 04009 } 04010 ast_mutex_unlock(&maxcalllock); 04011 04012 return failed; 04013 }
| static void insert_in_next_chars_alt_char_list | ( | struct match_char ** | parent_ptr, | |
| struct match_char * | node | |||
| ) | [static] |
Definition at line 1404 of file pbx.c.
References match_char::alt_char, and match_char::specificity.
Referenced by add_pattern_node().
01405 { 01406 struct match_char *curr, *lcurr; 01407 01408 /* insert node into the tree at "current", so the alt_char list from current is 01409 sorted in increasing value as you go to the leaves */ 01410 if (!(*parent_ptr)) { 01411 *parent_ptr = node; 01412 } else { 01413 if ((*parent_ptr)->specificity > node->specificity){ 01414 /* insert at head */ 01415 node->alt_char = (*parent_ptr); 01416 *parent_ptr = node; 01417 } else { 01418 lcurr = *parent_ptr; 01419 for (curr=(*parent_ptr)->alt_char; curr; curr = curr->alt_char) { 01420 if (curr->specificity > node->specificity) { 01421 node->alt_char = curr; 01422 lcurr->alt_char = node; 01423 break; 01424 } 01425 lcurr = curr; 01426 } 01427 if (!curr) 01428 { 01429 lcurr->alt_char = node; 01430 } 01431 } 01432 } 01433 }
| int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 8719 of file pbx.c.
References __ast_custom_function_register(), ast_cli_register_multiple(), AST_EVENT_DEVICE_STATE, AST_EVENT_IE_END, ast_event_subscribe(), ast_log(), ast_manager_register2(), ast_register_application2(), ast_taskprocessor_get(), ast_verb, builtins, device_state_cb(), EVENT_FLAG_CONFIG, EVENT_FLAG_REPORTING, exception_function, LOG_ERROR, LOG_WARNING, manager_show_dialplan(), mandescr_show_dialplan, and pbx_cli.
Referenced by main().
08720 { 08721 int x; 08722 08723 /* Initialize the PBX */ 08724 ast_verb(1, "Asterisk PBX Core Initializing\n"); 08725 if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) { 08726 ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n"); 08727 } 08728 08729 ast_verb(1, "Registering builtin applications:\n"); 08730 ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry)); 08731 __ast_custom_function_register(&exception_function, NULL); 08732 08733 /* Register builtin applications */ 08734 for (x = 0; x < sizeof(builtins) / sizeof(struct pbx_builtin); x++) { 08735 ast_verb(1, "[%s]\n", builtins[x].name); 08736 if (ast_register_application2(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description, NULL)) { 08737 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 08738 return -1; 08739 } 08740 } 08741 08742 /* Register manager application */ 08743 ast_manager_register2("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan, "List dialplan", mandescr_show_dialplan); 08744 08745 if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, NULL, 08746 AST_EVENT_IE_END))) { 08747 return -1; 08748 } 08749 08750 return 0; 08751 }
| void log_match_char_tree | ( | struct match_char * | node, | |
| char * | prefix | |||
| ) |
Definition at line 1106 of file pbx.c.
References match_char::alt_char, ast_debug, ast_str_alloca, ast_str_set(), match_char::deleted, ast_exten::exten, match_char::exten, match_char::is_pattern, match_char::next_char, match_char::specificity, ast_str::str, and match_char::x.
Referenced by ast_context_remove_extension_callerid2(), and pbx_find_extension().
01107 { 01108 char extenstr[40]; 01109 struct ast_str *my_prefix = ast_str_alloca(1024); 01110 01111 extenstr[0] = '\0'; 01112 01113 if (node && node->exten && node->exten) 01114 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01115 01116 if (strlen(node->x) > 1) { 01117 ast_debug(1, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', 01118 node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"", 01119 node->exten ? node->exten->exten : "", extenstr); 01120 } else { 01121 ast_debug(1, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', 01122 node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"", 01123 node->exten ? node->exten->exten : "", extenstr); 01124 } 01125 01126 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01127 01128 if (node->next_char) 01129 log_match_char_tree(node->next_char, my_prefix->str); 01130 01131 if (node->alt_char) 01132 log_match_char_tree(node->alt_char, prefix); 01133 }
| static int lookup_name | ( | const char * | s, | |
| 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 6232 of file pbx.c.
Referenced by get_range().
| static void manager_dpsendack | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Send ack once.
Definition at line 5364 of file pbx.c.
References astman_send_listack().
Referenced by manager_show_dialplan_helper().
05365 { 05366 astman_send_listack(s, m, "DialPlan list will follow", "start"); 05367 }
| static int manager_show_dialplan | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Manager listing of dial plan.
Definition at line 5510 of file pbx.c.
References ast_strlen_zero(), astman_get_header(), astman_send_error(), dialplan_counters::context_existence, EVENT_FLAG_CONFIG, dialplan_counters::extension_existence, manager_event, 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().
05511 { 05512 const char *exten, *context; 05513 const char *id = astman_get_header(m, "ActionID"); 05514 char idtext[256]; 05515 int res; 05516 05517 /* Variables used for different counters */ 05518 struct dialplan_counters counters; 05519 05520 if (!ast_strlen_zero(id)) 05521 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 05522 else 05523 idtext[0] = '\0'; 05524 05525 memset(&counters, 0, sizeof(counters)); 05526 05527 exten = astman_get_header(m, "Extension"); 05528 context = astman_get_header(m, "Context"); 05529 05530 res = manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL); 05531 05532 if (context && !counters.context_existence) { 05533 char errorbuf[BUFSIZ]; 05534 05535 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context); 05536 astman_send_error(s, m, errorbuf); 05537 return 0; 05538 } 05539 if (exten && !counters.extension_existence) { 05540 char errorbuf[BUFSIZ]; 05541 05542 if (context) 05543 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context); 05544 else 05545 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten); 05546 astman_send_error(s, m, errorbuf); 05547 return 0; 05548 } 05549 05550 manager_event(EVENT_FLAG_CONFIG, "ShowDialPlanComplete", 05551 "EventList: Complete\r\n" 05552 "ListItems: %d\r\n" 05553 "ListExtensions: %d\r\n" 05554 "ListPriorities: %d\r\n" 05555 "ListContexts: %d\r\n" 05556 "%s" 05557 "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext); 05558 05559 /* everything ok */ 05560 return 0; 05561 }
| 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 5373 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().
05377 { 05378 struct ast_context *c; 05379 int res = 0, old_total_exten = dpc->total_exten; 05380 05381 if (ast_strlen_zero(exten)) 05382 exten = NULL; 05383 if (ast_strlen_zero(context)) 05384 context = NULL; 05385 05386 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten); 05387 05388 /* try to lock contexts */ 05389 if (ast_rdlock_contexts()) { 05390 astman_send_error(s, m, "Failed to lock contexts"); 05391 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n"); 05392 return -1; 05393 } 05394 05395 c = NULL; /* walk all contexts ... */ 05396 while ( (c = ast_walk_contexts(c)) ) { 05397 struct ast_exten *e; 05398 struct ast_include *i; 05399 struct ast_ignorepat *ip; 05400 05401 if (context && strcmp(ast_get_context_name(c), context) != 0) 05402 continue; /* not the name we want */ 05403 05404 dpc->context_existence = 1; 05405 05406 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c)); 05407 05408 if (ast_rdlock_context(c)) { /* failed to lock */ 05409 ast_debug(3, "manager_show_dialplan: Failed to lock context\n"); 05410 continue; 05411 } 05412 05413 /* XXX note- an empty context is not printed */ 05414 e = NULL; /* walk extensions in context */ 05415 while ( (e = ast_walk_context_extensions(c, e)) ) { 05416 struct ast_exten *p; 05417 05418 /* looking for extension? is this our extension? */ 05419 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) { 05420 /* not the one we are looking for, continue */ 05421 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e)); 05422 continue; 05423 } 05424 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e)); 05425 05426 dpc->extension_existence = 1; 05427 05428 /* may we print context info? */ 05429 dpc->total_context++; 05430 dpc->total_exten++; 05431 05432 p = NULL; /* walk next extension peers */ 05433 while ( (p = ast_walk_extension_priorities(e, p)) ) { 05434 int prio = ast_get_extension_priority(p); 05435 05436 dpc->total_prio++; 05437 if (!dpc->total_items++) 05438 manager_dpsendack(s, m); 05439 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 05440 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) ); 05441 05442 /* XXX maybe make this conditional, if p != e ? */ 05443 if (ast_get_extension_label(p)) 05444 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p)); 05445 05446 if (prio == PRIORITY_HINT) { 05447 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p)); 05448 } else { 05449 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)); 05450 } 05451 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e)); 05452 } 05453 } 05454 05455 i = NULL; /* walk included and write info ... */ 05456 while ( (i = ast_walk_context_includes(c, i)) ) { 05457 if (exten) { 05458 /* Check all includes for the requested extension */ 05459 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i); 05460 } else { 05461 if (!dpc->total_items++) 05462 manager_dpsendack(s, m); 05463 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 05464 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)); 05465 astman_append(s, "\r\n"); 05466 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i)); 05467 } 05468 } 05469 05470 ip = NULL; /* walk ignore patterns and write info ... */ 05471 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 05472 const char *ipname = ast_get_ignorepat_name(ip); 05473 char ignorepat[AST_MAX_EXTENSION]; 05474 05475 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 05476 if (!exten || ast_extension_match(ignorepat, exten)) { 05477 if (!dpc->total_items++) 05478 manager_dpsendack(s, m); 05479 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 05480 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip)); 05481 astman_append(s, "\r\n"); 05482 } 05483 } 05484 if (!rinclude) { 05485 struct ast_sw *sw = NULL; 05486 while ( (sw = ast_walk_context_switches(c, sw)) ) { 05487 if (!dpc->total_items++) 05488 manager_dpsendack(s, m); 05489 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 05490 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)); 05491 astman_append(s, "\r\n"); 05492 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw)); 05493 } 05494 } 05495 05496 ast_unlock_context(c); 05497 } 05498 ast_unlock_contexts(); 05499 05500 if (dpc->total_exten == old_total_exten) { 05501 ast_debug(3, "manager_show_dialplan: Found nothing new\n"); 05502 /* Nothing new under the sun */ 05503 return -1; 05504 } else { 05505 return res; 05506 } 05507 }
| static int matchcid | ( | const char * | cidpattern, | |
| const char * | callerid | |||
| ) | [static] |
Definition at line 2057 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
02058 { 02059 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 02060 failing to get a number should count as a match, otherwise not */ 02061 02062 if (ast_strlen_zero(callerid)) 02063 return ast_strlen_zero(cidpattern) ? 1 : 0; 02064 02065 return ast_extension_match(cidpattern, callerid); 02066 }
| 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 1236 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, 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().
01237 { 01238 struct match_char *p; /* note minimal stack storage requirements */ 01239 struct ast_exten pattern = { .label = label }; 01240 #ifdef DEBUG_THIS 01241 if (tree) 01242 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action)); 01243 else 01244 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action)); 01245 #endif 01246 for (p=tree; p; p=p->alt_char) { 01247 if (p->x[0] == 'N') { 01248 if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) { 01249 #define NEW_MATCHER_CHK_MATCH \ 01250 if (p->exten && !(*(str+1))) { /* if a shorter pattern matches along the way, might as well report it */ \ 01251 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \ 01252 update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted, p); \ 01253 if (!p->deleted) { \ 01254 if (action == E_FINDLABEL) { \ 01255 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \ 01256 ast_debug(4, "Found label in preferred extension\n"); \ 01257 return; \ 01258 } \ 01259 } else { \ 01260 ast_debug(4,"returning an exact match-- first found-- %s\n", p->exten->exten); \ 01261 return; /* the first match, by definition, will be the best, because of the sorted tree */ \ 01262 } \ 01263 } \ 01264 } \ 01265 } 01266 01267 #define NEW_MATCHER_RECURSE \ 01268 if (p->next_char && ( *(str+1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \ 01269 || p->next_char->x[0] == '!')) { \ 01270 if (*(str+1) || p->next_char->x[0] == '!') { \ 01271 new_find_extension(str+1, score, p->next_char, length+1, spec+p->specificity, callerid, label, action); \ 01272 if (score->exten) { \ 01273 ast_debug(4,"returning an exact match-- %s\n", score->exten->exten); \ 01274 return; /* the first match is all we need */ \ 01275 } \ 01276 } else { \ 01277 new_find_extension("/", score, p->next_char, length+1, spec+p->specificity, callerid, label, action); \ 01278 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \ 01279 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \ 01280 "NULL"); \ 01281 return; /* the first match is all we need */ \ 01282 } \ 01283 } \ 01284 } else if (p->next_char && !*(str+1)) { \ 01285 score->canmatch = 1; \ 01286 score->canmatch_exten = get_canmatch_exten(p); \ 01287 if (action == E_CANMATCH || action == E_MATCHMORE) { \ 01288 ast_debug(4,"returning a canmatch/matchmore--- str=%s\n", str); \ 01289 return; \ 01290 } \ 01291 } 01292 01293 NEW_MATCHER_CHK_MATCH; 01294 NEW_MATCHER_RECURSE; 01295 } 01296 } else if (p->x[0] == 'Z') { 01297 if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) { 01298 NEW_MATCHER_CHK_MATCH; 01299 NEW_MATCHER_RECURSE; 01300 } 01301 } else if (p->x[0] == 'X') { 01302 if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) { 01303 NEW_MATCHER_CHK_MATCH; 01304 NEW_MATCHER_RECURSE; 01305 } 01306 } else if (p->x[0] == '.' && p->x[1] == 0) { 01307 /* how many chars will the . match against? */ 01308 int i = 0; 01309 const char *str2 = str; 01310 while (*str2 && *str2 != '/') { 01311 str2++; 01312 i++; 01313 } 01314 if (p->exten && *str2 != '/') { 01315 update_scoreboard(score, length+i, spec+(i*p->specificity), p->exten, '.', callerid, p->deleted, p); 01316 if (score->exten) { 01317 ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten); 01318 return; /* the first match is all we need */ 01319 } 01320 } 01321 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01322 new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid, label, action); 01323 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01324 ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL"); 01325 return; /* the first match is all we need */ 01326 } 01327 } 01328 } else if (p->x[0] == '!' && p->x[1] == 0) { 01329 /* how many chars will the . match against? */ 01330 int i = 1; 01331 const char *str2 = str; 01332 while (*str2 && *str2 != '/') { 01333 str2++; 01334 i++; 01335 } 01336 if (p->exten && *str2 != '/') { 01337 update_scoreboard(score, length+1, spec+(p->specificity*i), p->exten, '!', callerid, p->deleted, p); 01338 if (score->exten) { 01339 ast_debug(4,"return because scoreboard has a '!' match--- %s\n", score->exten->exten); 01340 return; /* the first match is all we need */ 01341 } 01342 } 01343 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01344 new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid, label, action); 01345 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01346 ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01347 return; /* the first match is all we need */ 01348 } 01349 } 01350 } else if (p->x[0] == '/' && p->x[1] == 0) { 01351 /* the pattern in the tree includes the cid match! */ 01352 if (p->next_char && callerid && *callerid) { 01353 new_find_extension(callerid, score, p->next_char, length+1, spec, callerid, label, action); 01354 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01355 ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01356 return; /* the first match is all we need */ 01357 } 01358 } 01359 } else if (strchr(p->x, *str)) { 01360 ast_debug(4, "Nothing strange about this match\n"); 01361 NEW_MATCHER_CHK_MATCH; 01362 NEW_MATCHER_RECURSE; 01363 } 01364 } 01365 ast_debug(4,"return at end of func\n"); 01366 }
| static int parse_variable_name | ( | char * | var, | |
| int * | offset, | |||
| int * | length, | |||
| int * | isfunc | |||
| ) | [static] |
extract offset:length from variable name.
Definition at line 2392 of file pbx.c.
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
02393 { 02394 int parens = 0; 02395 02396 *offset = 0; 02397 *length = INT_MAX; 02398 *isfunc = 0; 02399 for (; *var; var++) { 02400 if (*var == '(') { 02401 (*isfunc)++; 02402 parens++; 02403 } else if (*var == ')') { 02404 parens--; 02405 } else if (*var == ':' && parens == 0) { 02406 *var++ = '\0'; 02407 sscanf(var, "%30d:%30d", offset, length); 02408 return 1; /* offset:length valid */ 02409 } 02410 } 02411 return 0; 02412 }
| void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 8599 of file pbx.c.
References AST_LIST_REMOVE_HEAD, ast_rwlock_unlock(), ast_rwlock_wrlock(), and ast_var_delete().
Referenced by handle_cli_dialplan_reload(), and reload().
08600 { 08601 struct ast_var_t *vardata; 08602 08603 ast_rwlock_wrlock(&globalslock); 08604 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 08605 ast_var_delete(vardata); 08606 ast_rwlock_unlock(&globalslock); 08607 }
| const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
| const char * | name | |||
| ) |
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 8369 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(), and ast_channel::varshead.
Referenced by __ast_pbx_run(), _macro_exec(), _while_exec(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), array(), ast_bridge_call(), ast_call_forward(), ast_eivr_getvariable(), ast_feature_interpret(), ast_monitor_stop(), ast_park_call_full(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), dahdi_call(), dahdi_hangup(), dial_exec_full(), do_forward(), do_timelimit(), dundi_exec(), dundi_helper(), findparkinglotname(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_exec(), import_ch(), leave_voicemail(), local_hangup(), local_read(), login_exec(), macro_fixup(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_space_reserve(), pbx_builtin_background(), pickup_by_mark(), queue_exec(), real_ctx(), retrydial_exec(), ring_entry(), run_agi(), 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().
08370 { 08371 struct ast_var_t *variables; 08372 const char *ret = NULL; 08373 int i; 08374 struct varshead *places[2] = { NULL, &globals }; 08375 08376 if (!name) 08377 return NULL; 08378 08379 if (chan) { 08380 ast_channel_lock(chan); 08381 places[0] = &chan->varshead; 08382 } 08383 08384 for (i = 0; i < 2; i++) { 08385 if (!places[i]) 08386 continue; 08387 if (places[i] == &globals) 08388 ast_rwlock_rdlock(&globalslock); 08389 AST_LIST_TRAVERSE(places[i], variables, entries) { 08390 if (!strcmp(name, ast_var_name(variables))) { 08391 ret = ast_var_value(variables); 08392 break; 08393 } 08394 } 08395 if (places[i] == &globals) 08396 ast_rwlock_unlock(&globalslock); 08397 if (ret) 08398 break; 08399 } 08400 08401 if (chan) 08402 ast_channel_unlock(chan); 08403 08404 return ret; 08405 }
| static int pbx_builtin_gotoif | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 8621 of file pbx.c.
References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), pbx_checkcondition(), and strsep().
08622 { 08623 char *condition, *branch1, *branch2, *branch; 08624 char *stringp; 08625 08626 if (ast_strlen_zero(data)) { 08627 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 08628 return 0; 08629 } 08630 08631 stringp = ast_strdupa(data); 08632 condition = strsep(&stringp,"?"); 08633 branch1 = strsep(&stringp,":"); 08634 branch2 = strsep(&stringp,""); 08635 branch = pbx_checkcondition(condition) ? branch1 : branch2; 08636 08637 if (ast_strlen_zero(branch)) { 08638 ast_debug(1, "Not taking any branch\n"); 08639 return 0; 08640 } 08641 08642 return pbx_builtin_goto(chan, branch); 08643 }
| int pbx_builtin_importvar | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 8557 of file pbx.c.
References ast_channel_unlock, ast_get_channel_by_name_locked(), ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), s, strsep(), and VAR_BUF_SIZE.
08558 { 08559 char *name; 08560 char *value; 08561 char *channel; 08562 char tmp[VAR_BUF_SIZE]; 08563 static int deprecation_warning = 0; 08564 08565 if (ast_strlen_zero(data)) { 08566 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 08567 return 0; 08568 } 08569 tmp[0] = 0; 08570 if (!deprecation_warning) { 08571 ast_log(LOG_WARNING, "ImportVar is deprecated. Please use Set(varname=${IMPORT(channel,variable)}) instead.\n"); 08572 deprecation_warning = 1; 08573 } 08574 08575 value = ast_strdupa(data); 08576 name = strsep(&value,"="); 08577 channel = strsep(&value,","); 08578 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 08579 struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel); 08580 if (chan2) { 08581 char *s = alloca(strlen(value) + 4); 08582 if (s) { 08583 sprintf(s, "${%s}", value); 08584 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 08585 } 08586 ast_channel_unlock(chan2); 08587 } 08588 pbx_builtin_setvar_helper(chan, name, tmp); 08589 } 08590 08591 return(0); 08592 }
| static int pbx_builtin_incomplete | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 7960 of file pbx.c.
References __ast_answer(), ast_channel::_state, ast_check_hangup(), AST_PBX_INCOMPLETE, AST_STATE_UP, and ast_strlen_zero().
07961 { 07962 char *options = data; 07963 int answer = 1; 07964 07965 /* Some channels can receive DTMF in unanswered state; some cannot */ 07966 if (!ast_strlen_zero(options) && strchr(options, 'n')) { 07967 answer = 0; 07968 } 07969 07970 /* If the channel is hungup, stop waiting */ 07971 if (ast_check_hangup(chan)) { 07972 return -1; 07973 } else if (chan->_state != AST_STATE_UP && answer) { 07974 __ast_answer(chan, 0, 1); 07975 } 07976 07977 return AST_PBX_INCOMPLETE; 07978 }
| static int pbx_builtin_noop | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
| void pbx_builtin_pushvar_helper | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| const char * | value | |||
| ) |
Definition at line 8407 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, LOG_WARNING, and ast_channel::varshead.
Referenced by acf_odbc_read(), acf_odbc_write(), and frame_set_var().
08408 { 08409 struct ast_var_t *newvariable; 08410 struct varshead *headp; 08411 08412 if (name[strlen(name)-1] == ')') { 08413 char *function = ast_strdupa(name); 08414 08415 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 08416 ast_func_write(chan, function, value); 08417 return; 08418 } 08419 08420 if (chan) { 08421 ast_channel_lock(chan); 08422 headp = &chan->varshead; 08423 } else { 08424 ast_rwlock_wrlock(&globalslock); 08425 headp = &globals; 08426 } 08427 08428 if (value) { 08429 if (headp == &globals) 08430 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 08431 newvariable = ast_var_assign(name, value); 08432 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 08433 } 08434 08435 if (chan) 08436 ast_channel_unlock(chan); 08437 else 08438 ast_rwlock_unlock(&globalslock); 08439 }
| int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
| void * | vreason | |||
| ) |
Definition at line 2595 of file pbx.c.
References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), ast_free, ast_string_field_init, ast_string_field_set, ast_channel::context, ast_datastore::data, exception_store_info, ast_channel::exten, ast_channel::priority, pbx_exception::priority, and set_ext_pri().
Referenced by __ast_pbx_run().
02596 { 02597 const char *reason = vreason; 02598 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 02599 struct pbx_exception *exception = NULL; 02600 02601 if (!ds) { 02602 ds = ast_datastore_alloc(&exception_store_info, NULL); 02603 if (!ds) 02604 return -1; 02605 exception = ast_calloc(1, sizeof(struct pbx_exception)); 02606 if (!exception) { 02607 ast_datastore_free(ds); 02608 return -1; 02609 } 02610 if (ast_string_field_init(exception, 128)) { 02611 ast_free(exception); 02612 ast_datastore_free(ds); 02613 return -1; 02614 } 02615 ds->data = exception; 02616 ast_channel_datastore_add(chan, ds); 02617 } else 02618 exception = ds->data; 02619 02620 ast_string_field_set(exception, reason, reason); 02621 ast_string_field_set(exception, context, chan->context); 02622 ast_string_field_set(exception, exten, chan->exten); 02623 exception->priority = chan->priority; 02624 set_ext_pri(chan, "e", 0); 02625 return 0; 02626 }
| static int pbx_builtin_saycharacters | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 8682 of file pbx.c.
References ast_say_character_str().
08683 { 08684 int res = 0; 08685 08686 if (data) 08687 res = ast_say_character_str(chan, data, "", chan->language); 08688 return res; 08689 }
| static int pbx_builtin_saydigits | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 8673 of file pbx.c.
References ast_say_digit_str().
08674 { 08675 int res = 0; 08676 08677 if (data) 08678 res = ast_say_digit_str(chan, data, "", chan->language); 08679 return res; 08680 }
| static int pbx_builtin_saynumber | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 8645 of file pbx.c.
References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), LOG_WARNING, and strsep().
08646 { 08647 char tmp[256]; 08648 char *number = tmp; 08649 char *options; 08650 08651 if (ast_strlen_zero(data)) { 08652 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 08653 return -1; 08654 } 08655 ast_copy_string(tmp, data, sizeof(tmp)); 08656 strsep(&number, ","); 08657 options = strsep(&number, ","); 08658 if (options) { 08659 if ( strcasecmp(options, "f") && strcasecmp(options, "m") && 08660 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 08661 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 08662 return -1; 08663 } 08664 } 08665 08666 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 08667 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 08668 } 08669 08670 return 0; 08671 }
| static int pbx_builtin_sayphonetic | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 8691 of file pbx.c.
References ast_say_phonetic_str().
08692 { 08693 int res = 0; 08694 08695 if (data) 08696 res = ast_say_phonetic_str(chan, data, "", chan->language); 08697 return res; 08698 }
| int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
| struct ast_str ** | buf | |||
| ) |
Definition at line 8337 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_var_name(), ast_var_value(), LOG_ERROR, total, var, and ast_channel::varshead.
Referenced by dumpchan_exec(), handle_show_chanvar(), handle_showchan(), and vars2manager().
08338 { 08339 struct ast_var_t *variables; 08340 const char *var, *val; 08341 int total = 0; 08342 08343 if (!chan) 08344 return 0; 08345 08346 (*buf)->used = 0; 08347 (*buf)->str[0] = '\0'; 08348 08349 ast_channel_lock(chan); 08350 08351 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 08352 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 08353 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 08354 ) { 08355 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 08356 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 08357 break; 08358 } else 08359 total++; 08360 } else 08361 break; 08362 } 08363 08364 ast_channel_unlock(chan); 08365 08366 return total; 08367 }
| int pbx_builtin_setvar | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) |
Definition at line 8498 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 strsep().
Referenced by rpt_exec().
08499 { 08500 char *name, *value, *mydata; 08501 08502 if (ast_compat_app_set) { 08503 return pbx_builtin_setvar_multiple(chan, data); 08504 } 08505 08506 if (ast_strlen_zero(data)) { 08507 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 08508 return 0; 08509 } 08510 08511 mydata = ast_strdupa(data); 08512 name = strsep(&mydata, "="); 08513 value = mydata; 08514 if (strchr(name, ' ')) 08515 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 08516 08517 pbx_builtin_setvar_helper(chan, name, value); 08518 return(0); 08519 }
| void pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| const char * | value | |||
| ) |
Definition at line 8441 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE, AST_LIST_TRAVERSE, ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, manager_event, and ast_channel::varshead.
Referenced by __ast_pbx_run(), __oh323_new(), _macro_exec(), _while_exec(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), action_atxfer(), action_setvar(), agi_exec_full(), aji_status_exec(), aqm_exec(), array(), ast_bridge_call(), ast_eivr_setvariable(), ast_feature_request_and_dial(), ast_iax2_new(), ast_monitor_start(), ast_pbx_outgoing_exten(), ast_rtp_set_vars(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), chanavail_exec(), channel_spy(), conf_run(), controlplayback_exec(), count_exec(), dahdi_handle_dtmfup(), dahdi_new(), dial_exec_full(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), frame_set_var(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parkinglot(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_exec_full(), parse_moved_contact(), pbx_builtin_background(), 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(), pri_dchannel(), privacy_exec(), process_ast_dsp(), read_exec(), readexten_exec(), readfile_exec(), record_exec(), return_exec(), rotate_file(), rpt_exec(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_agentbycallerid(), set_queue_result(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), ss7_start_call(), ss_thread(), start_monitor_exec(), system_exec_helper(), transfer_exec(), transmit(), tryexec_exec(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().
08442 { 08443 struct ast_var_t *newvariable; 08444 struct varshead *headp; 08445 const char *nametail = name; 08446 08447 if (name[strlen(name) - 1] == ')') { 08448 char *function = ast_strdupa(name); 08449 08450 ast_func_write(chan, function, value); 08451 return; 08452 } 08453 08454 if (chan) { 08455 ast_channel_lock(chan); 08456 headp = &chan->varshead; 08457 } else { 08458 ast_rwlock_wrlock(&globalslock); 08459 headp = &globals; 08460 } 08461 08462 /* For comparison purposes, we have to strip leading underscores */ 08463 if (*nametail == '_') { 08464 nametail++; 08465 if (*nametail == '_') 08466 nametail++; 08467 } 08468 08469 AST_LIST_TRAVERSE (headp, newvariable, entries) { 08470 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) { 08471 /* there is already such a variable, delete it */ 08472 AST_LIST_REMOVE(headp, newvariable, entries); 08473 ast_var_delete(newvariable); 08474 break; 08475 } 08476 } 08477 08478 if (value) { 08479 if (headp == &globals) 08480 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 08481 newvariable = ast_var_assign(name, value); 08482 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 08483 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 08484 "Channel: %s\r\n" 08485 "Variable: %s\r\n" 08486 "Value: %s\r\n" 08487 "Uniqueid: %s\r\n", 08488 chan ? chan->name : "none", name, value, 08489 chan ? chan->uniqueid : "none"); 08490 } 08491 08492 if (chan) 08493 ast_channel_unlock(chan); 08494 else 08495 ast_rwlock_unlock(&globalslock); 08496 }
| int pbx_builtin_setvar_multiple | ( | struct ast_channel * | chan, | |
| void * | vdata | |||
| ) |
Definition at line 8521 of file pbx.c.
References 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(), and ast_channel::priority.
Referenced by pbx_builtin_setvar(), queue_function_var(), set_queue_variables(), and try_calling().
08522 { 08523 char *data; 08524 int x; 08525 AST_DECLARE_APP_ARGS(args, 08526 AST_APP_ARG(pair)[24]; 08527 ); 08528 AST_DECLARE_APP_ARGS(pair, 08529 AST_APP_ARG(name); 08530 AST_APP_ARG(value); 08531 ); 08532 08533 if (ast_strlen_zero(vdata)) { 08534 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 08535 return 0; 08536 } 08537 08538 data = ast_strdupa(vdata); 08539 AST_STANDARD_APP_ARGS(args, data); 08540 08541 for (x = 0; x < args.argc; x++) { 08542 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 08543 if (pair.argc == 2) { 08544 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 08545 if (strchr(pair.name, ' ')) 08546 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); 08547 } else if (!chan) { 08548 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 08549 } else { 08550 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 08551 } 08552 } 08553 08554 return 0; 08555 }
| 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 8609 of file pbx.c.
References ast_strlen_zero().
Referenced by _macro_exec(), _while_exec(), acf_if(), execif_exec(), gosubif_exec(), macroif_exec(), and pbx_builtin_gotoif().
08610 { 08611 int res; 08612 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 08613 return 0; 08614 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 08615 return res; 08616 } else { /* Strings are true */ 08617 return 1; 08618 } 08619 }
| static void pbx_destroy | ( | struct ast_pbx * | p | ) | [static] |
Definition at line 1011 of file pbx.c.
References ast_free.
Referenced by __ast_pbx_run().
01012 { 01013 ast_free(p); 01014 }
| int pbx_exec | ( | struct ast_channel * | c, | |
| struct ast_app * | app, | |||
| void * | 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.
| c | Channel | |
| app | Application | |
| data | Data for execution |
Definition at line 934 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_channel::appl, ast_cdr_setapp(), ast_check_hangup(), ast_log(), ast_opt_dont_warn, ast_strlen_zero(), ast_channel::cdr, ast_channel::data, ast_app::execute, LOG_WARNING, and S_OR.
Referenced by answer_exec_run(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), 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().
00937 { 00938 int res; 00939 struct ast_module_user *u = NULL; 00940 const char *saved_c_appl; 00941 const char *saved_c_data; 00942 00943 if (c->cdr && !ast_check_hangup(c)) 00944 ast_cdr_setapp(c->cdr, app->name, data); 00945 00946 /* save channel values */ 00947 saved_c_appl= c->appl; 00948 saved_c_data= c->data; 00949 00950 c->appl = app->name; 00951 c->data = data; 00952 if (app->module) 00953 u = __ast_module_user_add(app->module, c); 00954 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 00955 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 00956 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 00957 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 00958 app->name, (char *) data); 00959 } 00960 res = app->execute(c, S_OR(data, "")); 00961 if (app->module && u) 00962 __ast_module_user_remove(app->module, u); 00963 /* restore channel values */ 00964 c->appl = saved_c_appl; 00965 c->data = saved_c_data; 00966 return res; 00967 }
| 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 3153 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, 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().
03156 { 03157 struct ast_exten *e; 03158 struct ast_app *app; 03159 int res; 03160 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 03161 char passdata[EXT_DATA_SIZE]; 03162 03163 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 03164 03165 ast_rdlock_contexts(); 03166 if (found) 03167 *found = 0; 03168 03169 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 03170 if (e) { 03171 if (found) 03172 *found = 1; 03173 if (matching_action) { 03174 ast_unlock_contexts(); 03175 return -1; /* success, we found it */ 03176 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 03177 res = e->priority; 03178 ast_unlock_contexts(); 03179 return res; /* the priority we were looking for */ 03180 } else { /* spawn */ 03181 if (!e->cached_app) 03182 e->cached_app = pbx_findapp(e->app); 03183 app = e->cached_app; 03184 ast_unlock_contexts(); 03185 if (!app) { 03186 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 03187 return -1; 03188 } 03189 if (c->context != context) 03190 ast_copy_string(c->context, context, sizeof(c->context)); 03191 if (c->exten != exten) 03192 ast_copy_string(c->exten, exten, sizeof(c->exten)); 03193 c->priority = priority; 03194 pbx_substitute_variables(passdata, sizeof(passdata), c, e); 03195 #ifdef CHANNEL_TRACE 03196 ast_channel_trace_update(c); 03197 #endif 03198 ast_debug(1, "Launching '%s'\n", app->name); 03199 if (VERBOSITY_ATLEAST(3)) { 03200 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 03201 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 03202 exten, context, priority, 03203 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 03204 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 03205 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 03206 "in new stack"); 03207 } 03208 manager_event(EVENT_FLAG_DIALPLAN, "Newexten", 03209 "Channel: %s\r\n" 03210 "Context: %s\r\n" 03211 "Extension: %s\r\n" 03212 "Priority: %d\r\n" 03213 "Application: %s\r\n" 03214 "AppData: %s\r\n" 03215 "Uniqueid: %s\r\n", 03216 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 03217 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 03218 } 03219 } else if (q.swo) { /* not found here, but in another switch */ 03220 if (found) 03221 *found = 1; 03222 ast_unlock_contexts(); 03223 if (matching_action) { 03224 return -1; 03225 } else { 03226 if (!q.swo->exec) { 03227 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 03228 res = -1; 03229 } 03230 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 03231 } 03232 } else { /* not found anywhere, see what happened */ 03233 ast_unlock_contexts(); 03234 /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */ 03235 switch (q.status) { 03236 case STATUS_NO_CONTEXT: 03237 if (!matching_action && !combined_find_spawn) 03238 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, "")); 03239 break; 03240 case STATUS_NO_EXTENSION: 03241 if (!matching_action && !combined_find_spawn) 03242 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, "")); 03243 break; 03244 case STATUS_NO_PRIORITY: 03245 if (!matching_action && !combined_find_spawn) 03246 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, "")); 03247 break; 03248 case STATUS_NO_LABEL: 03249 if (context && !combined_find_spawn) 03250 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, "")); 03251 break; 03252 default: 03253 ast_debug(1, "Shouldn't happen!\n"); 03254 } 03255 03256 return (matching_action) ? 0 : -1; 03257 } 03258 }
| 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 2068 of file pbx.c.
References ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_thread_get(), ast_strdupa, ast_strlen_zero(), ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), 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, extension_match_core(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, ast_str::len, LOG_DEBUG, log_match_char_tree(), LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_sw::name, new_find_extension(), ast_include::next, scoreboard::node, 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, ast_str::str, strsep(), 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(), pbx_extension_helper(), pbx_find_extension(), and register_peer_exten().
02072 { 02073 int x, res; 02074 struct ast_context *tmp = NULL; 02075 struct ast_exten *e = NULL, *eroot = NULL; 02076 struct ast_include *i = NULL; 02077 struct ast_sw *sw = NULL; 02078 struct ast_exten pattern = {NULL, }; 02079 struct scoreboard score = {0, }; 02080 struct ast_str *tmpdata = NULL; 02081 02082 pattern.label = label; 02083 pattern.priority = priority; 02084 #ifdef NEED_DEBUG_HERE 02085 ast_log(LOG_NOTICE,"Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int)action); 02086 #endif 02087 02088 /* Initialize status if appropriate */ 02089 if (q->stacklen == 0) { 02090 q->status = STATUS_NO_CONTEXT; 02091 q->swo = NULL; 02092 q->data = NULL; 02093 q->foundcontext = NULL; 02094 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02095 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02096 return NULL; 02097 } 02098 02099 /* Check first to see if we've already been checked */ 02100 for (x = 0; x < q->stacklen; x++) { 02101 if (!strcasecmp(q->incstack[x], context)) 02102 return NULL; 02103 } 02104 02105 if (bypass) /* bypass means we only look there */ 02106 tmp = bypass; 02107 else { /* look in contexts */ 02108 struct fake_context item; 02109 02110 ast_copy_string(item.name, context, sizeof(item.name)); 02111 02112 tmp = ast_hashtab_lookup(contexts_table, &item); 02113 #ifdef NOTNOW 02114 tmp = NULL; 02115 while ((tmp = ast_walk_contexts(tmp)) ) { 02116 if (!strcmp(tmp->name, context)) 02117 break; 02118 } 02119 #endif 02120 if (!tmp) 02121 return NULL; 02122 02123 } 02124 02125 if (q->status < STATUS_NO_EXTENSION) 02126 q->status = STATUS_NO_EXTENSION; 02127 02128 /* Do a search for matching extension */ 02129 02130 eroot = NULL; 02131 score.total_specificity = 0; 02132 score.exten = 0; 02133 score.total_length = 0; 02134 if (!tmp->pattern_tree && tmp->root_table) 02135 { 02136 create_match_char_tree(tmp); 02137 #ifdef NEED_DEBUG 02138 ast_log(LOG_DEBUG,"Tree Created in context %s:\n", context); 02139 log_match_char_tree(tmp->pattern_tree," "); 02140 #endif 02141 } 02142 #ifdef NEED_DEBUG 02143 ast_log(LOG_NOTICE,"The Trie we are searching in:\n"); 02144 log_match_char_tree(tmp->pattern_tree, ":: "); 02145 #endif 02146 02147 do { 02148 if (!ast_strlen_zero(overrideswitch)) { 02149 char *osw = ast_strdupa(overrideswitch), *name; 02150 struct ast_switch *asw; 02151 ast_switch_f *aswf = NULL; 02152 char *datap; 02153 int eval = 0; 02154 02155 name = strsep(&osw, "/"); 02156 asw = pbx_findswitch(name); 02157 02158 if (!asw) { 02159 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 02160 break; 02161 } 02162 02163 if (osw && strchr(osw, '$')) { 02164 eval = 1; 02165 } 02166 02167 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02168 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!"); 02169 break; 02170 } else if (eval) { 02171 /* Substitute variables now */ 02172 pbx_substitute_variables_helper(chan, osw, tmpdata->str, tmpdata->len); 02173 datap = tmpdata->str; 02174 } else { 02175 datap = osw; 02176 } 02177 02178 /* equivalent of extension_match_core() at the switch level */ 02179 if (action == E_CANMATCH) 02180 aswf = asw->canmatch; 02181 else if (action == E_MATCHMORE) 02182 aswf = asw->matchmore; 02183 else /* action == E_MATCH */ 02184 aswf = asw->exists; 02185 if (!aswf) { 02186 res = 0; 02187 } else { 02188 if (chan) { 02189 ast_autoservice_start(chan); 02190 } 02191 res = aswf(chan, context, exten, priority, callerid, datap); 02192 if (chan) { 02193 ast_autoservice_stop(chan); 02194 } 02195 } 02196 if (res) { /* Got a match */ 02197 q->swo = asw; 02198 q->data = datap; 02199 q->foundcontext = context; 02200 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02201 return NULL; 02202 } 02203 } 02204 } while (0); 02205 02206 if (extenpatternmatchnew) { 02207 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02208 eroot = score.exten; 02209 02210 if (score.last_char == '!' && action == E_MATCHMORE) { 02211 /* We match an extension ending in '!'. 02212 * The decision in this case is final and is NULL (no match). 02213 */ 02214 #ifdef NEED_DEBUG_HERE 02215 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02216 #endif 02217 return NULL; 02218 } 02219 02220 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02221 q->status = STATUS_SUCCESS; 02222 #ifdef NEED_DEBUG_HERE 02223 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02224 #endif 02225 return score.canmatch_exten; 02226 } 02227 02228 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02229 if (score.node) { 02230 struct ast_exten *z = trie_find_next_match(score.node); 02231 if (z) { 02232 #ifdef NEED_DEBUG_HERE 02233 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02234 #endif 02235 } else { 02236 if (score.canmatch_exten) { 02237 #ifdef NEED_DEBUG_HERE 02238 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02239 #endif 02240 return score.canmatch_exten; 02241 } else { 02242 #ifdef NEED_DEBUG_HERE 02243 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02244 #endif 02245 } 02246 } 02247 return z; 02248 } 02249 #ifdef NEED_DEBUG_HERE 02250 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02251 #endif 02252 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02253 } 02254 02255 if (eroot) { 02256 /* found entry, now look for the right priority */ 02257 if (q->status < STATUS_NO_PRIORITY) 02258 q->status = STATUS_NO_PRIORITY; 02259 e = NULL; 02260 if (action == E_FINDLABEL && label ) { 02261 if (q->status < STATUS_NO_LABEL) 02262 q->status = STATUS_NO_LABEL; 02263 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02264 } else { 02265 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02266 } 02267 if (e) { /* found a valid match */ 02268 q->status = STATUS_SUCCESS; 02269 q->foundcontext = context; 02270 #ifdef NEED_DEBUG_HERE 02271 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 02272 #endif 02273 return e; 02274 } 02275 } 02276 } else { /* the old/current default exten pattern match algorithm */ 02277 02278 /* scan the list trying to match extension and CID */ 02279 eroot = NULL; 02280 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 02281 int match = extension_match_core(eroot->exten, exten, action); 02282 /* 0 on fail, 1 on match, 2 on earlymatch */ 02283 02284 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 02285 continue; /* keep trying */ 02286 if (match == 2 && action == E_MATCHMORE) { 02287 /* We match an extension ending in '!'. 02288 * The decision in this case is final and is NULL (no match). 02289 */ 02290 return NULL; 02291 } 02292 /* found entry, now look for the right priority */ 02293 if (q->status < STATUS_NO_PRIORITY) 02294 q->status = STATUS_NO_PRIORITY; 02295 e = NULL; 02296 if (action == E_FINDLABEL && label ) { 02297 if (q->status < STATUS_NO_LABEL) 02298 q->status = STATUS_NO_LABEL; 02299 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02300 } else { 02301 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02302 } 02303 #ifdef NOTNOW 02304 while ( (e = ast_walk_extension_priorities(eroot, e)) ) { 02305 /* Match label or priority */ 02306 if (action == E_FINDLABEL) { 02307 if (q->status < STATUS_NO_LABEL) 02308 q->status = STATUS_NO_LABEL; 02309 if (label && e->label && !strcmp(label, e->label)) 02310 break; /* found it */ 02311 } else if (e->priority == priority) { 02312 break; /* found it */ 02313 } /* else keep searching */ 02314 } 02315 #endif 02316 if (e) { /* found a valid match */ 02317 q->status = STATUS_SUCCESS; 02318 q->foundcontext = context; 02319 return e; 02320 } 02321 } 02322 } 02323 02324 02325 /* Check alternative switches */ 02326 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 02327 struct ast_switch *asw = pbx_findswitch(sw->name); 02328 ast_switch_f *aswf = NULL; 02329 char *datap; 02330 02331 if (!asw) { 02332 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 02333 continue; 02334 } 02335 /* Substitute variables now */ 02336 02337 if (sw->eval) { 02338 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02339 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 02340 continue; 02341 } 02342 pbx_substitute_variables_helper(chan, sw->data, tmpdata->str, tmpdata->len); 02343 } 02344 02345 /* equivalent of extension_match_core() at the switch level */ 02346 if (action == E_CANMATCH) 02347 aswf = asw->canmatch; 02348 else if (action == E_MATCHMORE) 02349 aswf = asw->matchmore; 02350 else /* action == E_MATCH */ 02351 aswf = asw->exists; 02352 datap = sw->eval ? tmpdata->str : sw->data; 02353 if (!aswf) 02354 res = 0; 02355 else { 02356 if (chan) 02357 ast_autoservice_start(chan); 02358 res = aswf(chan, context, exten, priority, callerid, datap); 02359 if (chan) 02360 ast_autoservice_stop(chan); 02361 } 02362 if (res) { /* Got a match */ 02363 q->swo = asw; 02364 q->data = datap; 02365 q->foundcontext = context; 02366 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02367 return NULL; 02368 } 02369 } 02370 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 02371 /* Now try any includes we have in this context */ 02372 for (i = tmp->includes; i; i = i->next) { 02373 if (include_valid(i)) { 02374 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 02375 #ifdef NEED_DEBUG_HERE 02376 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 02377 #endif 02378 return e; 02379 } 02380 if (q->swo) 02381 return NULL; 02382 } 02383 } 02384 return NULL; 02385 }
| struct ast_app* pbx_findapp | ( | const char * | app | ) | [read] |
Find application handle in linked list.
Look up an application.
Definition at line 975 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, and AST_RWLIST_UNLOCK.
Referenced by answer_exec_run(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), 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().
00976 { 00977 struct ast_app *tmp; 00978 00979 AST_RWLIST_RDLOCK(&apps); 00980 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 00981 if (!strcasecmp(tmp->name, app)) 00982 break; 00983 } 00984 AST_RWLIST_UNLOCK(&apps); 00985 00986 return tmp; 00987 }
| static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static, read] |
Definition at line 989 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_switch::name.
Referenced by pbx_find_extension().
00990 { 00991 struct ast_switch *asw; 00992 00993 AST_RWLIST_RDLOCK(&switches); 00994 AST_RWLIST_TRAVERSE(&switches, asw, list) { 00995 if (!strcasecmp(asw->name, sw)) 00996 break; 00997 } 00998 AST_RWLIST_UNLOCK(&switches); 00999 01000 return asw; 01001 }
| static int pbx_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string, | |||
| int | async | |||
| ) | [static] |
Definition at line 8997 of file pbx.c.
References ast_async_goto(), ast_explicit_goto(), ast_findlabel_extension(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::priority, and strsep().
Referenced by ast_async_parseable_goto(), and ast_parseable_goto().
08998 { 08999 char *exten, *pri, *context; 09000 char *stringp; 09001 int ipri; 09002 int mode = 0; 09003 09004 if (ast_strlen_zero(goto_string)) { 09005 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n"); 09006 return -1; 09007 } 09008 stringp = ast_strdupa(goto_string); 09009 context = strsep(&stringp, ","); /* guaranteed non-null */ 09010 exten = strsep(&stringp, ","); 09011 pri = strsep(&stringp, ","); 09012 if (!exten) { /* Only a priority in this one */ 09013 pri = context; 09014 exten = NULL; 09015 context = NULL; 09016 } else if (!pri) { /* Only an extension and priority in this one */ 09017 pri = exten; 09018 exten = context; 09019 context = NULL; 09020 } 09021 if (*pri == '+') { 09022 mode = 1; 09023 pri++; 09024 } else if (*pri == '-') { 09025 mode = -1; 09026 pri++; 09027 } 09028 if (sscanf(pri, "%30d", &ipri) != 1) { 09029 if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten, 09030 pri, chan->cid.cid_num)) < 1) { 09031 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 09032 return -1; 09033 } else 09034 mode = 0; 09035 } 09036 /* At this point we have a priority and maybe an extension and a context */ 09037 09038 if (mode) 09039 ipri = chan->priority + (ipri * mode); 09040 09041 if (async) 09042 ast_async_goto(chan, context, exten, ipri); 09043 else 09044 ast_explicit_goto(chan, context, exten, ipri); 09045 09046 return 0; 09047 09048 }
| 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.
Definition at line 2467 of file pbx.c.
References ARRAY_LEN, ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_copy_string(), ast_eid_default, ast_eid_to_str(), ast_get_hint(), AST_LIST_TRAVERSE, ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_strdupa, ast_var_name(), ast_var_value(), ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_pres, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_channel::exten, ast_channel::hangupcause, parse_variable_name(), ast_channel::priority, s, substring(), and ast_channel::varshead.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
02468 { 02469 const char not_found = '\0'; 02470 char *tmpvar; 02471 const char *s; /* the result */ 02472 int offset, length; 02473 int i, need_substring; 02474 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 02475 02476 if (c) { 02477 ast_channel_lock(c); 02478 places[0] = &c->varshead; 02479 } 02480 /* 02481 * Make a copy of var because parse_variable_name() modifies the string. 02482 * Then if called directly, we might need to run substring() on the result; 02483 * remember this for later in 'need_substring', 'offset' and 'length' 02484 */ 02485 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 02486 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 02487 02488 /* 02489 * Look first into predefined variables, then into variable lists. 02490 * Variable 's' points to the result, according to the following rules: 02491 * s == ¬_found (set at the beginning) means that we did not find a 02492 * matching variable and need to look into more places. 02493 * If s != ¬_found, s is a valid result string as follows: 02494 * s = NULL if the variable does not have a value; 02495 * you typically do this when looking for an unset predefined variable. 02496 * s = workspace if the result has been assembled there; 02497 * typically done when the result is built e.g. with an snprintf(), 02498 * so we don't need to do an additional copy. 02499 * s != workspace in case we have a string, that needs to be copied 02500 * (the ast_copy_string is done once for all at the end). 02501 * Typically done when the result is already available in some string. 02502 */ 02503 s = ¬_found; /* default value */ 02504 if (c) { /* This group requires a valid channel */ 02505 /* Names with common parts are looked up a piece at a time using strncmp. */ 02506 if (!strncmp(var, "CALL", 4)) { 02507 if (!strncmp(var + 4, "ING", 3)) { 02508 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 02509 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres); 02510 s = workspace; 02511 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 02512 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2); 02513 s = workspace; 02514 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 02515 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton); 02516 s = workspace; 02517 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 02518 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns); 02519 s = workspace; 02520 } 02521 } 02522 } else if (!strcmp(var, "HINT")) { 02523 s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL; 02524 } else if (!strcmp(var, "HINTNAME")) { 02525 s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL; 02526 } else if (!strcmp(var, "EXTEN")) { 02527 s = c->exten; 02528 } else if (!strcmp(var, "CONTEXT")) { 02529 s = c->context; 02530 } else if (!strcmp(var, "PRIORITY")) { 02531 snprintf(workspace, workspacelen, "%d", c->priority); 02532 s = workspace; 02533 } else if (!strcmp(var, "CHANNEL")) { 02534 s = c->name; 02535 } else if (!strcmp(var, "UNIQUEID")) { 02536 s = c->uniqueid; 02537 } else if (!strcmp(var, "HANGUPCAUSE")) { 02538 snprintf(workspace, workspacelen, "%d", c->hangupcause); 02539 s = workspace; 02540 } 02541 } 02542 if (s == ¬_found) { /* look for more */ 02543 if (!strcmp(var, "EPOCH")) { 02544 snprintf(workspace, workspacelen, "%u",(int)time(NULL)); 02545 s = workspace; 02546 } else if (!strcmp(var, "SYSTEMNAME")) { 02547 s = ast_config_AST_SYSTEM_NAME; 02548 } else if (!strcmp(var, "ENTITYID")) { 02549 ast_eid_to_str(workspace, workspacelen, &ast_eid_default); 02550 s = workspace; 02551 } 02552 } 02553 /* if not found, look into chanvars or global vars */ 02554 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 02555 struct ast_var_t *variables; 02556 if (!places[i]) 02557 continue; 02558 if (places[i] == &globals) 02559 ast_rwlock_rdlock(&globalslock); 02560 AST_LIST_TRAVERSE(places[i], variables, entries) { 02561 if (!strcasecmp(ast_var_name(variables), var)) { 02562 s = ast_var_value(variables); 02563 break; 02564 } 02565 } 02566 if (places[i] == &globals) 02567 ast_rwlock_unlock(&globalslock); 02568 } 02569 if (s == ¬_found || s == NULL) 02570 *ret = NULL; 02571 else { 02572 if (s != workspace) 02573 ast_copy_string(workspace, s, workspacelen); 02574 *ret = workspace; 02575 if (need_substring) 02576 *ret = substring(*ret, offset, length, workspace, workspacelen); 02577 } 02578 02579 if (c) 02580 ast_channel_unlock(c); 02581 }
| int pbx_set_autofallthrough | ( | int | newval | ) |
Set "autofallthrough" flag, if newval is <0, does not acutally 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 4109 of file pbx.c.
Referenced by pbx_load_module().
04110 { 04111 int oldval = autofallthrough; 04112 autofallthrough = newval; 04113 return oldval; 04114 }
| int pbx_set_extenpatternmatchnew | ( | int | newval | ) |
Set "extenpatternmatchnew" flag, if newval is <0, does not acutally 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 4116 of file pbx.c.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
04117 { 04118 int oldval = extenpatternmatchnew; 04119 extenpatternmatchnew = newval; 04120 return oldval; 04121 }
| 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 4123 of file pbx.c.
References ast_free, ast_strdup, and ast_strlen_zero().
Referenced by pbx_load_module().
04124 { 04125 if (overrideswitch) { 04126 ast_free(overrideswitch); 04127 } 04128 if (!ast_strlen_zero(newval)) { 04129 overrideswitch = ast_strdup(newval); 04130 } else { 04131 overrideswitch = NULL; 04132 } 04133 }
| static void pbx_substitute_variables | ( | char * | passdata, | |
| int | datalen, | |||
| struct ast_channel * | c, | |||
| struct ast_exten * | e | |||
| ) | [static] |
Definition at line 3118 of file pbx.c.
References ast_copy_string(), ast_exten::data, and pbx_substitute_variables_helper().
Referenced by pbx_extension_helper().
03119 { 03120 const char *tmp; 03121 03122 /* Nothing more to do */ 03123 if (!e->data) 03124 return; 03125 03126 /* No variables or expressions in e->data, so why scan it? */ 03127 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) { 03128 ast_copy_string(passdata, e->data, datalen); 03129 return; 03130 } 03131 03132 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1); 03133 }
| void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) |
Definition at line 3108 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by _macro_exec(), acf_import(), acf_odbc_read(), acf_odbc_write(), ast_add_extension2_lockopt(), config_curl(), custom_log(), cut_internal(), destroy_curl(), exec_exec(), function_eval(), function_fieldqty(), get_mapping_weight(), handle_getvariablefull(), launch_monitor_thread(), make_email_file(), manager_log(), pbx_builtin_importvar(), pbx_find_extension(), pbx_load_config(), pbx_substitute_variables(), realtime_curl(), realtime_exec(), realtime_multi_curl(), require_curl(), rotate_file(), rpt_do_lstats(), rpt_exec(), sendmail(), sendpage(), sqlite3_log(), store_curl(), substituted(), try_calling(), tryexec_exec(), and update_curl().
03109 { 03110 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count); 03111 }
| static void pbx_substitute_variables_helper_full | ( | struct ast_channel * | c, | |
| struct varshead * | headp, | |||
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) | [static] |
Definition at line 2916 of file pbx.c.
References ast_channel_alloc, ast_channel_free(), ast_copy_string(), ast_debug, ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), pbx_retrieve_variable(), substring(), var, VAR_BUF_SIZE, and ast_channel::varshead.
Referenced by pbx_substitute_variables_helper(), and pbx_substitute_variables_varshead().
02917 { 02918 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 02919 char *cp4; 02920 const char *tmp, *whereweare; 02921 int length, offset, offset2, isfunction; 02922 char *workspace = NULL; 02923 char *ltmp = NULL, *var = NULL; 02924 char *nextvar, *nextexp, *nextthing; 02925 char *vars, *vare; 02926 int pos, brackets, needsub, len; 02927 02928 *cp2 = 0; /* just in case nothing ends up there */ 02929 whereweare=tmp=cp1; 02930 while (!ast_strlen_zero(whereweare) && count) { 02931 /* Assume we're copying the whole remaining string */ 02932 pos = strlen(whereweare); 02933 nextvar = NULL; 02934 nextexp = NULL; 02935 nextthing = strchr(whereweare, '$'); 02936 if (nextthing) { 02937 switch (nextthing[1]) { 02938 case '{': 02939 nextvar = nextthing; 02940 pos = nextvar - whereweare; 02941 break; 02942 case '[': 02943 nextexp = nextthing; 02944 pos = nextexp - whereweare; 02945 break; 02946 default: 02947 pos = 1; 02948 } 02949 } 02950 02951 if (pos) { 02952 /* Can't copy more than 'count' bytes */ 02953 if (pos > count) 02954 pos = count; 02955 02956 /* Copy that many bytes */ 02957 memcpy(cp2, whereweare, pos); 02958 02959 count -= pos; 02960 cp2 += pos; 02961 whereweare += pos; 02962 *cp2 = 0; 02963 } 02964 02965 if (nextvar) { 02966 /* We have a variable. Find the start and end, and determine 02967 if we are going to have to recursively call ourselves on the 02968 contents */ 02969 vars = vare = nextvar + 2; 02970 brackets = 1; 02971 needsub = 0; 02972 02973 /* Find the end of it */ 02974 while (brackets && *vare) { 02975 if ((vare[0] == '$') && (vare[1] == '{')) { 02976 needsub++; 02977 } else if (vare[0] == '{') { 02978 brackets++; 02979 } else if (vare[0] == '}') { 02980 brackets--; 02981 } else if ((vare[0] == '$') && (vare[1] == '[')) 02982 needsub++; 02983 vare++; 02984 } 02985 if (brackets) 02986 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 02987 len = vare - vars - 1; 02988 02989 /* Skip totally over variable string */ 02990 whereweare += (len + 3); 02991 02992 if (!var) 02993 var = alloca(VAR_BUF_SIZE); 02994 02995 /* Store variable name (and truncate) */ 02996 ast_copy_string(var, vars, len + 1); 02997 02998 /* Substitute if necessary */ 02999 if (needsub) { 03000 if (!ltmp) 03001 ltmp = alloca(VAR_BUF_SIZE); 03002 03003 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 03004 vars = ltmp; 03005 } else { 03006 vars = var; 03007 } 03008 03009 if (!workspace) 03010 workspace = alloca(VAR_BUF_SIZE); 03011 03012 workspace[0] = '\0'; 03013 03014 parse_variable_name(vars, &offset, &offset2, &isfunction); 03015 if (isfunction) { 03016 /* Evaluate function */ 03017 if (c || !headp) 03018 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03019 else { 03020 struct varshead old; 03021 struct ast_channel *bogus = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars); 03022 if (bogus) { 03023 memcpy(&old, &bogus->varshead, sizeof(old)); 03024 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 03025 cp4 = ast_func_read(bogus, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03026 /* Don't deallocate the varshead that was passed in */ 03027 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 03028 ast_channel_free(bogus); 03029 } else 03030 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03031 } 03032 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03033 } else { 03034 /* Retrieve variable value */ 03035 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 03036 } 03037 if (cp4) { 03038 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 03039 03040 length = strlen(cp4); 03041 if (length > count) 03042 length = count; 03043 memcpy(cp2, cp4, length); 03044 count -= length; 03045 cp2 += length; 03046 *cp2 = 0; 03047 } 03048 } else if (nextexp) { 03049 /* We have an expression. Find the start and end, and determine 03050 if we are going to have to recursively call ourselves on the 03051 contents */ 03052 vars = vare = nextexp + 2; 03053 brackets = 1; 03054 needsub = 0; 03055 03056 /* Find the end of it */ 03057 while (brackets && *vare) { 03058 if ((vare[0] == '$') && (vare[1] == '[')) { 03059 needsub++; 03060 brackets++; 03061 vare++; 03062 } else if (vare[0] == '[') { 03063 brackets++; 03064 } else if (vare[0] == ']') { 03065 brackets--; 03066 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03067 needsub++; 03068 vare++; 03069 } 03070 vare++; 03071 } 03072 if (brackets) 03073 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03074 len = vare - vars - 1; 03075 03076 /* Skip totally over expression */ 03077 whereweare += (len + 3); 03078 03079 if (!var) 03080 var = alloca(VAR_BUF_SIZE); 03081 03082 /* Store variable name (and truncate) */ 03083 ast_copy_string(var, vars, len + 1); 03084 03085 /* Substitute if necessary */ 03086 if (needsub) { 03087 if (!ltmp) 03088 ltmp = alloca(VAR_BUF_SIZE); 03089 03090 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 03091 vars = ltmp; 03092 } else { 03093 vars = var; 03094 } 03095 03096 length = ast_expr(vars, cp2, count, c); 03097 03098 if (length) { 03099 ast_debug(1, "Expression result is '%s'\n", cp2); 03100 count -= length; 03101 cp2 += length; 03102 *cp2 = 0; 03103 } 03104 } 03105 } 03106 }
| void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) |
Definition at line 3113 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by add_user_extension(), build_user_routes(), do_say(), dundi_lookup_local(), loopback_subst(), phoneprov_callback(), pp_each_extension_exec(), and pp_each_user_exec().
03114 { 03115 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count); 03116 }
| static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 4037 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
04038 { 04039 /* Oh joyeous kernel, we're a new thread, with nothing to do but 04040 answer this channel and get it going. 04041 */ 04042 /* NOTE: 04043 The launcher of this function _MUST_ increment 'countcalls' 04044 before invoking the function; it will be decremented when the 04045 PBX has finished running on the channel 04046 */ 04047 struct ast_channel *c = data; 04048 04049 __ast_pbx_run(c, NULL); 04050 decrease_call_count(); 04051 04052 pthread_exit(NULL); 04053 04054 return NULL; 04055 }
| static void print_ext | ( | struct ast_exten * | e, | |
| char * | buf, | |||
| int | buflen | |||
| ) | [static] |
helper function to print an extension
Definition at line 5023 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().
05024 { 05025 int prio = ast_get_extension_priority(e); 05026 if (prio == PRIORITY_HINT) { 05027 snprintf(buf, buflen, "hint: %s", 05028 ast_get_extension_app(e)); 05029 } else { 05030 snprintf(buf, buflen, "%d. %s(%s)", 05031 prio, ast_get_extension_app(e), 05032 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 05033 } 05034 }
| 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 3677 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_raise_exception(), and pbx_builtin_waitexten().
03678 { 03679 ast_channel_lock(c); 03680 ast_copy_string(c->exten, exten, sizeof(c->exten)); 03681 c->priority = pri; 03682 ast_channel_unlock(c); 03683 }
| 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 5188 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::pattern_tree, dialplan_counters::total_context, and dialplan_counters::total_exten.
Referenced by handle_debug_dialplan().
05189 { 05190 struct ast_context *c = NULL; 05191 int res = 0, old_total_exten = dpc->total_exten; 05192 05193 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n"); 05194 05195 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n"); 05196 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n"); 05197 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n"); 05198 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n"); 05199 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n"); 05200 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n"); 05201 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n"); 05202 ast_rdlock_contexts(); 05203 05204 /* walk all contexts ... */ 05205 while ( (c = ast_walk_contexts(c)) ) { 05206 int context_info_printed = 0; 05207 05208 if (context && strcmp(ast_get_context_name(c), context)) 05209 continue; /* skip this one, name doesn't match */ 05210 05211 dpc->context_existence = 1; 05212 05213 if (!c->pattern_tree) 05214 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */ 05215 05216 ast_rdlock_context(c); 05217 05218 dpc->total_context++; 05219 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 05220 ast_get_context_name(c), ast_get_context_registrar(c)); 05221 context_info_printed = 1; 05222 05223 if (c->pattern_tree) 05224 { 05225 cli_match_char_tree(c->pattern_tree, " ", fd); 05226 } else { 05227 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n"); 05228 } 05229 05230 ast_unlock_context(c); 05231 05232 /* if we print something in context, make an empty line */ 05233 if (context_info_printed) 05234 ast_cli(fd, "\n"); 05235 } 05236 ast_unlock_contexts(); 05237 05238 return (dpc->total_exten == old_total_exten) ? -1 : res; 05239 }
| 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 5037 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(), buf, 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().
05038 { 05039 struct ast_context *c = NULL; 05040 int res = 0, old_total_exten = dpc->total_exten; 05041 05042 ast_rdlock_contexts(); 05043 05044 /* walk all contexts ... */ 05045 while ( (c = ast_walk_contexts(c)) ) { 05046 struct ast_exten *e; 05047 struct ast_include *i; 05048 struct ast_ignorepat *ip; 05049 char buf[256], buf2[256]; 05050 int context_info_printed = 0; 05051 05052 if (context && strcmp(ast_get_context_name(c), context)) 05053 continue; /* skip this one, name doesn't match */ 05054 05055 dpc->context_existence = 1; 05056 05057 ast_rdlock_context(c); 05058 05059 /* are we looking for exten too? if yes, we print context 05060 * only if we find our extension. 05061 * Otherwise print context even if empty ? 05062 * XXX i am not sure how the rinclude is handled. 05063 * I think it ought to go inside. 05064 */ 05065 if (!exten) { 05066 dpc->total_context++; 05067 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 05068 ast_get_context_name(c), ast_get_context_registrar(c)); 05069 context_info_printed = 1; 05070 } 05071 05072 /* walk extensions ... */ 05073 e = NULL; 05074 while ( (e = ast_walk_context_extensions(c, e)) ) { 05075 struct ast_exten *p; 05076 05077 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 05078 continue; /* skip, extension match failed */ 05079 05080 dpc->extension_existence = 1; 05081 05082 /* may we print context info? */ 05083 if (!context_info_printed) { 05084 dpc->total_context++; 05085 if (rinclude) { /* TODO Print more info about rinclude */ 05086 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 05087 ast_get_context_name(c), ast_get_context_registrar(c)); 05088 } else { 05089 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 05090 ast_get_context_name(c), ast_get_context_registrar(c)); 05091 } 05092 context_info_printed = 1; 05093 } 05094 dpc->total_prio++; 05095 05096 /* write extension name and first peer */ 05097 if (e->matchcid) 05098 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch); 05099 else 05100 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 05101 05102 print_ext(e, buf2, sizeof(buf2)); 05103 05104 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 05105 ast_get_extension_registrar(e)); 05106 05107 dpc->total_exten++; 05108 /* walk next extension peers */ 05109 p = e; /* skip the first one, we already got it */ 05110 while ( (p = ast_walk_extension_priorities(e, p)) ) { 05111 const char *el = ast_get_extension_label(p); 05112 dpc->total_prio++; 05113 if (el) 05114 snprintf(buf, sizeof(buf), " [%s]", el); 05115 else 05116 buf[0] = '\0'; 05117 print_ext(p, buf2, sizeof(buf2)); 05118 05119 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 05120 ast_get_extension_registrar(p)); 05121 } 05122 } 05123 05124 /* walk included and write info ... */ 05125 i = NULL; 05126 while ( (i = ast_walk_context_includes(c, i)) ) { 05127 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 05128 if (exten) { 05129 /* Check all includes for the requested extension */ 05130 if (includecount >= AST_PBX_MAX_STACK) { 05131 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n"); 05132 } else { 05133 int dupe = 0; 05134 int x; 05135 for (x = 0; x < includecount; x++) { 05136 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 05137 dupe++; 05138 break; 05139 } 05140 } 05141 if (!dupe) { 05142 includes[includecount] = ast_get_include_name(i); 05143 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 05144 } else { 05145 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 05146 } 05147 } 05148 } else { 05149 ast_cli(fd, " Include => %-45s [%s]\n", 05150 buf, ast_get_include_registrar(i)); 05151 } 05152 } 05153 05154 /* walk ignore patterns and write info ... */ 05155 ip = NULL; 05156 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 05157 const char *ipname = ast_get_ignorepat_name(ip); 05158 char ignorepat[AST_MAX_EXTENSION]; 05159 snprintf(buf, sizeof(buf), "'%s'", ipname); 05160 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 05161 if (!exten || ast_extension_match(ignorepat, exten)) { 05162 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 05163 buf, ast_get_ignorepat_registrar(ip)); 05164 } 05165 } 05166 if (!rinclude) { 05167 struct ast_sw *sw = NULL; 05168 while ( (sw = ast_walk_context_switches(c, sw)) ) { 05169 snprintf(buf, sizeof(buf), "'%s/%s'", 05170 ast_get_switch_name(sw), 05171 ast_get_switch_data(sw)); 05172 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 05173 buf, ast_get_switch_registrar(sw)); 05174 } 05175 } 05176 05177 ast_unlock_context(c); 05178 05179 /* if we print something in context, make an empty line */ 05180 if (context_info_printed) 05181 ast_cli(fd, "\n"); 05182 } 05183 ast_unlock_contexts(); 05184 05185 return (dpc->total_exten == old_total_exten) ? -1 : res; 05186 }
| 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 2425 of file pbx.c.
References ast_copy_string().
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
02426 { 02427 char *ret = workspace; 02428 int lr; /* length of the input string after the copy */ 02429 02430 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 02431 02432 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 02433 02434 /* Quick check if no need to do anything */ 02435 if (offset == 0 && length >= lr) /* take the whole string */ 02436 return ret; 02437 02438 if (offset < 0) { /* translate negative offset into positive ones */ 02439 offset = lr + offset; 02440 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 02441 offset = 0; 02442 } 02443 02444 /* too large offset result in empty string so we know what to return */ 02445 if (offset >= lr) 02446 return ret + lr; /* the final '\0' */ 02447 02448 ret += offset; /* move to the start position */ 02449 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 02450 ret[length] = '\0'; 02451 else if (length < 0) { 02452 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 02453 ret[lr + length - offset] = '\0'; 02454 else 02455 ret[0] = '\0'; 02456 } 02457 02458 return ret; 02459 }
| static struct ast_exten* trie_find_next_match | ( | struct match_char * | node | ) | [static, read] |
Definition at line 1183 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().
01184 { 01185 struct match_char *m3; 01186 struct match_char *m4; 01187 struct ast_exten *e3; 01188 01189 if (node && node->x[0] == '.' && !node->x[1]) /* dot and ! will ALWAYS be next match in a matchmore */ 01190 return node->exten; 01191 01192 if (node && node->x[0] == '!' && !node->x[1]) 01193 return node->exten; 01194 01195 if (!node || !node->next_char) 01196 return NULL; 01197 01198 m3 = node->next_char; 01199 01200 if (m3->exten) 01201 return m3->exten; 01202 for(m4=m3->alt_char; m4; m4 = m4->alt_char) { 01203 if (m4->exten) 01204 return m4->exten; 01205 } 01206 for(m4=m3; m4; m4 = m4->alt_char) { 01207 e3 = trie_find_next_match(m3); 01208 if (e3) 01209 return e3; 01210 } 01211 return NULL; 01212 }
| static void unreference_cached_app | ( | struct ast_app * | app | ) | [static] |
Definition at line 5833 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().
05834 { 05835 struct ast_context *context = NULL; 05836 struct ast_exten *eroot = NULL, *e = NULL; 05837 05838 ast_rdlock_contexts(); 05839 while ((context = ast_walk_contexts(context))) { 05840 while ((eroot = ast_walk_context_extensions(context, eroot))) { 05841 while ((e = ast_walk_extension_priorities(eroot, e))) { 05842 if (e->cached_app == app) 05843 e->cached_app = NULL; 05844 } 05845 } 05846 } 05847 ast_unlock_contexts(); 05848 05849 return; 05850 }
| 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 1090 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().
01091 { 01092 /* if this extension is marked as deleted, then skip this -- if it never shows 01093 on the scoreboard, it will never be found, nor will halt the traversal. */ 01094 if (deleted) 01095 return; 01096 board->total_specificity = spec; 01097 board->total_length = length; 01098 board->exten = exten; 01099 board->last_char = last; 01100 board->node = node; 01101 #ifdef NEED_DEBUG_HERE 01102 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec); 01103 #endif 01104 }
| static void wait_for_hangup | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 7864 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().
07865 { 07866 int res; 07867 struct ast_frame *f; 07868 double waitsec; 07869 int waittime; 07870 07871 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0)) 07872 waitsec = -1; 07873 if (waitsec > -1) { 07874 waittime = waitsec * 1000.0; 07875 ast_safe_sleep(chan, waittime); 07876 } else do { 07877 res = ast_waitfor(chan, -1); 07878 if (res < 0) 07879 return; 07880 f = ast_read(chan); 07881 if (f) 07882 ast_frfree(f); 07883 } while(f); 07884 }
int autofallthrough = 1 [static] |
struct pbx_builtin builtins[] [static] |
Declaration of builtin applications.
Referenced by load_pbx().
struct ast_cli_entry cli_set_chanvar_deprecated = AST_CLI_DEFINE(handle_set_chanvar_deprecated, "Set a channel variable.") [static] |
struct ast_cli_entry cli_set_global_deprecated = AST_CLI_DEFINE(handle_set_global_deprecated, "Set global dialplan variable.") [static] |
struct ast_cli_entry cli_show_globals_deprecated = AST_CLI_DEFINE(handle_show_globals_deprecated, "Show global dialplan variables.") [static] |
int conlock_wrlock_version = 0 [static] |
Definition at line 8752 of file pbx.c.
Referenced by ast_wrlock_contexts(), and ast_wrlock_contexts_version().
struct ast_context* contexts [static] |
struct ast_hashtab* contexts_table = NULL [static] |
int countcalls [static] |
char* days[] [static] |
Definition at line 6381 of file pbx.c.
Referenced by ast_build_timing().
struct ast_event_sub* device_state_sub [static] |
struct ast_taskprocessor* device_state_tps [static] |
struct ast_custom_function exception_function [static] |
Definition at line 2648 of file pbx.c.
Referenced by load_pbx().
struct ast_datastore_info exception_store_info [static] |
{
.type = "EXCEPTION",
.destroy = exception_store_free,
}
Definition at line 2590 of file pbx.c.
Referenced by acf_exception_read(), and pbx_builtin_raise_exception().
int extenpatternmatchnew = 0 [static] |
struct cfextension_states extension_states[] [static] |
Referenced by ast_extension_state2str().
struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE [static] |
char mandescr_show_dialplan[] [static] |
Definition at line 5563 of file pbx.c.
Referenced by load_pbx().
char* months[] [static] |
Definition at line 6393 of file pbx.c.
Referenced by ast_build_timing().
char* overrideswitch = NULL [static] |
Definition at line 428 of file pbx.c.
Referenced by handle_cli_dialplan_save().
struct ast_cli_entry pbx_cli[] [static] |
Definition at line 5812 of file pbx.c.
Referenced by load_pbx().
int totalcalls [static] |
Definition at line 435 of file pbx.c.
Referenced by timing_read().
1.6.1