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) |
| 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 2035 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
| #define STATUS_NO_EXTENSION 2 |
Definition at line 2036 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
| #define STATUS_NO_LABEL 4 |
Definition at line 2038 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
| #define STATUS_NO_PRIORITY 3 |
Definition at line 2037 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
| #define STATUS_SUCCESS 5 |
Definition at line 2039 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 7700 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().
07701 { 07702 struct ast_context *tmp, *tmpl=NULL; 07703 struct ast_exten *exten_item, *prio_item; 07704 07705 for (tmp = list; tmp; ) { 07706 struct ast_context *next = NULL; /* next starting point */ 07707 /* The following code used to skip forward to the next 07708 context with matching registrar, but this didn't 07709 make sense; individual priorities registrar'd to 07710 the matching registrar could occur in any context! */ 07711 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar); 07712 if (con) { 07713 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */ 07714 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar); 07715 if ( !strcasecmp(tmp->name, con->name) ) { 07716 break; /* found it */ 07717 } 07718 } 07719 } 07720 07721 if (!tmp) /* not found, we are done */ 07722 break; 07723 ast_wrlock_context(tmp); 07724 07725 if (registrar) { 07726 /* then search thru and remove any extens that match registrar. */ 07727 struct ast_hashtab_iter *exten_iter; 07728 struct ast_hashtab_iter *prio_iter; 07729 struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL; 07730 struct ast_include *i, *pi = NULL, *ni = NULL; 07731 struct ast_sw *sw = NULL; 07732 07733 /* remove any ignorepats whose registrar matches */ 07734 for (ip = tmp->ignorepats; ip; ip = ipn) { 07735 ipn = ip->next; 07736 if (!strcmp(ip->registrar, registrar)) { 07737 if (ipl) { 07738 ipl->next = ip->next; 07739 ast_free(ip); 07740 continue; /* don't change ipl */ 07741 } else { 07742 tmp->ignorepats = ip->next; 07743 ast_free(ip); 07744 continue; /* don't change ipl */ 07745 } 07746 } 07747 ipl = ip; 07748 } 07749 /* remove any includes whose registrar matches */ 07750 for (i = tmp->includes; i; i = ni) { 07751 ni = i->next; 07752 if (strcmp(i->registrar, registrar) == 0) { 07753 /* remove from list */ 07754 if (pi) { 07755 pi->next = i->next; 07756 /* free include */ 07757 ast_free(i); 07758 continue; /* don't change pi */ 07759 } else { 07760 tmp->includes = i->next; 07761 /* free include */ 07762 ast_free(i); 07763 continue; /* don't change pi */ 07764 } 07765 } 07766 pi = i; 07767 } 07768 /* remove any switches whose registrar matches */ 07769 AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) { 07770 if (strcmp(sw->registrar,registrar) == 0) { 07771 AST_LIST_REMOVE_CURRENT(list); 07772 ast_free(sw); 07773 } 07774 } 07775 AST_LIST_TRAVERSE_SAFE_END; 07776 07777 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */ 07778 exten_iter = ast_hashtab_start_traversal(tmp->root_table); 07779 while ((exten_item=ast_hashtab_next(exten_iter))) { 07780 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 07781 while ((prio_item=ast_hashtab_next(prio_iter))) { 07782 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) { 07783 continue; 07784 } 07785 ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n", 07786 tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL); 07787 /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */ 07788 ast_context_remove_extension_callerid2(tmp, prio_item->exten, prio_item->priority, prio_item->cidmatch, 1, NULL, 1); 07789 } 07790 ast_hashtab_end_traversal(prio_iter); 07791 } 07792 ast_hashtab_end_traversal(exten_iter); 07793 } 07794 07795 /* delete the context if it's registrar matches, is empty, has refcount of 1, */ 07796 /* it's not empty, if it has includes, ignorepats, or switches that are registered from 07797 another registrar. It's not empty if there are any extensions */ 07798 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) { 07799 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 07800 ast_hashtab_remove_this_object(contexttab, tmp); 07801 07802 next = tmp->next; 07803 if (tmpl) 07804 tmpl->next = next; 07805 else 07806 contexts = next; 07807 /* Okay, now we're safe to let it go -- in a sense, we were 07808 ready to let it go as soon as we locked it. */ 07809 ast_unlock_context(tmp); 07810 __ast_internal_context_destroy(tmp); 07811 } else { 07812 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar, 07813 tmp->refcount, tmp->root); 07814 ast_unlock_context(tmp); 07815 next = tmp->next; 07816 tmpl = tmp; 07817 } 07818 } else if (con) { 07819 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar); 07820 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 07821 ast_hashtab_remove_this_object(contexttab, tmp); 07822 07823 next = tmp->next; 07824 if (tmpl) 07825 tmpl->next = next; 07826 else 07827 contexts = next; 07828 /* Okay, now we're safe to let it go -- in a sense, we were 07829 ready to let it go as soon as we locked it. */ 07830 ast_unlock_context(tmp); 07831 __ast_internal_context_destroy(tmp); 07832 } 07833 07834 /* if we have a specific match, we are done, otherwise continue */ 07835 tmp = con ? NULL : next; 07836 } 07837 }
| int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
| struct ast_module * | mod | |||
| ) |
Register a custom function.
Definition at line 2795 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().
02796 { 02797 struct ast_custom_function *cur; 02798 char tmps[80]; 02799 02800 if (!acf) 02801 return -1; 02802 02803 acf->mod = mod; 02804 02805 AST_RWLIST_WRLOCK(&acf_root); 02806 02807 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 02808 if (!strcmp(acf->name, cur->name)) { 02809 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 02810 AST_RWLIST_UNLOCK(&acf_root); 02811 return -1; 02812 } 02813 } 02814 02815 /* Store in alphabetical order */ 02816 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 02817 if (strcasecmp(acf->name, cur->name) < 0) { 02818 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 02819 break; 02820 } 02821 } 02822 AST_RWLIST_TRAVERSE_SAFE_END; 02823 if (!cur) 02824 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 02825 02826 AST_RWLIST_UNLOCK(&acf_root); 02827 02828 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 02829 02830 return 0; 02831 }
| static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| int | async | |||
| ) | [static] |
Definition at line 8935 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().
08936 { 08937 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 08938 08939 if (!chan) 08940 return -2; 08941 08942 if (context == NULL) 08943 context = chan->context; 08944 if (exten == NULL) 08945 exten = chan->exten; 08946 08947 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 08948 if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num)) 08949 return goto_func(chan, context, exten, priority); 08950 else 08951 return -3; 08952 }
| static void __ast_internal_context_destroy | ( | struct ast_context * | con | ) | [static] |
Definition at line 7653 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().
07654 { 07655 struct ast_include *tmpi; 07656 struct ast_sw *sw; 07657 struct ast_exten *e, *el, *en; 07658 struct ast_ignorepat *ipi; 07659 struct ast_context *tmp = con; 07660 07661 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 07662 struct ast_include *tmpil = tmpi; 07663 tmpi = tmpi->next; 07664 ast_free(tmpil); 07665 } 07666 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 07667 struct ast_ignorepat *ipl = ipi; 07668 ipi = ipi->next; 07669 ast_free(ipl); 07670 } 07671 if (tmp->registrar) 07672 ast_free(tmp->registrar); 07673 07674 /* destroy the hash tabs */ 07675 if (tmp->root_table) { 07676 ast_hashtab_destroy(tmp->root_table, 0); 07677 } 07678 /* and destroy the pattern tree */ 07679 if (tmp->pattern_tree) 07680 destroy_pattern_tree(tmp->pattern_tree); 07681 07682 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 07683 ast_free(sw); 07684 for (e = tmp->root; e;) { 07685 for (en = e->peer; en;) { 07686 el = en; 07687 en = en->peer; 07688 destroy_exten(el); 07689 } 07690 el = e; 07691 e = e->next; 07692 destroy_exten(el); 07693 } 07694 tmp->root = NULL; 07695 ast_rwlock_destroy(&tmp->lock); 07696 ast_free(tmp); 07697 }
| static enum ast_pbx_result __ast_pbx_run | ( | struct ast_channel * | c, | |
| struct ast_pbx_args * | args | |||
| ) | [static] |
Definition at line 3699 of file pbx.c.
References ast_channel::_softhangup, ast_calloc, AST_CAUSE_NORMAL_CLEARING, 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_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, ast_channel::hangupcause, 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().
03701 { 03702 int found = 0; /* set if we find at least one match */ 03703 int res = 0; 03704 int autoloopflag; 03705 int error = 0; /* set an error conditions */ 03706 03707 /* A little initial setup here */ 03708 if (c->pbx) { 03709 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 03710 /* XXX and now what ? */ 03711 ast_free(c->pbx); 03712 } 03713 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 03714 return -1; 03715 /* Set reasonable defaults */ 03716 c->pbx->rtimeoutms = 10000; 03717 c->pbx->dtimeoutms = 5000; 03718 03719 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 03720 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 03721 03722 /* Start by trying whatever the channel is set to */ 03723 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 03724 /* If not successful fall back to 's' */ 03725 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); 03726 /* XXX the original code used the existing priority in the call to 03727 * ast_exists_extension(), and reset it to 1 afterwards. 03728 * I believe the correct thing is to set it to 1 immediately. 03729 */ 03730 set_ext_pri(c, "s", 1); 03731 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 03732 /* JK02: And finally back to default if everything else failed */ 03733 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); 03734 ast_copy_string(c->context, "default", sizeof(c->context)); 03735 } 03736 } 03737 for (;;) { 03738 char dst_exten[256]; /* buffer to accumulate digits */ 03739 int pos = 0; /* XXX should check bounds */ 03740 int digit = 0; 03741 int invalid = 0; 03742 int timeout = 0; 03743 03744 /* loop on priorities in this context/exten */ 03745 while ( !(res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found,1))) { 03746 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) { 03747 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */ 03748 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 03749 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 03750 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 03751 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03752 pbx_builtin_raise_exception(c, "ABSOLUTETIMEOUT"); 03753 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 03754 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 03755 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 03756 } else if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 03757 c->_softhangup = 0; 03758 continue; 03759 } else if (ast_check_hangup(c)) { 03760 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n", 03761 c->exten, c->priority); 03762 error = 1; 03763 break; 03764 } 03765 c->priority++; 03766 } /* end while - from here on we can use 'break' to go out */ 03767 if (found && res) { 03768 /* Something bad happened, or a hangup has been requested. */ 03769 if (strchr("0123456789ABCDEF*#", res)) { 03770 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res); 03771 pos = 0; 03772 dst_exten[pos++] = digit = res; 03773 dst_exten[pos] = '\0'; 03774 } else if (res == AST_PBX_INCOMPLETE) { 03775 ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 03776 ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 03777 03778 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */ 03779 if (!ast_matchmore_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 03780 invalid = 1; 03781 } else { 03782 ast_copy_string(dst_exten, c->exten, sizeof(dst_exten)); 03783 digit = 1; 03784 pos = strlen(dst_exten); 03785 } 03786 } else { 03787 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 03788 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 03789 03790 if ((res == AST_PBX_ERROR) && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03791 /* if we are already on the 'e' exten, don't jump to it again */ 03792 if (!strcmp(c->exten, "e")) { 03793 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); 03794 error = 1; 03795 } else { 03796 pbx_builtin_raise_exception(c, "ERROR"); 03797 continue; 03798 } 03799 } 03800 03801 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 03802 c->_softhangup = 0; 03803 continue; 03804 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) { 03805 set_ext_pri(c, "T", 1); 03806 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 03807 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 03808 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 03809 continue; 03810 } else { 03811 if (c->cdr) 03812 ast_cdr_update(c); 03813 error = 1; 03814 break; 03815 } 03816 } 03817 } 03818 if (error) 03819 break; 03820 03821 /*!\note 03822 * We get here on a failure of some kind: non-existing extension or 03823 * hangup. We have options, here. We can either catch the failure 03824 * and continue, or we can drop out entirely. */ 03825 03826 if (invalid || !ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) { 03827 /*!\note 03828 * If there is no match at priority 1, it is not a valid extension anymore. 03829 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if 03830 * neither exist. 03831 */ 03832 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 03833 ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 03834 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 03835 set_ext_pri(c, "i", 1); 03836 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03837 pbx_builtin_raise_exception(c, "INVALID"); 03838 } else { 03839 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 03840 c->name, c->exten, c->context); 03841 error = 1; /* we know what to do with it */ 03842 break; 03843 } 03844 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 03845 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 03846 c->_softhangup = 0; 03847 } else { /* keypress received, get more digits for a full extension */ 03848 int waittime = 0; 03849 if (digit) 03850 waittime = c->pbx->dtimeoutms; 03851 else if (!autofallthrough) 03852 waittime = c->pbx->rtimeoutms; 03853 if (!waittime) { 03854 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 03855 if (!status) 03856 status = "UNKNOWN"; 03857 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 03858 if (!strcasecmp(status, "CONGESTION")) 03859 res = pbx_builtin_congestion(c, "10"); 03860 else if (!strcasecmp(status, "CHANUNAVAIL")) 03861 res = pbx_builtin_congestion(c, "10"); 03862 else if (!strcasecmp(status, "BUSY")) 03863 res = pbx_builtin_busy(c, "10"); 03864 error = 1; /* XXX disable message */ 03865 break; /* exit from the 'for' loop */ 03866 } 03867 03868 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 03869 break; 03870 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos])) 03871 timeout = 1; 03872 if (!timeout && ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */ 03873 set_ext_pri(c, dst_exten, 1); 03874 else { 03875 /* No such extension */ 03876 if (!timeout && !ast_strlen_zero(dst_exten)) { 03877 /* An invalid extension */ 03878 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 03879 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 03880 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 03881 set_ext_pri(c, "i", 1); 03882 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03883 pbx_builtin_raise_exception(c, "INVALID"); 03884 } else { 03885 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context); 03886 found = 1; /* XXX disable message */ 03887 break; 03888 } 03889 } else { 03890 /* A simple timeout */ 03891 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) { 03892 ast_verb(3, "Timeout on %s\n", c->name); 03893 set_ext_pri(c, "t", 1); 03894 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03895 pbx_builtin_raise_exception(c, "RESPONSETIMEOUT"); 03896 } else { 03897 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); 03898 found = 1; /* XXX disable message */ 03899 break; 03900 } 03901 } 03902 } 03903 if (c->cdr) { 03904 ast_verb(2, "CDR updated on %s\n",c->name); 03905 ast_cdr_update(c); 03906 } 03907 } 03908 } 03909 03910 if (!found && !error) { 03911 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 03912 } 03913 03914 if (!args || !args->no_hangup_chan) { 03915 ast_softhangup(c, c->hangupcause ? c->hangupcause : AST_CAUSE_NORMAL_CLEARING); 03916 } 03917 03918 if ((!args || !args->no_hangup_chan) && 03919 !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) && 03920 ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) { 03921 set_ext_pri(c, "h", 1); 03922 if (c->cdr && ast_opt_end_cdr_before_h_exten) { 03923 ast_cdr_end(c->cdr); 03924 } 03925 while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found, 1)) == 0) { 03926 c->priority++; 03927 } 03928 if (found && res) { 03929 /* Something bad happened, or a hangup has been requested. */ 03930 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 03931 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 03932 } 03933 } 03934 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 03935 ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */ 03936 pbx_destroy(c->pbx); 03937 c->pbx = NULL; 03938 03939 if (!args || !args->no_hangup_chan) { 03940 ast_hangup(c); 03941 } 03942 03943 return 0; 03944 }
| static int _extension_match_core | ( | const char * | pattern, | |
| const char * | data, | |||
| enum ext_match_t | mode | |||
| ) | [static] |
Definition at line 1811 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, LOG_NOTICE, and LOG_WARNING.
Referenced by extension_match_core().
01812 { 01813 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 01814 01815 #ifdef NEED_DEBUG_HERE 01816 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode); 01817 #endif 01818 01819 if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */ 01820 #ifdef NEED_DEBUG_HERE 01821 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n"); 01822 #endif 01823 return 1; 01824 } 01825 01826 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 01827 int ld = strlen(data), lp = strlen(pattern); 01828 01829 if (lp < ld) { /* pattern too short, cannot match */ 01830 #ifdef NEED_DEBUG_HERE 01831 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n"); 01832 #endif 01833 return 0; 01834 } 01835 /* depending on the mode, accept full or partial match or both */ 01836 if (mode == E_MATCH) { 01837 #ifdef NEED_DEBUG_HERE 01838 ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data); 01839 #endif 01840 return !strcmp(pattern, data); /* 1 on match, 0 on fail */ 01841 } 01842 if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */ 01843 #ifdef NEED_DEBUG_HERE 01844 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld); 01845 #endif 01846 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 01847 } else { 01848 #ifdef NEED_DEBUG_HERE 01849 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data); 01850 #endif 01851 return 0; 01852 } 01853 } 01854 pattern++; /* skip leading _ */ 01855 /* 01856 * XXX below we stop at '/' which is a separator for the CID info. However we should 01857 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 01858 */ 01859 while (*data && *pattern && *pattern != '/') { 01860 const char *end; 01861 01862 if (*data == '-') { /* skip '-' in data (just a separator) */ 01863 data++; 01864 continue; 01865 } 01866 switch (toupper(*pattern)) { 01867 case '[': /* a range */ 01868 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */ 01869 if (end == NULL) { 01870 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 01871 return 0; /* unconditional failure */ 01872 } 01873 for (pattern++; pattern != end; pattern++) { 01874 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 01875 if (*data >= pattern[0] && *data <= pattern[2]) 01876 break; /* match found */ 01877 else { 01878 pattern += 2; /* skip a total of 3 chars */ 01879 continue; 01880 } 01881 } else if (*data == pattern[0]) 01882 break; /* match found */ 01883 } 01884 if (pattern == end) { 01885 #ifdef NEED_DEBUG_HERE 01886 ast_log(LOG_NOTICE,"return (0) when pattern==end\n"); 01887 #endif 01888 return 0; 01889 } 01890 pattern = end; /* skip and continue */ 01891 break; 01892 case 'N': 01893 if (*data < '2' || *data > '9') { 01894 #ifdef NEED_DEBUG_HERE 01895 ast_log(LOG_NOTICE,"return (0) N is matched\n"); 01896 #endif 01897 return 0; 01898 } 01899 break; 01900 case 'X': 01901 if (*data < '0' || *data > '9') { 01902 #ifdef NEED_DEBUG_HERE 01903 ast_log(LOG_NOTICE,"return (0) X is matched\n"); 01904 #endif 01905 return 0; 01906 } 01907 break; 01908 case 'Z': 01909 if (*data < '1' || *data > '9') { 01910 #ifdef NEED_DEBUG_HERE 01911 ast_log(LOG_NOTICE,"return (0) Z is matched\n"); 01912 #endif 01913 return 0; 01914 } 01915 break; 01916 case '.': /* Must match, even with more digits */ 01917 #ifdef NEED_DEBUG_HERE 01918 ast_log(LOG_NOTICE,"return (1) when '.' is matched\n"); 01919 #endif 01920 return 1; 01921 case '!': /* Early match */ 01922 #ifdef NEED_DEBUG_HERE 01923 ast_log(LOG_NOTICE,"return (2) when '!' is matched\n"); 01924 #endif 01925 return 2; 01926 case ' ': 01927 case '-': /* Ignore these in patterns */ 01928 data--; /* compensate the final data++ */ 01929 break; 01930 default: 01931 if (*data != *pattern) { 01932 #ifdef NEED_DEBUG_HERE 01933 ast_log(LOG_NOTICE,"return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern); 01934 #endif 01935 return 0; 01936 } 01937 01938 } 01939 data++; 01940 pattern++; 01941 } 01942 if (*data) /* data longer than pattern, no match */ { 01943 #ifdef NEED_DEBUG_HERE 01944 ast_log(LOG_NOTICE,"return (0) when data longer than pattern\n"); 01945 #endif 01946 return 0; 01947 } 01948 01949 /* 01950 * match so far, but ran off the end of the data. 01951 * Depending on what is next, determine match or not. 01952 */ 01953 if (*pattern == '\0' || *pattern == '/') { /* exact match */ 01954 #ifdef NEED_DEBUG_HERE 01955 ast_log(LOG_NOTICE,"at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1); 01956 #endif 01957 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 01958 } else if (*pattern == '!') { /* early match */ 01959 #ifdef NEED_DEBUG_HERE 01960 ast_log(LOG_NOTICE,"at end, return (2) when '!' is matched\n"); 01961 #endif 01962 return 2; 01963 } else { /* partial match */ 01964 #ifdef NEED_DEBUG_HERE 01965 ast_log(LOG_NOTICE,"at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1); 01966 #endif 01967 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 01968 } 01969 }
| static int acf_exception_read | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | buflen | |||
| ) | [static] |
Definition at line 2612 of file pbx.c.
References ast_channel_datastore_find(), ast_copy_string(), ast_datastore::data, exception_store_info, and pbx_exception::priority.
02613 { 02614 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 02615 struct pbx_exception *exception = NULL; 02616 if (!ds || !ds->data) 02617 return -1; 02618 exception = ds->data; 02619 if (!strcasecmp(data, "REASON")) 02620 ast_copy_string(buf, exception->reason, buflen); 02621 else if (!strcasecmp(data, "CONTEXT")) 02622 ast_copy_string(buf, exception->context, buflen); 02623 else if (!strncasecmp(data, "EXTEN", 5)) 02624 ast_copy_string(buf, exception->exten, buflen); 02625 else if (!strcasecmp(data, "PRIORITY")) 02626 snprintf(buf, buflen, "%d", exception->priority); 02627 else 02628 return -1; 02629 return 0; 02630 }
| 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 6866 of file pbx.c.
References add_pri_lockopt().
Referenced by ast_add_extension2_lockopt().
06868 { 06869 return add_pri_lockopt(con, tmp, el, e, replace, 1); 06870 }
| 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 6877 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().
06879 { 06880 struct ast_exten *ep; 06881 struct ast_exten *eh=e; 06882 06883 for (ep = NULL; e ; ep = e, e = e->peer) { 06884 if (e->priority >= tmp->priority) 06885 break; 06886 } 06887 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 06888 ast_hashtab_insert_safe(eh->peer_table, tmp); 06889 06890 if (tmp->label) { 06891 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 06892 } 06893 ep->peer = tmp; 06894 return 0; /* success */ 06895 } 06896 if (e->priority == tmp->priority) { 06897 /* Can't have something exactly the same. Is this a 06898 replacement? If so, replace, otherwise, bonk. */ 06899 if (!replace) { 06900 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 06901 if (tmp->datad) { 06902 tmp->datad(tmp->data); 06903 /* if you free this, null it out */ 06904 tmp->data = NULL; 06905 } 06906 06907 ast_free(tmp); 06908 return -1; 06909 } 06910 /* we are replacing e, so copy the link fields and then update 06911 * whoever pointed to e to point to us 06912 */ 06913 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 06914 tmp->peer = e->peer; /* always meaningful */ 06915 if (ep) { /* We're in the peer list, just insert ourselves */ 06916 ast_hashtab_remove_object_via_lookup(eh->peer_table,e); 06917 06918 if (e->label) { 06919 ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e); 06920 } 06921 06922 ast_hashtab_insert_safe(eh->peer_table,tmp); 06923 if (tmp->label) { 06924 ast_hashtab_insert_safe(eh->peer_label_table,tmp); 06925 } 06926 06927 ep->peer = tmp; 06928 } else if (el) { /* We're the first extension. Take over e's functions */ 06929 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 06930 tmp->peer_table = e->peer_table; 06931 tmp->peer_label_table = e->peer_label_table; 06932 ast_hashtab_remove_object_via_lookup(tmp->peer_table,e); 06933 ast_hashtab_insert_safe(tmp->peer_table,tmp); 06934 if (e->label) { 06935 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 06936 } 06937 if (tmp->label) { 06938 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 06939 } 06940 06941 ast_hashtab_remove_object_via_lookup(con->root_table, e); 06942 ast_hashtab_insert_safe(con->root_table, tmp); 06943 el->next = tmp; 06944 /* The pattern trie points to this exten; replace the pointer, 06945 and all will be well */ 06946 if (x) { /* if the trie isn't formed yet, don't sweat this */ 06947 if (x->exten) { /* this test for safety purposes */ 06948 x->exten = tmp; /* replace what would become a bad pointer */ 06949 } else { 06950 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 06951 } 06952 } 06953 } else { /* We're the very first extension. */ 06954 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 06955 ast_hashtab_remove_object_via_lookup(con->root_table, e); 06956 ast_hashtab_insert_safe(con->root_table, tmp); 06957 tmp->peer_table = e->peer_table; 06958 tmp->peer_label_table = e->peer_label_table; 06959 ast_hashtab_remove_object_via_lookup(tmp->peer_table, e); 06960 ast_hashtab_insert_safe(tmp->peer_table, tmp); 06961 if (e->label) { 06962 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 06963 } 06964 if (tmp->label) { 06965 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 06966 } 06967 06968 ast_hashtab_remove_object_via_lookup(con->root_table, e); 06969 ast_hashtab_insert_safe(con->root_table, tmp); 06970 con->root = tmp; 06971 /* The pattern trie points to this exten; replace the pointer, 06972 and all will be well */ 06973 if (x) { /* if the trie isn't formed yet; no problem */ 06974 if (x->exten) { /* this test for safety purposes */ 06975 x->exten = tmp; /* replace what would become a bad pointer */ 06976 } else { 06977 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 06978 } 06979 } 06980 } 06981 if (tmp->priority == PRIORITY_HINT) 06982 ast_change_hint(e,tmp); 06983 /* Destroy the old one */ 06984 if (e->datad) 06985 e->datad(e->data); 06986 ast_free(e); 06987 } else { /* Slip ourselves in just before e */ 06988 tmp->peer = e; 06989 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 06990 if (ep) { /* Easy enough, we're just in the peer list */ 06991 if (tmp->label) { 06992 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 06993 } 06994 ast_hashtab_insert_safe(eh->peer_table, tmp); 06995 ep->peer = tmp; 06996 } else { /* we are the first in some peer list, so link in the ext list */ 06997 tmp->peer_table = e->peer_table; 06998 tmp->peer_label_table = e->peer_label_table; 06999 e->peer_table = 0; 07000 e->peer_label_table = 0; 07001 ast_hashtab_insert_safe(tmp->peer_table, tmp); 07002 if (tmp->label) { 07003 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 07004 } 07005 ast_hashtab_remove_object_via_lookup(con->root_table, e); 07006 ast_hashtab_insert_safe(con->root_table, tmp); 07007 if (el) 07008 el->next = tmp; /* in the middle... */ 07009 else 07010 con->root = tmp; /* ... or at the head */ 07011 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 07012 } 07013 /* And immediately return success. */ 07014 if (tmp->priority == PRIORITY_HINT) { 07015 if (lockhints) { 07016 ast_add_hint(tmp); 07017 } else { 07018 ast_add_hint_nolock(tmp); 07019 } 07020 } 07021 } 07022 return 0; 07023 }
| 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 4082 of file pbx.c.
Referenced by handle_chanlist(), handle_showcalls(), and sysinfo_helper().
04083 { 04084 return countcalls; 04085 }
| 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 6732 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().
06735 { 06736 int ret = -1; 06737 struct ast_context *c = find_context_locked(context); 06738 06739 if (c) { 06740 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 06741 application, data, datad, registrar); 06742 ast_unlock_contexts(); 06743 } 06744 06745 return ret; 06746 }
| 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 7050 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().
07054 { 07055 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1); 07056 }
| 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 7063 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().
07067 { 07068 /* 07069 * Sort extensions (or patterns) according to the rules indicated above. 07070 * These are implemented by the function ext_cmp()). 07071 * All priorities for the same ext/pattern/cid are kept in a list, 07072 * using the 'peer' field as a link field.. 07073 */ 07074 struct ast_exten *tmp, *tmp2, *e, *el = NULL; 07075 int res; 07076 int length; 07077 char *p; 07078 char expand_buf[VAR_BUF_SIZE]; 07079 struct ast_exten dummy_exten = {0}; 07080 char dummy_name[1024]; 07081 07082 if (ast_strlen_zero(extension)) { 07083 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", 07084 con->name); 07085 return -1; 07086 } 07087 07088 /* If we are adding a hint evalulate in variables and global variables */ 07089 if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) { 07090 struct ast_channel c = {0, }; 07091 07092 ast_copy_string(c.exten, extension, sizeof(c.exten)); 07093 ast_copy_string(c.context, con->name, sizeof(c.context)); 07094 pbx_substitute_variables_helper(&c, application, expand_buf, sizeof(expand_buf)); 07095 application = expand_buf; 07096 } 07097 07098 length = sizeof(struct ast_exten); 07099 length += strlen(extension) + 1; 07100 length += strlen(application) + 1; 07101 if (label) 07102 length += strlen(label) + 1; 07103 if (callerid) 07104 length += strlen(callerid) + 1; 07105 else 07106 length ++; /* just the '\0' */ 07107 07108 /* Be optimistic: Build the extension structure first */ 07109 if (!(tmp = ast_calloc(1, length))) 07110 return -1; 07111 07112 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */ 07113 label = 0; 07114 07115 /* use p as dst in assignments, as the fields are const char * */ 07116 p = tmp->stuff; 07117 if (label) { 07118 tmp->label = p; 07119 strcpy(p, label); 07120 p += strlen(label) + 1; 07121 } 07122 tmp->exten = p; 07123 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 07124 tmp->priority = priority; 07125 tmp->cidmatch = p; /* but use p for assignments below */ 07126 if (!ast_strlen_zero(callerid)) { 07127 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 07128 tmp->matchcid = 1; 07129 } else { 07130 *p++ = '\0'; 07131 tmp->matchcid = 0; 07132 } 07133 tmp->app = p; 07134 strcpy(p, application); 07135 tmp->parent = con; 07136 tmp->data = data; 07137 tmp->datad = datad; 07138 tmp->registrar = registrar; 07139 07140 if (lockconts) { 07141 ast_wrlock_context(con); 07142 } 07143 07144 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding 07145 an extension, and the trie exists, then we need to incrementally add this pattern to it. */ 07146 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 07147 dummy_exten.exten = dummy_name; 07148 dummy_exten.matchcid = 0; 07149 dummy_exten.cidmatch = 0; 07150 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten); 07151 if (!tmp2) { 07152 /* hmmm, not in the trie; */ 07153 add_exten_to_pattern_tree(con, tmp, 0); 07154 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */ 07155 } 07156 } 07157 res = 0; /* some compilers will think it is uninitialized otherwise */ 07158 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 07159 res = ext_cmp(e->exten, tmp->exten); 07160 if (res == 0) { /* extension match, now look at cidmatch */ 07161 if (!e->matchcid && !tmp->matchcid) 07162 res = 0; 07163 else if (tmp->matchcid && !e->matchcid) 07164 res = 1; 07165 else if (e->matchcid && !tmp->matchcid) 07166 res = -1; 07167 else 07168 res = strcasecmp(e->cidmatch, tmp->cidmatch); 07169 } 07170 if (res >= 0) 07171 break; 07172 } 07173 if (e && res == 0) { /* exact match, insert in the pri chain */ 07174 res = add_pri(con, tmp, el, e, replace); 07175 if (lockconts) { 07176 ast_unlock_context(con); 07177 } 07178 if (res < 0) { 07179 errno = EEXIST; /* XXX do we care ? */ 07180 return 0; /* XXX should we return -1 maybe ? */ 07181 } 07182 } else { 07183 /* 07184 * not an exact match, this is the first entry with this pattern, 07185 * so insert in the main list right before 'e' (if any) 07186 */ 07187 tmp->next = e; 07188 if (el) { /* there is another exten already in this context */ 07189 el->next = tmp; 07190 tmp->peer_table = ast_hashtab_create(13, 07191 hashtab_compare_exten_numbers, 07192 ast_hashtab_resize_java, 07193 ast_hashtab_newsize_java, 07194 hashtab_hash_priority, 07195 0); 07196 tmp->peer_label_table = ast_hashtab_create(7, 07197 hashtab_compare_exten_labels, 07198 ast_hashtab_resize_java, 07199 ast_hashtab_newsize_java, 07200 hashtab_hash_labels, 07201 0); 07202 if (label) { 07203 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 07204 } 07205 ast_hashtab_insert_safe(tmp->peer_table, tmp); 07206 } else { /* this is the first exten in this context */ 07207 if (!con->root_table) 07208 con->root_table = ast_hashtab_create(27, 07209 hashtab_compare_extens, 07210 ast_hashtab_resize_java, 07211 ast_hashtab_newsize_java, 07212 hashtab_hash_extens, 07213 0); 07214 con->root = tmp; 07215 con->root->peer_table = ast_hashtab_create(13, 07216 hashtab_compare_exten_numbers, 07217 ast_hashtab_resize_java, 07218 ast_hashtab_newsize_java, 07219 hashtab_hash_priority, 07220 0); 07221 con->root->peer_label_table = ast_hashtab_create(7, 07222 hashtab_compare_exten_labels, 07223 ast_hashtab_resize_java, 07224 ast_hashtab_newsize_java, 07225 hashtab_hash_labels, 07226 0); 07227 if (label) { 07228 ast_hashtab_insert_safe(con->root->peer_label_table, tmp); 07229 } 07230 ast_hashtab_insert_safe(con->root->peer_table, tmp); 07231 07232 } 07233 ast_hashtab_insert_safe(con->root_table, tmp); 07234 if (lockconts) { 07235 ast_unlock_context(con); 07236 } 07237 if (tmp->priority == PRIORITY_HINT) { 07238 if (lockhints) { 07239 ast_add_hint(tmp); 07240 } else { 07241 ast_add_hint_nolock(tmp); 07242 } 07243 } 07244 } 07245 if (option_debug) { 07246 if (tmp->matchcid) { 07247 ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 07248 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 07249 } else { 07250 ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n", 07251 tmp->exten, tmp->priority, con->name, con); 07252 } 07253 } 07254 07255 if (tmp->matchcid) { 07256 ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 07257 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 07258 } else { 07259 ast_verb(3, "Added extension '%s' priority %d to %s (%p)\n", 07260 tmp->exten, tmp->priority, con->name, con); 07261 } 07262 07263 return 0; 07264 }
| 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 6713 of file pbx.c.
References ast_add_extension2_lockopt(), and find_context().
Referenced by ast_merge_contexts_and_delete().
06716 { 06717 int ret = -1; 06718 struct ast_context *c = find_context(context); 06719 06720 if (c) { 06721 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid, 06722 application, data, datad, registrar, 0, 0); 06723 } 06724 06725 return ret; 06726 }
| static int ast_add_hint | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state.
Definition at line 3546 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().
03547 { 03548 int ret; 03549 03550 AST_RWLIST_WRLOCK(&hints); 03551 ret = ast_add_hint_nolock(e); 03552 AST_RWLIST_UNLOCK(&hints); 03553 03554 return ret; 03555 }
| 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 3517 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().
03518 { 03519 struct ast_hint *hint; 03520 03521 if (!e) 03522 return -1; 03523 03524 /* Search if hint exists, do nothing */ 03525 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03526 if (hint->exten == e) { 03527 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 03528 return -1; 03529 } 03530 } 03531 03532 ast_debug(2, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 03533 03534 if (!(hint = ast_calloc(1, sizeof(*hint)))) { 03535 return -1; 03536 } 03537 /* Initialize and insert new item at the top */ 03538 hint->exten = e; 03539 hint->laststate = ast_extension_state2(e); 03540 AST_RWLIST_INSERT_HEAD(&hints, hint, list); 03541 03542 return 0; 03543 }
| 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 6771 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(), and socket_process().
06772 { 06773 int res = 0; 06774 06775 ast_channel_lock(chan); 06776 06777 if (chan->pbx) { /* This channel is currently in the PBX */ 06778 ast_explicit_goto(chan, context, exten, priority + 1); 06779 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 06780 } else { 06781 /* In order to do it when the channel doesn't really exist within 06782 the PBX, we have to make a new channel, masquerade, and start the PBX 06783 at the new location */ 06784 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name); 06785 if (!tmpchan) { 06786 res = -1; 06787 } else { 06788 if (chan->cdr) { 06789 ast_cdr_discard(tmpchan->cdr); 06790 tmpchan->cdr = ast_cdr_dup(chan->cdr); /* share the love */ 06791 } 06792 /* Make formats okay */ 06793 tmpchan->readformat = chan->readformat; 06794 tmpchan->writeformat = chan->writeformat; 06795 /* Setup proper location */ 06796 ast_explicit_goto(tmpchan, 06797 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 06798 06799 /* Masquerade into temp channel */ 06800 if (ast_channel_masquerade(tmpchan, chan)) { 06801 /* Failed to set up the masquerade. It's probably chan_local 06802 * in the middle of optimizing itself out. Sad. :( */ 06803 ast_hangup(tmpchan); 06804 tmpchan = NULL; 06805 res = -1; 06806 } else { 06807 /* Grab the locks and get going */ 06808 ast_channel_lock(tmpchan); 06809 ast_do_masquerade(tmpchan); 06810 ast_channel_unlock(tmpchan); 06811 /* Start the PBX going on our stolen channel */ 06812 if (ast_pbx_start(tmpchan)) { 06813 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 06814 ast_hangup(tmpchan); 06815 res = -1; 06816 } 06817 } 06818 } 06819 } 06820 ast_channel_unlock(chan); 06821 return res; 06822 }
| int ast_async_goto_by_name | ( | const char * | channame, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 6824 of file pbx.c.
References ast_async_goto(), ast_channel_unlock, and ast_get_channel_by_name_locked().
06825 { 06826 struct ast_channel *chan; 06827 int res = -1; 06828 06829 chan = ast_get_channel_by_name_locked(channame); 06830 if (chan) { 06831 res = ast_async_goto(chan, context, exten, priority); 06832 ast_channel_unlock(chan); 06833 } 06834 return res; 06835 }
| int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 8959 of file pbx.c.
References __ast_goto_if_exists().
08960 { 08961 return __ast_goto_if_exists(chan, context, exten, priority, 1); 08962 }
| int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 9022 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec().
09023 { 09024 return pbx_parseable_goto(chan, goto_string, 1); 09025 }
| int ast_build_timing | ( | struct ast_timing * | i, | |
| const char * | info_in | |||
| ) |
Definition at line 6392 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().
06393 { 06394 char info_save[256]; 06395 char *info; 06396 06397 /* Check for empty just in case */ 06398 if (ast_strlen_zero(info_in)) 06399 return 0; 06400 /* make a copy just in case we were passed a static string */ 06401 ast_copy_string(info_save, info_in, sizeof(info_save)); 06402 info = info_save; 06403 /* Assume everything except time */ 06404 i->monthmask = 0xfff; /* 12 bits */ 06405 i->daymask = 0x7fffffffU; /* 31 bits */ 06406 i->dowmask = 0x7f; /* 7 bits */ 06407 /* on each call, use strsep() to move info to the next argument */ 06408 get_timerange(i, strsep(&info, "|,")); 06409 if (info) 06410 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 06411 if (info) 06412 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 06413 if (info) 06414 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 06415 return 1; 06416 }
| 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 3644 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(), phone_check_exception(), pri_dchannel(), skinny_ss(), ss_thread(), and valid_exit().
03645 { 03646 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 03647 }
Change hint for an extension.
Definition at line 3558 of file pbx.c.
References AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and ast_hint::exten.
Referenced by add_pri_lockopt().
03559 { 03560 struct ast_hint *hint; 03561 int res = -1; 03562 03563 AST_RWLIST_WRLOCK(&hints); 03564 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03565 if (hint->exten == oe) { 03566 hint->exten = ne; 03567 res = 0; 03568 break; 03569 } 03570 } 03571 AST_RWLIST_UNLOCK(&hints); 03572 03573 return res; 03574 }
| int ast_check_timing | ( | const struct ast_timing * | i | ) |
Definition at line 6418 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().
06419 { 06420 struct ast_tm tm; 06421 struct timeval now = ast_tvnow(); 06422 06423 ast_localtime(&now, &tm, NULL); 06424 06425 /* If it's not the right month, return */ 06426 if (!(i->monthmask & (1 << tm.tm_mon))) 06427 return 0; 06428 06429 /* If it's not that time of the month.... */ 06430 /* Warning, tm_mday has range 1..31! */ 06431 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 06432 return 0; 06433 06434 /* If it's not the right day of the week */ 06435 if (!(i->dowmask & (1 << tm.tm_wday))) 06436 return 0; 06437 06438 /* Sanity check the hour just to be safe */ 06439 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 06440 ast_log(LOG_WARNING, "Insane time...\n"); 06441 return 0; 06442 } 06443 06444 /* Now the tough part, we calculate if it fits 06445 in the right time based on min/hour */ 06446 if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2)))) 06447 return 0; 06448 06449 /* If we got this far, then we're good */ 06450 return 1; 06451 }
| 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 6644 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
06645 { 06646 int ret = -1; 06647 struct ast_context *c = find_context_locked(context); 06648 06649 if (c) { 06650 ret = ast_context_add_ignorepat2(c, value, registrar); 06651 ast_unlock_contexts(); 06652 } 06653 return ret; 06654 }
| int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | value, | |||
| const char * | registrar | |||
| ) |
Definition at line 6656 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().
06657 { 06658 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 06659 int length; 06660 char *pattern; 06661 length = sizeof(struct ast_ignorepat); 06662 length += strlen(value) + 1; 06663 if (!(ignorepat = ast_calloc(1, length))) 06664 return -1; 06665 /* The cast to char * is because we need to write the initial value. 06666 * The field is not supposed to be modified otherwise. Also, gcc 4.2 06667 * sees the cast as dereferencing a type-punned pointer and warns about 06668 * it. This is the workaround (we're telling gcc, yes, that's really 06669 * what we wanted to do). 06670 */ 06671 pattern = (char *) ignorepat->pattern; 06672 strcpy(pattern, value); 06673 ignorepat->next = NULL; 06674 ignorepat->registrar = registrar; 06675 ast_wrlock_context(con); 06676 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 06677 ignorepatl = ignorepatc; 06678 if (!strcasecmp(ignorepatc->pattern, value)) { 06679 /* Already there */ 06680 ast_unlock_context(con); 06681 errno = EEXIST; 06682 return -1; 06683 } 06684 } 06685 if (ignorepatl) 06686 ignorepatl->next = ignorepat; 06687 else 06688 con->ignorepats = ignorepat; 06689 ast_unlock_context(con); 06690 return 0; 06691 06692 }
| 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 6198 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
06199 { 06200 int ret = -1; 06201 struct ast_context *c = find_context_locked(context); 06202 06203 if (c) { 06204 ret = ast_context_add_include2(c, include, registrar); 06205 ast_unlock_contexts(); 06206 } 06207 return ret; 06208 }
| 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 6460 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().
06462 { 06463 struct ast_include *new_include; 06464 char *c; 06465 struct ast_include *i, *il = NULL; /* include, include_last */ 06466 int length; 06467 char *p; 06468 06469 length = sizeof(struct ast_include); 06470 length += 2 * (strlen(value) + 1); 06471 06472 /* allocate new include structure ... */ 06473 if (!(new_include = ast_calloc(1, length))) 06474 return -1; 06475 /* Fill in this structure. Use 'p' for assignments, as the fields 06476 * in the structure are 'const char *' 06477 */ 06478 p = new_include->stuff; 06479 new_include->name = p; 06480 strcpy(p, value); 06481 p += strlen(value) + 1; 06482 new_include->rname = p; 06483 strcpy(p, value); 06484 /* Strip off timing info, and process if it is there */ 06485 if ( (c = strchr(p, ',')) ) { 06486 *c++ = '\0'; 06487 new_include->hastime = ast_build_timing(&(new_include->timing), c); 06488 } 06489 new_include->next = NULL; 06490 new_include->registrar = registrar; 06491 06492 ast_wrlock_context(con); 06493 06494 /* ... go to last include and check if context is already included too... */ 06495 for (i = con->includes; i; i = i->next) { 06496 if (!strcasecmp(i->name, new_include->name)) { 06497 ast_free(new_include); 06498 ast_unlock_context(con); 06499 errno = EEXIST; 06500 return -1; 06501 } 06502 il = i; 06503 } 06504 06505 /* ... include new context into context list, unlock, return */ 06506 if (il) 06507 il->next = new_include; 06508 else 06509 con->includes = new_include; 06510 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 06511 06512 ast_unlock_context(con); 06513 06514 return 0; 06515 }
| 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 6522 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
06523 { 06524 int ret = -1; 06525 struct ast_context *c = find_context_locked(context); 06526 06527 if (c) { /* found, add switch to this context */ 06528 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 06529 ast_unlock_contexts(); 06530 } 06531 return ret; 06532 }
| 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 6541 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().
06543 { 06544 struct ast_sw *new_sw; 06545 struct ast_sw *i; 06546 int length; 06547 char *p; 06548 06549 length = sizeof(struct ast_sw); 06550 length += strlen(value) + 1; 06551 if (data) 06552 length += strlen(data); 06553 length++; 06554 06555 /* allocate new sw structure ... */ 06556 if (!(new_sw = ast_calloc(1, length))) 06557 return -1; 06558 /* ... fill in this structure ... */ 06559 p = new_sw->stuff; 06560 new_sw->name = p; 06561 strcpy(new_sw->name, value); 06562 p += strlen(value) + 1; 06563 new_sw->data = p; 06564 if (data) { 06565 strcpy(new_sw->data, data); 06566 p += strlen(data) + 1; 06567 } else { 06568 strcpy(new_sw->data, ""); 06569 p++; 06570 } 06571 new_sw->eval = eval; 06572 new_sw->registrar = registrar; 06573 06574 /* ... try to lock this context ... */ 06575 ast_wrlock_context(con); 06576 06577 /* ... go to last sw and check if context is already swd too... */ 06578 AST_LIST_TRAVERSE(&con->alts, i, list) { 06579 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 06580 ast_free(new_sw); 06581 ast_unlock_context(con); 06582 errno = EEXIST; 06583 return -1; 06584 } 06585 } 06586 06587 /* ... sw new context into context list, unlock, return */ 06588 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 06589 06590 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 06591 06592 ast_unlock_context(con); 06593 06594 return 0; 06595 }
| 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 7839 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().
07840 { 07841 ast_wrlock_contexts(); 07842 __ast_context_destroy(contexts, contexts_table, con,registrar); 07843 ast_unlock_contexts(); 07844 }
| 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 2015 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().
02016 { 02017 struct ast_context *tmp = NULL; 02018 struct fake_context item; 02019 02020 ast_copy_string(item.name, name, sizeof(item.name)); 02021 02022 ast_rdlock_contexts(); 02023 if( contexts_table ) { 02024 tmp = ast_hashtab_lookup(contexts_table,&item); 02025 } else { 02026 while ( (tmp = ast_walk_contexts(tmp)) ) { 02027 if (!name || !strcasecmp(name, tmp->name)) 02028 break; 02029 } 02030 } 02031 ast_unlock_contexts(); 02032 return tmp; 02033 }
| 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 5855 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().
05856 { 05857 struct ast_context *tmp, **local_contexts; 05858 struct fake_context search; 05859 int length = sizeof(struct ast_context) + strlen(name) + 1; 05860 05861 if (!contexts_table) { 05862 contexts_table = ast_hashtab_create(17, 05863 ast_hashtab_compare_contexts, 05864 ast_hashtab_resize_java, 05865 ast_hashtab_newsize_java, 05866 ast_hashtab_hash_contexts, 05867 0); 05868 } 05869 05870 ast_copy_string(search.name, name, sizeof(search.name)); 05871 if (!extcontexts) { 05872 ast_rdlock_contexts(); 05873 local_contexts = &contexts; 05874 tmp = ast_hashtab_lookup(contexts_table, &search); 05875 ast_unlock_contexts(); 05876 if (tmp) { 05877 tmp->refcount++; 05878 return tmp; 05879 } 05880 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 05881 local_contexts = extcontexts; 05882 tmp = ast_hashtab_lookup(exttable, &search); 05883 if (tmp) { 05884 tmp->refcount++; 05885 return tmp; 05886 } 05887 } 05888 05889 if ((tmp = ast_calloc(1, length))) { 05890 ast_rwlock_init(&tmp->lock); 05891 ast_mutex_init(&tmp->macrolock); 05892 strcpy(tmp->name, name); 05893 tmp->root = NULL; 05894 tmp->root_table = NULL; 05895 tmp->registrar = ast_strdup(registrar); 05896 tmp->includes = NULL; 05897 tmp->ignorepats = NULL; 05898 tmp->refcount = 1; 05899 } else { 05900 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 05901 return NULL; 05902 } 05903 05904 if (!extcontexts) { 05905 ast_wrlock_contexts(); 05906 tmp->next = *local_contexts; 05907 *local_contexts = tmp; 05908 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 05909 ast_unlock_contexts(); 05910 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 05911 ast_verb(3, "Registered extension context '%s' (%p) in table %p; registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 05912 } else { 05913 tmp->next = *local_contexts; 05914 if (exttable) 05915 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 05916 05917 *local_contexts = tmp; 05918 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 05919 ast_verb(3, "Registered extension context '%s' (%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 05920 } 05921 return tmp; 05922 }
| int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 4469 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().
04470 { 04471 struct ast_context *c = NULL; 04472 int ret = -1; 04473 struct fake_context item; 04474 04475 ast_rdlock_contexts(); 04476 04477 ast_copy_string(item.name, context, sizeof(item.name)); 04478 04479 c = ast_hashtab_lookup(contexts_table,&item); 04480 if (c) 04481 ret = 0; 04482 04483 04484 #ifdef NOTNOW 04485 04486 while ((c = ast_walk_contexts(c))) { 04487 if (!strcmp(ast_get_context_name(c), context)) { 04488 ret = 0; 04489 break; 04490 } 04491 } 04492 04493 #endif 04494 ast_unlock_contexts(); 04495 04496 /* if we found context, lock macrolock */ 04497 if (ret == 0) 04498 ret = ast_mutex_lock(&c->macrolock); 04499 04500 return ret; 04501 }
| 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 4276 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), unregister_exten(), and UnregisterExtension().
04277 { 04278 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 04279 }
| 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 4303 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by load_config(), manage_parkinglot(), park_exec_full(), and unload_module().
04304 { 04305 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 04306 }
| 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 4281 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().
04282 { 04283 int ret = -1; /* default error return */ 04284 struct ast_context *c = find_context_locked(context); 04285 04286 if (c) { /* ... remove extension ... */ 04287 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1); 04288 ast_unlock_contexts(); 04289 } 04290 return ret; 04291 }
| 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 4308 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().
04309 { 04310 struct ast_exten *exten, *prev_exten = NULL; 04311 struct ast_exten *peer; 04312 struct ast_exten ex, *exten2, *exten3; 04313 char dummy_name[1024]; 04314 struct ast_exten *previous_peer = NULL; 04315 struct ast_exten *next_peer = NULL; 04316 int found = 0; 04317 04318 if (!already_locked) 04319 ast_wrlock_context(con); 04320 04321 /* Handle this is in the new world */ 04322 04323 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 04324 * peers, not just those matching the callerid. */ 04325 #ifdef NEED_DEBUG 04326 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 04327 #endif 04328 #ifdef CONTEXT_DEBUG 04329 check_contexts(__FILE__, __LINE__); 04330 #endif 04331 /* find this particular extension */ 04332 ex.exten = dummy_name; 04333 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 04334 ex.cidmatch = callerid; 04335 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 04336 exten = ast_hashtab_lookup(con->root_table, &ex); 04337 if (exten) { 04338 if (priority == 0) { 04339 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 04340 if (!exten2) 04341 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); 04342 if (con->pattern_tree) { 04343 04344 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 04345 04346 if (x->exten) { /* this test for safety purposes */ 04347 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 04348 x->exten = 0; /* get rid of what will become a bad pointer */ 04349 } else { 04350 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 04351 } 04352 } 04353 } else { 04354 ex.priority = priority; 04355 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 04356 if (exten2) { 04357 04358 if (exten2->label) { /* if this exten has a label, remove that, too */ 04359 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 04360 if (!exten3) 04361 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); 04362 } 04363 04364 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 04365 if (!exten3) 04366 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); 04367 if (exten2 == exten && exten2->peer) { 04368 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 04369 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 04370 } 04371 if (ast_hashtab_size(exten->peer_table) == 0) { 04372 /* well, if the last priority of an exten is to be removed, 04373 then, the extension is removed, too! */ 04374 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 04375 if (!exten3) 04376 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 04377 if (con->pattern_tree) { 04378 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 04379 if (x->exten) { /* this test for safety purposes */ 04380 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 04381 x->exten = 0; /* get rid of what will become a bad pointer */ 04382 } 04383 } 04384 } 04385 } else { 04386 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 04387 priority, exten->exten, con->name); 04388 } 04389 } 04390 } else { 04391 /* hmmm? this exten is not in this pattern tree? */ 04392 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 04393 extension, con->name); 04394 } 04395 #ifdef NEED_DEBUG 04396 if (con->pattern_tree) { 04397 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 04398 log_match_char_tree(con->pattern_tree, " "); 04399 } 04400 #endif 04401 04402 /* scan the extension list to find first matching extension-registrar */ 04403 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 04404 if (!strcmp(exten->exten, extension) && 04405 (!registrar || !strcmp(exten->registrar, registrar)) && 04406 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 04407 break; 04408 } 04409 if (!exten) { 04410 /* we can't find right extension */ 04411 if (!already_locked) 04412 ast_unlock_context(con); 04413 return -1; 04414 } 04415 04416 /* scan the priority list to remove extension with exten->priority == priority */ 04417 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 04418 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))); 04419 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 04420 if ((priority == 0 || peer->priority == priority) && 04421 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 04422 (!registrar || !strcmp(peer->registrar, registrar) )) { 04423 found = 1; 04424 04425 /* we are first priority extension? */ 04426 if (!previous_peer) { 04427 /* 04428 * We are first in the priority chain, so must update the extension chain. 04429 * The next node is either the next priority or the next extension 04430 */ 04431 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 04432 if (peer->peer) { 04433 /* move the peer_table and peer_label_table down to the next peer, if 04434 it is there */ 04435 peer->peer->peer_table = peer->peer_table; 04436 peer->peer->peer_label_table = peer->peer_label_table; 04437 peer->peer_table = NULL; 04438 peer->peer_label_table = NULL; 04439 } 04440 if (!prev_exten) { /* change the root... */ 04441 con->root = next_node; 04442 } else { 04443 prev_exten->next = next_node; /* unlink */ 04444 } 04445 if (peer->peer) { /* update the new head of the pri list */ 04446 peer->peer->next = peer->next; 04447 } 04448 } else { /* easy, we are not first priority in extension */ 04449 previous_peer->peer = peer->peer; 04450 } 04451 04452 /* now, free whole priority extension */ 04453 destroy_exten(peer); 04454 } else { 04455 previous_peer = peer; 04456 } 04457 } 04458 if (!already_locked) 04459 ast_unlock_context(con); 04460 return found ? 0 : -1; 04461 }
| int ast_context_remove_ignorepat | ( | const char * | context, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 6601 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
06602 { 06603 int ret = -1; 06604 struct ast_context *c = find_context_locked(context); 06605 06606 if (c) { 06607 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 06608 ast_unlock_contexts(); 06609 } 06610 return ret; 06611 }
| int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 6613 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().
06614 { 06615 struct ast_ignorepat *ip, *ipl = NULL; 06616 06617 ast_wrlock_context(con); 06618 06619 for (ip = con->ignorepats; ip; ip = ip->next) { 06620 if (!strcmp(ip->pattern, ignorepat) && 06621 (!registrar || (registrar == ip->registrar))) { 06622 if (ipl) { 06623 ipl->next = ip->next; 06624 ast_free(ip); 06625 } else { 06626 con->ignorepats = ip->next; 06627 ast_free(ip); 06628 } 06629 ast_unlock_context(con); 06630 return 0; 06631 } 06632 ipl = ip; 06633 } 06634 06635 ast_unlock_context(con); 06636 errno = EINVAL; 06637 return -1; 06638 }
| 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 4168 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
04169 { 04170 int ret = -1; 04171 struct ast_context *c = find_context_locked(context); 04172 04173 if (c) { 04174 /* found, remove include from this context ... */ 04175 ret = ast_context_remove_include2(c, include, registrar); 04176 ast_unlock_contexts(); 04177 } 04178 return ret; 04179 }
| 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 4190 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().
04191 { 04192 struct ast_include *i, *pi = NULL; 04193 int ret = -1; 04194 04195 ast_wrlock_context(con); 04196 04197 /* find our include */ 04198 for (i = con->includes; i; pi = i, i = i->next) { 04199 if (!strcmp(i->name, include) && 04200 (!registrar || !strcmp(i->registrar, registrar))) { 04201 /* remove from list */ 04202 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 04203 if (pi) 04204 pi->next = i->next; 04205 else 04206 con->includes = i->next; 04207 /* free include and return */ 04208 ast_free(i); 04209 ret = 0; 04210 break; 04211 } 04212 } 04213 04214 ast_unlock_context(con); 04215 04216 return ret; 04217 }
| int ast_context_remove_switch | ( | const char * | context, | |
| const char * | sw, | |||
| const char * | data, | |||
| const char * | registrar | |||
| ) |
Remove a switch.
Definition at line 4224 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
04225 { 04226 int ret = -1; /* default error return */ 04227 struct ast_context *c = find_context_locked(context); 04228 04229 if (c) { 04230 /* remove switch from this context ... */ 04231 ret = ast_context_remove_switch2(c, sw, data, registrar); 04232 ast_unlock_contexts(); 04233 } 04234 return ret; 04235 }
| 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 4245 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().
04246 { 04247 struct ast_sw *i; 04248 int ret = -1; 04249 04250 ast_wrlock_context(con); 04251 04252 /* walk switches */ 04253 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 04254 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 04255 (!registrar || !strcmp(i->registrar, registrar))) { 04256 /* found, remove from list */ 04257 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 04258 AST_LIST_REMOVE_CURRENT(list); 04259 ast_free(i); /* free switch and return */ 04260 ret = 0; 04261 break; 04262 } 04263 } 04264 AST_LIST_TRAVERSE_SAFE_END; 04265 04266 ast_unlock_context(con); 04267 04268 return ret; 04269 }
| int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 4508 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().
04509 { 04510 struct ast_context *c = NULL; 04511 int ret = -1; 04512 struct fake_context item; 04513 04514 ast_rdlock_contexts(); 04515 04516 ast_copy_string(item.name, context, sizeof(item.name)); 04517 04518 c = ast_hashtab_lookup(contexts_table,&item); 04519 if (c) 04520 ret = 0; 04521 #ifdef NOTNOW 04522 04523 while ((c = ast_walk_contexts(c))) { 04524 if (!strcmp(ast_get_context_name(c), context)) { 04525 ret = 0; 04526 break; 04527 } 04528 } 04529 04530 #endif 04531 ast_unlock_contexts(); 04532 04533 /* if we found context, unlock macrolock */ 04534 if (ret == 0) 04535 ret = ast_mutex_unlock(&c->macrolock); 04536 04537 return ret; 04538 }
| 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 8916 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().
08917 { 08918 struct ast_include *inc = NULL; 08919 int res = 0; 08920 08921 while ( (inc = ast_walk_context_includes(con, inc)) ) { 08922 if (ast_context_find(inc->rname)) 08923 continue; 08924 08925 res = -1; 08926 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 08927 ast_get_context_name(con), inc->rname); 08928 break; 08929 } 08930 08931 return res; 08932 }
| struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 2766 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().
02767 { 02768 struct ast_custom_function *acf = NULL; 02769 02770 AST_RWLIST_RDLOCK(&acf_root); 02771 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 02772 if (!strcmp(name, acf->name)) 02773 break; 02774 } 02775 AST_RWLIST_UNLOCK(&acf_root); 02776 02777 return acf; 02778 }
| int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 2780 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().
02781 { 02782 struct ast_custom_function *cur; 02783 02784 if (!acf) 02785 return -1; 02786 02787 AST_RWLIST_WRLOCK(&acf_root); 02788 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) 02789 ast_verb(2, "Unregistered custom function %s\n", cur->name); 02790 AST_RWLIST_UNLOCK(&acf_root); 02791 02792 return cur ? 0 : -1; 02793 }
| 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 3259 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().
03260 { 03261 switch (devstate) { 03262 case AST_DEVICE_ONHOLD: 03263 return AST_EXTENSION_ONHOLD; 03264 case AST_DEVICE_BUSY: 03265 return AST_EXTENSION_BUSY; 03266 case AST_DEVICE_UNAVAILABLE: 03267 case AST_DEVICE_UNKNOWN: 03268 case AST_DEVICE_INVALID: 03269 return AST_EXTENSION_UNAVAILABLE; 03270 case AST_DEVICE_RINGINUSE: 03271 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 03272 case AST_DEVICE_RINGING: 03273 return AST_EXTENSION_RINGING; 03274 case AST_DEVICE_INUSE: 03275 return AST_EXTENSION_INUSE; 03276 case AST_DEVICE_NOT_INUSE: 03277 return AST_EXTENSION_NOT_INUSE; 03278 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 03279 break; 03280 } 03281 03282 return AST_EXTENSION_NOT_INUSE; 03283 }
| 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 3629 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(), skinny_ss(), socket_process(), ss7_linkset(), ss_thread(), and waitstream_core().
03630 { 03631 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 03632 }
| int ast_explicit_goto | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 6748 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().
06749 { 06750 if (!chan) 06751 return -1; 06752 06753 ast_channel_lock(chan); 06754 06755 if (!ast_strlen_zero(context)) 06756 ast_copy_string(chan->context, context, sizeof(chan->context)); 06757 if (!ast_strlen_zero(exten)) 06758 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06759 if (priority > -1) { 06760 chan->priority = priority; 06761 /* see flag description in channel.h for explanation */ 06762 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 06763 chan->priority--; 06764 } 06765 06766 ast_channel_unlock(chan); 06767 06768 return 0; 06769 }
| int ast_extension_close | ( | const char * | pattern, | |
| const char * | data, | |||
| int | needmore | |||
| ) |
Definition at line 1992 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().
01993 { 01994 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 01995 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 01996 return extension_match_core(pattern, data, needmore); 01997 }
| 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 1794 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
01795 { 01796 return ext_cmp(a, b); 01797 }
| 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 1987 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().
01988 { 01989 return extension_match_core(pattern, data, E_MATCH); 01990 }
| 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 3321 of file pbx.c.
References ast_extension_state2(), and ast_hint_extension().
Referenced by action_extensionstate(), extstate_read(), and handle_request_subscribe().
03322 { 03323 struct ast_exten *e; 03324 03325 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */ 03326 if (!e) 03327 return -1; /* No hint, return -1 */ 03328 03329 return ast_extension_state2(e); /* Check all devices in the hint */ 03330 }
| static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
Check state of extension by using hints.
Definition at line 3286 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().
03287 { 03288 char hint[AST_MAX_EXTENSION] = ""; 03289 char *cur, *rest; 03290 struct ast_devstate_aggregate agg; 03291 03292 if (!e) 03293 return -1; 03294 03295 ast_devstate_aggregate_init(&agg); 03296 03297 ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint)); 03298 03299 rest = hint; /* One or more devices separated with a & character */ 03300 03301 while ( (cur = strsep(&rest, "&")) ) { 03302 ast_devstate_aggregate_add(&agg, ast_device_state(cur)); 03303 } 03304 03305 return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg)); 03306 }
| 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 3309 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().
03310 { 03311 int i; 03312 03313 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 03314 if (extension_states[i].extension_state == extension_state) 03315 return extension_states[i].text; 03316 } 03317 return "Unknown"; 03318 }
| 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 3382 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().
03384 { 03385 struct ast_hint *hint; 03386 struct ast_state_cb *cblist; 03387 struct ast_exten *e; 03388 03389 /* If there's no context and extension: add callback to statecbs list */ 03390 if (!context && !exten) { 03391 AST_RWLIST_WRLOCK(&hints); 03392 03393 AST_LIST_TRAVERSE(&statecbs, cblist, entry) { 03394 if (cblist->callback == callback) { 03395 cblist->data = data; 03396 AST_RWLIST_UNLOCK(&hints); 03397 return 0; 03398 } 03399 } 03400 03401 /* Now insert the callback */ 03402 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 03403 AST_RWLIST_UNLOCK(&hints); 03404 return -1; 03405 } 03406 cblist->id = 0; 03407 cblist->callback = callback; 03408 cblist->data = data; 03409 03410 AST_LIST_INSERT_HEAD(&statecbs, cblist, entry); 03411 03412 AST_RWLIST_UNLOCK(&hints); 03413 03414 return 0; 03415 } 03416 03417 if (!context || !exten) 03418 return -1; 03419 03420 /* This callback type is for only one hint, so get the hint */ 03421 e = ast_hint_extension(NULL, context, exten); 03422 if (!e) { 03423 return -1; 03424 } 03425 03426 /* If this is a pattern, dynamically create a new extension for this 03427 * particular match. Note that this will only happen once for each 03428 * individual extension, because the pattern will no longer match first. 03429 */ 03430 if (e->exten[0] == '_') { 03431 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 03432 e->cidmatch, e->app, ast_strdup(e->data), ast_free_ptr, 03433 e->registrar); 03434 e = ast_hint_extension(NULL, context, exten); 03435 if (!e || e->exten[0] == '_') { 03436 return -1; 03437 } 03438 } 03439 03440 /* Find the hint in the list of hints */ 03441 AST_RWLIST_WRLOCK(&hints); 03442 03443 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03444 if (hint->exten == e) 03445 break; 03446 } 03447 03448 if (!hint) { 03449 /* We have no hint, sorry */ 03450 AST_RWLIST_UNLOCK(&hints); 03451 return -1; 03452 } 03453 03454 /* Now insert the callback in the callback list */ 03455 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 03456 AST_RWLIST_UNLOCK(&hints); 03457 return -1; 03458 } 03459 03460 cblist->id = stateid++; /* Unique ID for this callback */ 03461 cblist->callback = callback; /* Pointer to callback routine */ 03462 cblist->data = data; /* Data for the callback */ 03463 03464 AST_LIST_INSERT_HEAD(&hint->callbacks, cblist, entry); 03465 03466 AST_RWLIST_UNLOCK(&hints); 03467 03468 return cblist->id; 03469 }
| 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 3472 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().
03473 { 03474 struct ast_state_cb *p_cur = NULL; 03475 int ret = -1; 03476 03477 if (!id && !callback) 03478 return -1; 03479 03480 AST_RWLIST_WRLOCK(&hints); 03481 03482 if (!id) { /* id == 0 is a callback without extension */ 03483 AST_LIST_TRAVERSE_SAFE_BEGIN(&statecbs, p_cur, entry) { 03484 if (p_cur->callback == callback) { 03485 AST_LIST_REMOVE_CURRENT(entry); 03486 break; 03487 } 03488 } 03489 AST_LIST_TRAVERSE_SAFE_END; 03490 } else { /* callback with extension, find the callback based on ID */ 03491 struct ast_hint *hint; 03492 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03493 AST_LIST_TRAVERSE_SAFE_BEGIN(&hint->callbacks, p_cur, entry) { 03494 if (p_cur->id == id) { 03495 AST_LIST_REMOVE_CURRENT(entry); 03496 break; 03497 } 03498 } 03499 AST_LIST_TRAVERSE_SAFE_END; 03500 03501 if (p_cur) 03502 break; 03503 } 03504 } 03505 03506 if (p_cur) { 03507 ast_free(p_cur); 03508 } 03509 03510 AST_RWLIST_UNLOCK(&hints); 03511 03512 return ret; 03513 }
| 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 3634 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().
03635 { 03636 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 03637 }
| 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 3639 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
03640 { 03641 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 03642 }
| 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 2853 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().
02854 { 02855 char *copy = ast_strdupa(function); 02856 char *args = func_args(copy); 02857 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 02858 02859 if (acfptr == NULL) 02860 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 02861 else if (!acfptr->read) 02862 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 02863 else { 02864 int res; 02865 struct ast_module_user *u = NULL; 02866 if (acfptr->mod) 02867 u = __ast_module_user_add(acfptr->mod, chan); 02868 res = acfptr->read(chan, copy, args, workspace, len); 02869 if (acfptr->mod && u) 02870 __ast_module_user_remove(acfptr->mod, u); 02871 return res; 02872 } 02873 return -1; 02874 }
| 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 2876 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().
02877 { 02878 char *copy = ast_strdupa(function); 02879 char *args = func_args(copy); 02880 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 02881 02882 if (acfptr == NULL) 02883 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 02884 else if (!acfptr->write) 02885 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 02886 else { 02887 int res; 02888 struct ast_module_user *u = NULL; 02889 if (acfptr->mod) 02890 u = __ast_module_user_add(acfptr->mod, chan); 02891 res = acfptr->write(chan, copy, args, value); 02892 if (acfptr->mod && u) 02893 __ast_module_user_remove(acfptr->mod, u); 02894 return res; 02895 } 02896 02897 return -1; 02898 }
| const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 8768 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 8806 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
08807 { 08808 return c ? c->registrar : NULL; 08809 }
| const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 8836 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().
08837 { 08838 return e ? e->app : NULL; 08839 }
| void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 8841 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().
08842 { 08843 return e ? e->data : NULL; 08844 }
| const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 8831 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
08832 { 08833 return e ? e->cidmatch : NULL; 08834 }
| struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 8773 of file pbx.c.
References ast_exten::parent.
Referenced by handle_show_hint(), and handle_show_hints().
08774 { 08775 return exten ? exten->parent : NULL; 08776 }
| const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 8783 of file pbx.c.
References ast_exten::label.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
08784 { 08785 return exten ? exten->label : NULL; 08786 }
| int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 8826 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
08827 { 08828 return e ? e->matchcid : 0; 08829 }
| const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 8778 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().
08779 { 08780 return exten ? exten->exten : NULL; 08781 }
| int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 8798 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().
08799 { 08800 return exten ? exten->priority : -1; 08801 }
| const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 8811 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
08812 { 08813 return e ? e->registrar : NULL; 08814 }
| 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 3612 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().
03613 { 03614 struct ast_exten *e = ast_hint_extension(c, context, exten); 03615 03616 if (e) { 03617 if (hint) 03618 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 03619 if (name) { 03620 const char *tmp = ast_get_extension_app_data(e); 03621 if (tmp) 03622 ast_copy_string(name, tmp, namesize); 03623 } 03624 return -1; 03625 } 03626 return 0; 03627 }
| const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 8793 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().
08794 { 08795 return ip ? ip->pattern : NULL; 08796 }
| const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 8821 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().
08822 { 08823 return ip ? ip->registrar : NULL; 08824 }
| const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 8788 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().
08789 { 08790 return inc ? inc->name : NULL; 08791 }
| const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 8816 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().
08817 { 08818 return i ? i->registrar : NULL; 08819 }
| const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 8851 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().
08852 { 08853 return sw ? sw->data : NULL; 08854 }
| int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 8856 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
08857 { 08858 return sw->eval; 08859 }
| const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 8846 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().
08847 { 08848 return sw ? sw->name : NULL; 08849 }
| const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 8861 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().
08862 { 08863 return sw ? sw->registrar : NULL; 08864 }
| int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 8954 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().
08955 { 08956 return __ast_goto_if_exists(chan, context, exten, priority, 0); 08957 }
| 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 3250 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().
03251 { 03252 struct ast_exten *e; 03253 ast_rdlock_contexts(); 03254 e = ast_hint_extension_nolock(c, context, exten); 03255 ast_unlock_contexts(); 03256 return e; 03257 }
| 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 3244 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().
03245 { 03246 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 03247 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 03248 }
| 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 6694 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().
06695 { 06696 struct ast_context *con = ast_context_find(context); 06697 if (con) { 06698 struct ast_ignorepat *pat; 06699 for (pat = con->ignorepats; pat; pat = pat->next) { 06700 if (ast_extension_match(pat->pattern, pattern)) 06701 return 1; 06702 } 06703 } 06704 06705 return 0; 06706 }
| 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 3649 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().
03650 { 03651 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 03652 }
| 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 6054 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_context::registrar, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
06055 { 06056 double ft; 06057 struct ast_context *tmp, *oldcontextslist; 06058 struct ast_hashtab *oldtable; 06059 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 06060 struct store_hint *this; 06061 struct ast_hint *hint; 06062 struct ast_exten *exten; 06063 int length; 06064 struct ast_state_cb *thiscb; 06065 struct ast_hashtab_iter *iter; 06066 06067 /* it is very important that this function hold the hint list lock _and_ the conlock 06068 during its operation; not only do we need to ensure that the list of contexts 06069 and extensions does not change, but also that no hint callbacks (watchers) are 06070 added or removed during the merge/delete process 06071 06072 in addition, the locks _must_ be taken in this order, because there are already 06073 other code paths that use this order 06074 */ 06075 06076 struct timeval begintime, writelocktime, endlocktime, enddeltime; 06077 int wrlock_ver; 06078 06079 begintime = ast_tvnow(); 06080 ast_rdlock_contexts(); 06081 iter = ast_hashtab_start_traversal(contexts_table); 06082 while ((tmp = ast_hashtab_next(iter))) { 06083 context_merge(extcontexts, exttable, tmp, registrar); 06084 } 06085 ast_hashtab_end_traversal(iter); 06086 wrlock_ver = ast_wrlock_contexts_version(); 06087 06088 ast_unlock_contexts(); /* this feels real retarded, but you must do 06089 what you must do If this isn't done, the following 06090 wrlock is a guraranteed deadlock */ 06091 ast_wrlock_contexts(); 06092 if (ast_wrlock_contexts_version() > wrlock_ver+1) { 06093 ast_log(LOG_WARNING,"==================!!!!!!!!!!!!!!!Something changed the contexts in the middle of merging contexts!\n"); 06094 } 06095 06096 AST_RWLIST_WRLOCK(&hints); 06097 writelocktime = ast_tvnow(); 06098 06099 /* preserve all watchers for hints associated with this registrar */ 06100 AST_RWLIST_TRAVERSE(&hints, hint, list) { 06101 if (!AST_LIST_EMPTY(&hint->callbacks) && !strcmp(registrar, hint->exten->parent->registrar)) { 06102 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 06103 if (!(this = ast_calloc(1, length))) 06104 continue; 06105 AST_LIST_APPEND_LIST(&this->callbacks, &hint->callbacks, entry); 06106 this->laststate = hint->laststate; 06107 this->context = this->data; 06108 strcpy(this->data, hint->exten->parent->name); 06109 this->exten = this->data + strlen(this->context) + 1; 06110 strcpy(this->exten, hint->exten->exten); 06111 AST_LIST_INSERT_HEAD(&store, this, list); 06112 } 06113 } 06114 06115 /* save the old table and list */ 06116 oldtable = contexts_table; 06117 oldcontextslist = contexts; 06118 06119 /* move in the new table and list */ 06120 contexts_table = exttable; 06121 contexts = *extcontexts; 06122 06123 /* restore the watchers for hints that can be found; notify those that 06124 cannot be restored 06125 */ 06126 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 06127 struct pbx_find_info q = { .stacklen = 0 }; 06128 exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH); 06129 /* If this is a pattern, dynamically create a new extension for this 06130 * particular match. Note that this will only happen once for each 06131 * individual extension, because the pattern will no longer match first. 06132 */ 06133 if (exten && exten->exten[0] == '_') { 06134 ast_add_extension_nolock(exten->parent->name, 0, this->exten, PRIORITY_HINT, NULL, 06135 0, exten->app, ast_strdup(exten->data), ast_free_ptr, registrar); 06136 /* rwlocks are not recursive locks */ 06137 exten = ast_hint_extension_nolock(NULL, this->context, this->exten); 06138 } 06139 06140 /* Find the hint in the list of hints */ 06141 AST_RWLIST_TRAVERSE(&hints, hint, list) { 06142 if (hint->exten == exten) 06143 break; 06144 } 06145 if (!exten || !hint) { 06146 /* this hint has been removed, notify the watchers */ 06147 while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) { 06148 thiscb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, thiscb->data); 06149 ast_free(thiscb); 06150 } 06151 } else { 06152 AST_LIST_APPEND_LIST(&hint->callbacks, &this->callbacks, entry); 06153 hint->laststate = this->laststate; 06154 } 06155 ast_free(this); 06156 } 06157 06158 AST_RWLIST_UNLOCK(&hints); 06159 ast_unlock_contexts(); 06160 endlocktime = ast_tvnow(); 06161 06162 /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk 06163 is now freely using the new stuff instead */ 06164 06165 ast_hashtab_destroy(oldtable, NULL); 06166 06167 for (tmp = oldcontextslist; tmp; ) { 06168 struct ast_context *next; /* next starting point */ 06169 next = tmp->next; 06170 __ast_internal_context_destroy(tmp); 06171 tmp = next; 06172 } 06173 enddeltime = ast_tvnow(); 06174 06175 ft = ast_tvdiff_us(writelocktime, begintime); 06176 ft /= 1000000.0; 06177 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 06178 06179 ft = ast_tvdiff_us(endlocktime, writelocktime); 06180 ft /= 1000000.0; 06181 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 06182 06183 ft = ast_tvdiff_us(enddeltime, endlocktime); 06184 ft /= 1000000.0; 06185 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 06186 06187 ft = ast_tvdiff_us(enddeltime, begintime); 06188 ft /= 1000000.0; 06189 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 06190 return; 06191 }
| AST_MUTEX_DEFINE_STATIC | ( | maxcalllock | ) |
| int ast_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 9017 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().
09018 { 09019 return pbx_parseable_goto(chan, goto_string, 0); 09020 }
| 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 7530 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().
07531 { 07532 struct ast_channel *chan; 07533 struct app_tmp *tmp; 07534 int res = -1, cdr_res = -1; 07535 struct outgoing_helper oh; 07536 07537 memset(&oh, 0, sizeof(oh)); 07538 oh.vars = vars; 07539 oh.account = account; 07540 07541 if (locked_channel) 07542 *locked_channel = NULL; 07543 if (ast_strlen_zero(app)) { 07544 res = -1; 07545 goto outgoing_app_cleanup; 07546 } 07547 if (synchronous) { 07548 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07549 if (chan) { 07550 ast_set_variables(chan, vars); 07551 if (account) 07552 ast_cdr_setaccount(chan, account); 07553 if (chan->_state == AST_STATE_UP) { 07554 res = 0; 07555 ast_verb(4, "Channel %s was answered.\n", chan->name); 07556 tmp = ast_calloc(1, sizeof(*tmp)); 07557 if (!tmp) 07558 res = -1; 07559 else { 07560 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 07561 if (appdata) 07562 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 07563 tmp->chan = chan; 07564 if (synchronous > 1) { 07565 if (locked_channel) 07566 ast_channel_unlock(chan); 07567 ast_pbx_run_app(tmp); 07568 } else { 07569 if (locked_channel) 07570 ast_channel_lock(chan); 07571 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 07572 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 07573 ast_free(tmp); 07574 if (locked_channel) 07575 ast_channel_unlock(chan); 07576 ast_hangup(chan); 07577 res = -1; 07578 } else { 07579 if (locked_channel) 07580 *locked_channel = chan; 07581 } 07582 } 07583 } 07584 } else { 07585 ast_verb(4, "Channel %s was never answered.\n", chan->name); 07586 if (chan->cdr) { /* update the cdr */ 07587 /* here we update the status of the call, which sould be busy. 07588 * if that fails then we set the status to failed */ 07589 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 07590 ast_cdr_failed(chan->cdr); 07591 } 07592 ast_hangup(chan); 07593 } 07594 } 07595 07596 if (res < 0) { /* the call failed for some reason */ 07597 if (*reason == 0) { /* if the call failed (not busy or no answer) 07598 * update the cdr with the failed message */ 07599 cdr_res = ast_pbx_outgoing_cdr_failed(); 07600 if (cdr_res != 0) { 07601 res = cdr_res; 07602 goto outgoing_app_cleanup; 07603 } 07604 } 07605 } 07606 07607 } else { 07608 struct async_stat *as; 07609 if (!(as = ast_calloc(1, sizeof(*as)))) { 07610 res = -1; 07611 goto outgoing_app_cleanup; 07612 } 07613 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07614 if (!chan) { 07615 ast_free(as); 07616 res = -1; 07617 goto outgoing_app_cleanup; 07618 } 07619 as->chan = chan; 07620 ast_copy_string(as->app, app, sizeof(as->app)); 07621 if (appdata) 07622 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 07623 as->timeout = timeout; 07624 ast_set_variables(chan, vars); 07625 if (account) 07626 ast_cdr_setaccount(chan, account); 07627 /* Start a new thread, and get something handling this channel. */ 07628 if (locked_channel) 07629 ast_channel_lock(chan); 07630 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 07631 ast_log(LOG_WARNING, "Failed to start async wait\n"); 07632 ast_free(as); 07633 if (locked_channel) 07634 ast_channel_unlock(chan); 07635 ast_hangup(chan); 07636 res = -1; 07637 goto outgoing_app_cleanup; 07638 } else { 07639 if (locked_channel) 07640 *locked_channel = chan; 07641 } 07642 res = 0; 07643 } 07644 outgoing_app_cleanup: 07645 ast_variables_destroy(vars); 07646 return res; 07647 }
| static int ast_pbx_outgoing_cdr_failed | ( | void | ) | [static] |
Function to post an empty cdr after a spool call fails.
Definition at line 7338 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().
07339 { 07340 /* allocate a channel */ 07341 struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", ""); 07342 07343 if (!chan) 07344 return -1; /* failure */ 07345 07346 if (!chan->cdr) { 07347 /* allocation of the cdr failed */ 07348 ast_channel_free(chan); /* free the channel */ 07349 return -1; /* return failure */ 07350 } 07351 07352 /* allocation of the cdr was successful */ 07353 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 07354 ast_cdr_start(chan->cdr); /* record the start and stop time */ 07355 ast_cdr_end(chan->cdr); 07356 ast_cdr_failed(chan->cdr); /* set the status to failed */ 07357 ast_cdr_detach(chan->cdr); /* post and free the record */ 07358 chan->cdr = NULL; 07359 ast_channel_free(chan); /* free the channel */ 07360 07361 return 0; /* success */ 07362 }
| 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 7364 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().
07365 { 07366 struct ast_channel *chan; 07367 struct async_stat *as; 07368 int res = -1, cdr_res = -1; 07369 struct outgoing_helper oh; 07370 07371 if (synchronous) { 07372 oh.context = context; 07373 oh.exten = exten; 07374 oh.priority = priority; 07375 oh.cid_num = cid_num; 07376 oh.cid_name = cid_name; 07377 oh.account = account; 07378 oh.vars = vars; 07379 oh.parent_channel = NULL; 07380 07381 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07382 if (channel) { 07383 *channel = chan; 07384 if (chan) 07385 ast_channel_lock(chan); 07386 } 07387 if (chan) { 07388 if (chan->_state == AST_STATE_UP) { 07389 res = 0; 07390 ast_verb(4, "Channel %s was answered.\n", chan->name); 07391 07392 if (synchronous > 1) { 07393 if (channel) 07394 ast_channel_unlock(chan); 07395 if (ast_pbx_run(chan)) { 07396 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 07397 if (channel) 07398 *channel = NULL; 07399 ast_hangup(chan); 07400 chan = NULL; 07401 res = -1; 07402 } 07403 } else { 07404 if (ast_pbx_start(chan)) { 07405 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 07406 if (channel) { 07407 *channel = NULL; 07408 ast_channel_unlock(chan); 07409 } 07410 ast_hangup(chan); 07411 res = -1; 07412 } 07413 chan = NULL; 07414 } 07415 } else { 07416 ast_verb(4, "Channel %s was never answered.\n", chan->name); 07417 07418 if (chan->cdr) { /* update the cdr */ 07419 /* here we update the status of the call, which sould be busy. 07420 * if that fails then we set the status to failed */ 07421 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 07422 ast_cdr_failed(chan->cdr); 07423 } 07424 07425 if (channel) { 07426 *channel = NULL; 07427 ast_channel_unlock(chan); 07428 } 07429 ast_hangup(chan); 07430 chan = NULL; 07431 } 07432 } 07433 07434 if (res < 0) { /* the call failed for some reason */ 07435 if (*reason == 0) { /* if the call failed (not busy or no answer) 07436 * update the cdr with the failed message */ 07437 cdr_res = ast_pbx_outgoing_cdr_failed(); 07438 if (cdr_res != 0) { 07439 res = cdr_res; 07440 goto outgoing_exten_cleanup; 07441 } 07442 } 07443 07444 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 07445 /* check if "failed" exists */ 07446 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 07447 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed"); 07448 if (chan) { 07449 char failed_reason[4] = ""; 07450 if (!ast_strlen_zero(context)) 07451 ast_copy_string(chan->context, context, sizeof(chan->context)); 07452 set_ext_pri(chan, "failed", 1); 07453 ast_set_variables(chan, vars); 07454 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 07455 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 07456 if (account) 07457 ast_cdr_setaccount(chan, account); 07458 if (ast_pbx_run(chan)) { 07459 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 07460 ast_hangup(chan); 07461 } 07462 chan = NULL; 07463 } 07464 } 07465 } 07466 } else { 07467 if (!(as = ast_calloc(1, sizeof(*as)))) { 07468 res = -1; 07469 goto outgoing_exten_cleanup; 07470 } 07471 chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name); 07472 if (channel) { 07473 *channel = chan; 07474 if (chan) 07475 ast_channel_lock(chan); 07476 } 07477 if (!chan) { 07478 ast_free(as); 07479 res = -1; 07480 goto outgoing_exten_cleanup; 07481 } 07482 as->chan = chan; 07483 ast_copy_string(as->context, context, sizeof(as->context)); 07484 set_ext_pri(as->chan, exten, priority); 07485 as->timeout = timeout; 07486 ast_set_variables(chan, vars); 07487 if (account) 07488 ast_cdr_setaccount(chan, account); 07489 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 07490 ast_log(LOG_WARNING, "Failed to start async wait\n"); 07491 ast_free(as); 07492 if (channel) { 07493 *channel = NULL; 07494 ast_channel_unlock(chan); 07495 } 07496 ast_hangup(chan); 07497 res = -1; 07498 goto outgoing_exten_cleanup; 07499 } 07500 res = 0; 07501 } 07502 outgoing_exten_cleanup: 07503 ast_variables_destroy(vars); 07504 return res; 07505 }
| 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 4077 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().
04078 { 04079 return ast_pbx_run_args(c, NULL); 04080 }
| static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 7515 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().
07516 { 07517 struct app_tmp *tmp = data; 07518 struct ast_app *app; 07519 app = pbx_findapp(tmp->app); 07520 if (app) { 07521 ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 07522 pbx_exec(tmp->chan, app, tmp->data); 07523 } else 07524 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 07525 ast_hangup(tmp->chan); 07526 ast_free(tmp); 07527 return NULL; 07528 }
| 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 4062 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().
04063 { 04064 enum ast_pbx_result res = AST_PBX_SUCCESS; 04065 04066 if (increase_call_count(c)) { 04067 return AST_PBX_CALL_LIMIT; 04068 } 04069 04070 res = __ast_pbx_run(c, args); 04071 04072 decrease_call_count(); 04073 04074 return res; 04075 }
| 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 4040 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().
04041 { 04042 pthread_t t; 04043 04044 if (!c) { 04045 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 04046 return AST_PBX_FAILED; 04047 } 04048 04049 if (increase_call_count(c)) 04050 return AST_PBX_CALL_LIMIT; 04051 04052 /* Start a new thread, and get something handling this channel. */ 04053 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 04054 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 04055 decrease_call_count(); 04056 return AST_PBX_FAILED; 04057 } 04058 04059 return AST_PBX_SUCCESS; 04060 }
| int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 4087 of file pbx.c.
Referenced by handle_chanlist(), and handle_showcalls().
04088 { 04089 return totalcalls; 04090 }
| 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 8755 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().
08756 { 08757 return ast_rwlock_rdlock(&con->lock); 08758 }
| int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 8737 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().
08738 { 08739 return ast_rwlock_rdlock(&conlock); 08740 }
| 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 4541 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().
04542 { 04543 struct ast_app *tmp, *cur = NULL; 04544 char tmps[80]; 04545 int length, res; 04546 04547 AST_RWLIST_WRLOCK(&apps); 04548 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 04549 if (!(res = strcasecmp(app, tmp->name))) { 04550 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 04551 AST_RWLIST_UNLOCK(&apps); 04552 return -1; 04553 } else if (res < 0) 04554 break; 04555 } 04556 04557 length = sizeof(*tmp) + strlen(app) + 1; 04558 04559 if (!(tmp = ast_calloc(1, length))) { 04560 AST_RWLIST_UNLOCK(&apps); 04561 return -1; 04562 } 04563 04564 strcpy(tmp->name, app); 04565 tmp->execute = execute; 04566 tmp->synopsis = synopsis; 04567 tmp->description = description; 04568 tmp->module = mod; 04569 04570 /* Store in alphabetical order */ 04571 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 04572 if (strcasecmp(tmp->name, cur->name) < 0) { 04573 AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list); 04574 break; 04575 } 04576 } 04577 AST_RWLIST_TRAVERSE_SAFE_END; 04578 if (!cur) 04579 AST_RWLIST_INSERT_TAIL(&apps, tmp, list); 04580 04581 ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 04582 04583 AST_RWLIST_UNLOCK(&apps); 04584 04585 return 0; 04586 }
| 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 4592 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().
04593 { 04594 struct ast_switch *tmp; 04595 04596 AST_RWLIST_WRLOCK(&switches); 04597 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 04598 if (!strcasecmp(tmp->name, sw->name)) { 04599 AST_RWLIST_UNLOCK(&switches); 04600 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 04601 return -1; 04602 } 04603 } 04604 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 04605 AST_RWLIST_UNLOCK(&switches); 04606 04607 return 0; 04608 }
| static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
Remove hint from extension.
Definition at line 3577 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().
03578 { 03579 /* Cleanup the Notifys if hint is removed */ 03580 struct ast_hint *hint; 03581 struct ast_state_cb *cblist; 03582 int res = -1; 03583 03584 if (!e) 03585 return -1; 03586 03587 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) { 03588 if (hint->exten != e) 03589 continue; 03590 03591 while ((cblist = AST_LIST_REMOVE_HEAD(&hint->callbacks, entry))) { 03592 /* Notify with -1 and remove all callbacks */ 03593 cblist->callback(hint->exten->parent->name, hint->exten->exten, 03594 AST_EXTENSION_DEACTIVATED, cblist->data); 03595 ast_free(cblist); 03596 } 03597 03598 AST_RWLIST_REMOVE_CURRENT(list); 03599 ast_free(hint); 03600 03601 res = 0; 03602 03603 break; 03604 } 03605 AST_RWLIST_TRAVERSE_SAFE_END; 03606 03607 return res; 03608 }
| 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 3654 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().
03655 { 03656 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 03657 }
| 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 8760 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().
08761 { 08762 return ast_rwlock_unlock(&con->lock); 08763 }
| int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
| 0 | on success | |
| -1 | on failure |
Definition at line 8742 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().
08743 { 08744 return ast_rwlock_unlock(&conlock); 08745 }
| 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 5835 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().
05836 { 05837 struct ast_app *tmp; 05838 05839 AST_RWLIST_WRLOCK(&apps); 05840 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 05841 if (!strcasecmp(app, tmp->name)) { 05842 unreference_cached_app(tmp); 05843 AST_RWLIST_REMOVE_CURRENT(list); 05844 ast_verb(2, "Unregistered application '%s'\n", tmp->name); 05845 ast_free(tmp); 05846 break; 05847 } 05848 } 05849 AST_RWLIST_TRAVERSE_SAFE_END; 05850 AST_RWLIST_UNLOCK(&apps); 05851 05852 return tmp ? 0 : -1; 05853 }
| void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
| sw | switch to unregister |
Unregisters a switch from asterisk.
Definition at line 4610 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
04611 { 04612 AST_RWLIST_WRLOCK(&switches); 04613 AST_RWLIST_REMOVE(&switches, sw, list); 04614 AST_RWLIST_UNLOCK(&switches); 04615 }
| struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
| struct ast_exten * | exten | |||
| ) | [read] |
Definition at line 8874 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 8907 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().
08909 { 08910 if (!ip) 08911 return con ? con->ignorepats : NULL; 08912 else 08913 return ip->next; 08914 }
| struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
| struct ast_include * | inc | |||
| ) | [read] |
Definition at line 8898 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 8883 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().
08885 { 08886 if (!sw) 08887 return con ? AST_LIST_FIRST(&con->alts) : NULL; 08888 else 08889 return AST_LIST_NEXT(sw, list); 08890 }
| struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 8869 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 8892 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().
08894 { 08895 return priority ? priority->peer : exten; 08896 }
| 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 8750 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().
08751 { 08752 return ast_rwlock_wrlock(&con->lock); 08753 }
| int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 8729 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().
08730 { 08731 int res = ast_rwlock_wrlock(&conlock); 08732 if (!res) 08733 ast_atomic_fetchadd_int(&conlock_wrlock_version, 1); 08734 return res; 08735 }
| int ast_wrlock_contexts_version | ( | void | ) |
Definition at line 8721 of file pbx.c.
References conlock_wrlock_version.
Referenced by ast_merge_contexts_and_delete().
08722 { 08723 return conlock_wrlock_version; 08724 }
| static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 7277 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().
07278 { 07279 struct async_stat *as = data; 07280 struct ast_channel *chan = as->chan; 07281 int timeout = as->timeout; 07282 int res; 07283 struct ast_frame *f; 07284 struct ast_app *app; 07285 07286 while (timeout && (chan->_state != AST_STATE_UP)) { 07287 res = ast_waitfor(chan, timeout); 07288 if (res < 1) 07289 break; 07290 if (timeout > -1) 07291 timeout = res; 07292 f = ast_read(chan); 07293 if (!f) 07294 break; 07295 if (f->frametype == AST_FRAME_CONTROL) { 07296 if ((f->subclass == AST_CONTROL_BUSY) || 07297 (f->subclass == AST_CONTROL_CONGESTION) ) { 07298 ast_frfree(f); 07299 break; 07300 } 07301 } 07302 ast_frfree(f); 07303 } 07304 if (chan->_state == AST_STATE_UP) { 07305 if (!ast_strlen_zero(as->app)) { 07306 app = pbx_findapp(as->app); 07307 if (app) { 07308 ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 07309 pbx_exec(chan, app, as->appdata); 07310 } else 07311 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 07312 } else { 07313 if (!ast_strlen_zero(as->context)) 07314 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 07315 if (!ast_strlen_zero(as->exten)) 07316 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 07317 if (as->priority > 0) 07318 chan->priority = as->priority; 07319 /* Run the PBX */ 07320 if (ast_pbx_run(chan)) { 07321 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 07322 } else { 07323 /* PBX will have taken care of this */ 07324 chan = NULL; 07325 } 07326 } 07327 } 07328 ast_free(as); 07329 if (chan) 07330 ast_hangup(chan); 07331 return NULL; 07332 }
| 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 3673 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().
03674 { 03675 int digit; 03676 03677 buf[pos] = '\0'; /* make sure it is properly terminated */ 03678 while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) { 03679 /* As long as we're willing to wait, and as long as it's not defined, 03680 keep reading digits until we can't possibly get a right answer anymore. */ 03681 digit = ast_waitfordigit(c, waittime); 03682 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 03683 c->_softhangup = 0; 03684 } else { 03685 if (!digit) /* No entry */ 03686 break; 03687 if (digit < 0) /* Error, maybe a hangup */ 03688 return -1; 03689 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 03690 buf[pos++] = digit; 03691 buf[pos] = '\0'; 03692 } 03693 waittime = c->pbx->dtimeoutms; 03694 } 03695 } 03696 return 0; 03697 }
| 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 4770 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().
04771 { 04772 struct ast_hint *hint; 04773 char *ret = NULL; 04774 int which = 0; 04775 int wordlen; 04776 04777 if (pos != 3) 04778 return NULL; 04779 04780 wordlen = strlen(word); 04781 04782 AST_RWLIST_RDLOCK(&hints); 04783 /* walk through all hints */ 04784 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04785 if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) { 04786 ret = ast_strdup(ast_get_extension_name(hint->exten)); 04787 break; 04788 } 04789 } 04790 AST_RWLIST_UNLOCK(&hints); 04791 04792 return ret; 04793 }
| static char* complete_show_dialplan_context | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 4966 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().
04968 { 04969 struct ast_context *c = NULL; 04970 char *ret = NULL; 04971 int which = 0; 04972 int wordlen; 04973 04974 /* we are do completion of [exten@]context on second position only */ 04975 if (pos != 2) 04976 return NULL; 04977 04978 ast_rdlock_contexts(); 04979 04980 wordlen = strlen(word); 04981 04982 /* walk through all contexts and return the n-th match */ 04983 while ( (c = ast_walk_contexts(c)) ) { 04984 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 04985 ret = ast_strdup(ast_get_context_name(c)); 04986 break; 04987 } 04988 } 04989 04990 ast_unlock_contexts(); 04991 04992 return ret; 04993 }
| static void context_merge | ( | struct ast_context ** | extcontexts, | |
| struct ast_hashtab * | exttable, | |||
| struct ast_context * | context, | |||
| const char * | registrar | |||
| ) | [static] |
Definition at line 5970 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().
05971 { 05972 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */ 05973 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item; 05974 struct ast_hashtab_iter *exten_iter; 05975 struct ast_hashtab_iter *prio_iter; 05976 int insert_count = 0; 05977 int first = 1; 05978 05979 /* We'll traverse all the extensions/prios, and see which are not registrar'd with 05980 the current registrar, and copy them to the new context. If the new context does not 05981 exist, we'll create it "on demand". If no items are in this context to copy, then we'll 05982 only create the empty matching context if the old one meets the criteria */ 05983 05984 if (context->root_table) { 05985 exten_iter = ast_hashtab_start_traversal(context->root_table); 05986 while ((exten_item=ast_hashtab_next(exten_iter))) { 05987 if (new) { 05988 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item); 05989 } else { 05990 new_exten_item = NULL; 05991 } 05992 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 05993 while ((prio_item=ast_hashtab_next(prio_iter))) { 05994 int res1; 05995 char *dupdstr; 05996 05997 if (new_exten_item) { 05998 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item); 05999 } else { 06000 new_prio_item = NULL; 06001 } 06002 if (strcmp(prio_item->registrar,registrar) == 0) { 06003 continue; 06004 } 06005 /* make sure the new context exists, so we have somewhere to stick this exten/prio */ 06006 if (!new) { 06007 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 */ 06008 } 06009 06010 /* copy in the includes, switches, and ignorepats */ 06011 if (first) { /* but, only need to do this once */ 06012 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 06013 first = 0; 06014 } 06015 06016 if (!new) { 06017 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name); 06018 return; /* no sense continuing. */ 06019 } 06020 /* we will not replace existing entries in the new context with stuff from the old context. 06021 but, if this is because of some sort of registrar conflict, we ought to say something... */ 06022 06023 dupdstr = ast_strdup(prio_item->data); 06024 06025 res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 06026 prio_item->cidmatch, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar); 06027 if (!res1 && new_exten_item && new_prio_item){ 06028 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n", 06029 context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar); 06030 } else { 06031 /* 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, 06032 and no double frees take place, either! */ 06033 insert_count++; 06034 } 06035 } 06036 ast_hashtab_end_traversal(prio_iter); 06037 } 06038 ast_hashtab_end_traversal(exten_iter); 06039 } 06040 06041 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 || 06042 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) { 06043 /* we could have given it the registrar of the other module who incremented the refcount, 06044 but that's not available, so we give it the registrar we know about */ 06045 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar); 06046 06047 /* copy in the includes, switches, and ignorepats */ 06048 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 06049 } 06050 }
| static void context_merge_incls_swits_igps_other_registrars | ( | struct ast_context * | new, | |
| struct ast_context * | old, | |||
| const char * | registrar | |||
| ) | [static] |
Definition at line 5937 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().
05938 { 05939 struct ast_include *i; 05940 struct ast_ignorepat *ip; 05941 struct ast_sw *sw; 05942 05943 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); 05944 /* copy in the includes, switches, and ignorepats */ 05945 /* walk through includes */ 05946 for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) { 05947 if (strcmp(ast_get_include_registrar(i), registrar) == 0) 05948 continue; /* not mine */ 05949 ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i)); 05950 } 05951 05952 /* walk through switches */ 05953 for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) { 05954 if (strcmp(ast_get_switch_registrar(sw), registrar) == 0) 05955 continue; /* not mine */ 05956 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)); 05957 } 05958 05959 /* walk thru ignorepats ... */ 05960 for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) { 05961 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) 05962 continue; /* not mine */ 05963 ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip)); 05964 } 05965 }
| 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 3998 of file pbx.c.
References ast_mutex_lock(), and ast_mutex_unlock().
Referenced by ast_pbx_run_args(), ast_pbx_start(), and pbx_thread().
03999 { 04000 ast_mutex_lock(&maxcalllock); 04001 if (countcalls > 0) 04002 countcalls--; 04003 ast_mutex_unlock(&maxcalllock); 04004 }
| static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 4006 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().
04007 { 04008 if (e->priority == PRIORITY_HINT) 04009 ast_remove_hint(e); 04010 04011 if (e->peer_table) 04012 ast_hashtab_destroy(e->peer_table,0); 04013 if (e->peer_label_table) 04014 ast_hashtab_destroy(e->peer_label_table, 0); 04015 if (e->datad) 04016 e->datad(e->data); 04017 ast_free(e); 04018 }
| 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 8667 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().
08668 { 08669 const char *device; 08670 struct statechange *sc; 08671 08672 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 08673 if (ast_strlen_zero(device)) { 08674 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n"); 08675 return; 08676 } 08677 08678 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1))) 08679 return; 08680 strcpy(sc->dev, device); 08681 if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) { 08682 ast_free(sc); 08683 } 08684 }
| static void exception_store_free | ( | void * | data | ) | [static] |
Definition at line 2567 of file pbx.c.
References ast_free, and ast_string_field_free_memory.
02568 { 02569 struct pbx_exception *exception = data; 02570 ast_string_field_free_memory(exception); 02571 ast_free(exception); 02572 }
| static int ext_cmp | ( | const char * | a, | |
| const char * | b | |||
| ) | [static] |
the full routine to compare extensions in rules.
Definition at line 1768 of file pbx.c.
References ext_cmp1().
Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().
01769 { 01770 /* make sure non-patterns come first. 01771 * If a is not a pattern, it either comes first or 01772 * we use strcmp to compare the strings. 01773 */ 01774 int ret = 0; 01775 01776 if (a[0] != '_') 01777 return (b[0] == '_') ? -1 : strcmp(a, b); 01778 01779 /* Now we know a is a pattern; if b is not, a comes first */ 01780 if (b[0] != '_') 01781 return 1; 01782 #if 0 /* old mode for ext matching */ 01783 return strcmp(a, b); 01784 #endif 01785 /* ok we need full pattern sorting routine */ 01786 while (!ret && a && b) 01787 ret = ext_cmp1(&a) - ext_cmp1(&b); 01788 if (ret == 0) 01789 return 0; 01790 else 01791 return (ret > 0) ? 1 : -1; 01792 }
| static int ext_cmp1 | ( | const char ** | p | ) | [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 uint32_t chars[8]; 01700 int c, cmin = 0xff, count = 0; 01701 const char *end; 01702 01703 /* load, sign extend and advance pointer until we find 01704 * a valid character. 01705 */ 01706 c = *(*p)++; 01707 01708 /* always return unless we have a set of chars */ 01709 switch (toupper(c)) { 01710 default: /* ordinary character */ 01711 return 0x0000 | (c & 0xff); 01712 01713 case 'N': /* 2..9 */ 01714 return 0x0800 | '2' ; 01715 01716 case 'X': /* 0..9 */ 01717 return 0x0A00 | '0'; 01718 01719 case 'Z': /* 1..9 */ 01720 return 0x0900 | '1'; 01721 01722 case '.': /* wildcard */ 01723 return 0x10000; 01724 01725 case '!': /* earlymatch */ 01726 return 0x20000; /* less specific than NULL */ 01727 01728 case '\0': /* empty string */ 01729 *p = NULL; 01730 return 0x30000; 01731 01732 case '[': /* pattern */ 01733 break; 01734 } 01735 /* locate end of set */ 01736 end = strchr(*p, ']'); 01737 01738 if (end == NULL) { 01739 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 01740 return 0x40000; /* XXX make this entry go last... */ 01741 } 01742 01743 memset(chars, '\0', sizeof(chars)); /* clear all chars in the set */ 01744 for (; *p < end ; (*p)++) { 01745 unsigned char c1, c2; /* first-last char in range */ 01746 c1 = (unsigned char)((*p)[0]); 01747 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 01748 c2 = (unsigned char)((*p)[2]); 01749 *p += 2; /* skip a total of 3 chars */ 01750 } else /* individual character */ 01751 c2 = c1; 01752 if (c1 < cmin) 01753 cmin = c1; 01754 for (; c1 <= c2; c1++) { 01755 uint32_t mask = 1 << (c1 % 32); 01756 if ( (chars[ c1 / 32 ] & mask) == 0) 01757 count += 0x100; 01758 chars[ c1 / 32 ] |= mask; 01759 } 01760 } 01761 (*p)++; 01762 return count == 0 ? 0x30000 : (count | cmin); 01763 }
| static int ext_strncpy | ( | char * | dst, | |
| const char * | src, | |||
| int | len | |||
| ) | [static] |
copy a string skipping whitespace
Definition at line 6838 of file pbx.c.
Referenced by ast_add_extension2_lockopt().
06839 { 06840 int count = 0; 06841 06842 while (*src && (count < len - 1)) { 06843 switch (*src) { 06844 case ' ': 06845 /* otherwise exten => [a-b],1,... doesn't work */ 06846 /* case '-': */ 06847 /* Ignore */ 06848 break; 06849 default: 06850 *dst = *src; 06851 dst++; 06852 } 06853 src++; 06854 count++; 06855 } 06856 *dst = '\0'; 06857 06858 return count; 06859 }
| static int extension_match_core | ( | const char * | pattern, | |
| const char * | data, | |||
| enum ext_match_t | mode | |||
| ) | [static] |
Definition at line 1975 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().
01976 { 01977 int i; 01978 static int prof_id = -2; /* marker for 'unallocated' id */ 01979 if (prof_id == -2) 01980 prof_id = ast_add_profile("ext_match", 0); 01981 ast_mark(prof_id, 1); 01982 i = _extension_match_core(pattern, data, mode); 01983 ast_mark(prof_id, 0); 01984 return i; 01985 }
| 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 4122 of file pbx.c.
References ast_copy_string(), and ast_hashtab_lookup().
Referenced by ast_add_extension_nolock().
04123 { 04124 struct ast_context *c = NULL; 04125 struct fake_context item; 04126 04127 ast_copy_string(item.name, context, sizeof(item.name)); 04128 04129 c = ast_hashtab_lookup(contexts_table,&item); 04130 04131 return c; 04132 }
| 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 4139 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().
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 ast_rdlock_contexts(); 04147 c = ast_hashtab_lookup(contexts_table,&item); 04148 04149 #ifdef NOTNOW 04150 04151 while ( (c = ast_walk_contexts(c)) ) { 04152 if (!strcmp(ast_get_context_name(c), context)) 04153 return c; 04154 } 04155 #endif 04156 if (!c) 04157 ast_unlock_contexts(); 04158 04159 return c; 04160 }
| 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 2836 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), and ast_func_write().
02837 { 02838 char *args = strchr(function, '('); 02839 02840 if (!args) 02841 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n"); 02842 else { 02843 char *p; 02844 *args++ = '\0'; 02845 if ((p = strrchr(args, ')')) ) 02846 *p = '\0'; 02847 else 02848 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n"); 02849 } 02850 return args; 02851 }
| 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 6232 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and s.
Referenced by ast_build_timing().
06233 { 06234 int s, e; /* start and ending position */ 06235 unsigned int mask = 0; 06236 06237 /* Check for whole range */ 06238 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 06239 s = 0; 06240 e = max - 1; 06241 } else { 06242 /* Get start and ending position */ 06243 char *c = strchr(src, '-'); 06244 if (c) 06245 *c++ = '\0'; 06246 /* Find the start */ 06247 s = lookup_name(src, names, max); 06248 if (!s) { 06249 ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src); 06250 return 0; 06251 } 06252 s--; 06253 if (c) { /* find end of range */ 06254 e = lookup_name(c, names, max); 06255 if (!e) { 06256 ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c); 06257 return 0; 06258 } 06259 e--; 06260 } else 06261 e = s; 06262 } 06263 /* Fill the mask. Remember that ranges are cyclic */ 06264 mask = 1 << e; /* initialize with last element */ 06265 while (s != e) { 06266 if (s >= max) { 06267 s = 0; 06268 mask |= (1 << s); 06269 } else { 06270 mask |= (1 << s); 06271 s++; 06272 } 06273 } 06274 return mask; 06275 }
| 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 6278 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
06279 { 06280 char *e; 06281 int x; 06282 int s1, s2; 06283 int e1, e2; 06284 /* int cth, ctm; */ 06285 06286 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 06287 memset(i->minmask, 0, sizeof(i->minmask)); 06288 06289 /* 2-minutes per bit, since the mask has only 32 bits :( */ 06290 /* Star is all times */ 06291 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 06292 for (x = 0; x < 24; x++) 06293 i->minmask[x] = 0x3fffffff; /* 30 bits */ 06294 return; 06295 } 06296 /* Otherwise expect a range */ 06297 e = strchr(times, '-'); 06298 if (!e) { 06299 ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n"); 06300 return; 06301 } 06302 *e++ = '\0'; 06303 /* XXX why skip non digits ? */ 06304 while (*e && !isdigit(*e)) 06305 e++; 06306 if (!*e) { 06307 ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n"); 06308 return; 06309 } 06310 if (sscanf(times, "%2d:%2d", &s1, &s2) != 2) { 06311 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times); 06312 return; 06313 } 06314 if (sscanf(e, "%2d:%2d", &e1, &e2) != 2) { 06315 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e); 06316 return; 06317 } 06318 /* XXX this needs to be optimized */ 06319 #if 1 06320 s1 = s1 * 30 + s2/2; 06321 if ((s1 < 0) || (s1 >= 24*30)) { 06322 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times); 06323 return; 06324 } 06325 e1 = e1 * 30 + e2/2; 06326 if ((e1 < 0) || (e1 >= 24*30)) { 06327 ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e); 06328 return; 06329 } 06330 /* Go through the time and enable each appropriate bit */ 06331 for (x=s1;x != e1;x = (x + 1) % (24 * 30)) { 06332 i->minmask[x/30] |= (1 << (x % 30)); 06333 } 06334 /* Do the last one */ 06335 i->minmask[x/30] |= (1 << (x % 30)); 06336 #else 06337 for (cth = 0; cth < 24; cth++) { 06338 /* Initialize masks to blank */ 06339 i->minmask[cth] = 0; 06340 for (ctm = 0; ctm < 30; ctm++) { 06341 if ( 06342 /* First hour with more than one hour */ 06343 (((cth == s1) && (ctm >= s2)) && 06344 ((cth < e1))) 06345 /* Only one hour */ 06346 || (((cth == s1) && (ctm >= s2)) && 06347 ((cth == e1) && (ctm <= e2))) 06348 /* In between first and last hours (more than 2 hours) */ 06349 || ((cth > s1) && 06350 (cth < e1)) 06351 /* Last hour with more than one hour */ 06352 || ((cth > s1) && 06353 ((cth == e1) && (ctm <= e2))) 06354 ) 06355 i->minmask[cth] |= (1 << (ctm / 2)); 06356 } 06357 } 06358 #endif 06359 /* All done */ 06360 return; 06361 }
| static char* handle_debug_dialplan | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Send ack once.
Definition at line 5291 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.
05292 { 05293 char *exten = NULL, *context = NULL; 05294 /* Variables used for different counters */ 05295 struct dialplan_counters counters; 05296 const char *incstack[AST_PBX_MAX_STACK]; 05297 05298 switch (cmd) { 05299 case CLI_INIT: 05300 e->command = "dialplan debug"; 05301 e->usage = 05302 "Usage: dialplan debug [context]\n" 05303 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n"; 05304 return NULL; 05305 case CLI_GENERATE: 05306 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 05307 } 05308 05309 memset(&counters, 0, sizeof(counters)); 05310 05311 if (a->argc != 2 && a->argc != 3) 05312 return CLI_SHOWUSAGE; 05313 05314 /* we obtain [exten@]context? if yes, split them ... */ 05315 /* note: we ignore the exten totally here .... */ 05316 if (a->argc == 3) { 05317 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 05318 context = ast_strdupa(a->argv[2]); 05319 exten = strsep(&context, "@"); 05320 /* change empty strings to NULL */ 05321 if (ast_strlen_zero(exten)) 05322 exten = NULL; 05323 } else { /* no '@' char, only context given */ 05324 context = a->argv[2]; 05325 } 05326 if (ast_strlen_zero(context)) 05327 context = NULL; 05328 } 05329 /* else Show complete dial plan, context and exten are NULL */ 05330 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 05331 05332 /* check for input failure and throw some error messages */ 05333 if (context && !counters.context_existence) { 05334 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 05335 return CLI_FAILURE; 05336 } 05337 05338 05339 ast_cli(a->fd,"-= %d %s. =-\n", 05340 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 05341 05342 /* everything ok */ 05343 return CLI_SUCCESS; 05344 }
| static char* handle_set_chanvar | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5685 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().
05686 { 05687 struct ast_channel *chan; 05688 const char *chan_name, *var_name, *var_value; 05689 05690 switch (cmd) { 05691 case CLI_INIT: 05692 e->command = "dialplan set chanvar"; 05693 e->usage = 05694 "Usage: dialplan set chanvar <channel> <varname> <value>\n" 05695 " Set channel variable <varname> to <value>\n"; 05696 return NULL; 05697 case CLI_GENERATE: 05698 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 05699 } 05700 05701 if (a->argc != e->args + 3) 05702 return CLI_SHOWUSAGE; 05703 05704 chan_name = a->argv[e->args]; 05705 var_name = a->argv[e->args + 1]; 05706 var_value = a->argv[e->args + 2]; 05707 05708 if (!(chan = ast_get_channel_by_name_locked(chan_name))) { 05709 ast_cli(a->fd, "Channel '%s' not found\n", chan_name); 05710 return CLI_FAILURE; 05711 } 05712 05713 pbx_builtin_setvar_helper(chan, var_name, var_value); 05714 ast_channel_unlock(chan); 05715 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name); 05716 05717 return CLI_SUCCESS; 05718 }
| static char* handle_set_chanvar_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5720 of file pbx.c.
References CLI_INIT, ast_cli_entry::command, and handle_set_chanvar().
05721 { 05722 char *res = handle_set_chanvar(e, cmd, a); 05723 if (cmd == CLI_INIT) 05724 e->command = "core set chanvar"; 05725 return res; 05726 }
| static char* handle_set_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5728 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.
05729 { 05730 int oldval = 0; 05731 05732 switch (cmd) { 05733 case CLI_INIT: 05734 e->command = "dialplan set extenpatternmatchnew true"; 05735 e->usage = 05736 "Usage: dialplan set extenpatternmatchnew true|false\n" 05737 " Use the NEW extension pattern matching algorithm, true or false.\n"; 05738 return NULL; 05739 case CLI_GENERATE: 05740 return NULL; 05741 } 05742 05743 if (a->argc != 4) 05744 return CLI_SHOWUSAGE; 05745 05746 oldval = pbx_set_extenpatternmatchnew(1); 05747 05748 if (oldval) 05749 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n"); 05750 else 05751 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n"); 05752 05753 return CLI_SUCCESS; 05754 }
| static char* handle_set_global | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5655 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().
05656 { 05657 switch (cmd) { 05658 case CLI_INIT: 05659 e->command = "dialplan set global"; 05660 e->usage = 05661 "Usage: dialplan set global <name> <value>\n" 05662 " Set global dialplan variable <name> to <value>\n"; 05663 return NULL; 05664 case CLI_GENERATE: 05665 return NULL; 05666 } 05667 05668 if (a->argc != e->args + 2) 05669 return CLI_SHOWUSAGE; 05670 05671 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]); 05672 ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]); 05673 05674 return CLI_SUCCESS; 05675 }
| static char* handle_set_global_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5677 of file pbx.c.
References CLI_INIT, ast_cli_entry::command, and handle_set_global().
05678 { 05679 char *res = handle_set_global(e, cmd, a); 05680 if (cmd == CLI_INIT) 05681 e->command = "core set global"; 05682 return res; 05683 }
| static char* handle_show_application | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4624 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.
04625 { 04626 struct ast_app *aa; 04627 int app, no_registered_app = 1; 04628 char *ret = NULL; 04629 int which = 0; 04630 int wordlen; 04631 04632 switch (cmd) { 04633 case CLI_INIT: 04634 e->command = "core show application"; 04635 e->usage = 04636 "Usage: core show application <application> [<application> [<application> [...]]]\n" 04637 " Describes a particular application.\n"; 04638 return NULL; 04639 case CLI_GENERATE: 04640 /* 04641 * There is a possibility to show informations about more than one 04642 * application at one time. You can type 'show application Dial Echo' and 04643 * you will see informations about these two applications ... 04644 */ 04645 wordlen = strlen(a->word); 04646 /* return the n-th [partial] matching entry */ 04647 AST_RWLIST_RDLOCK(&apps); 04648 AST_RWLIST_TRAVERSE(&apps, aa, list) { 04649 if (!strncasecmp(a->word, aa->name, wordlen) && ++which > a->n) { 04650 ret = ast_strdup(aa->name); 04651 break; 04652 } 04653 } 04654 AST_RWLIST_UNLOCK(&apps); 04655 04656 return ret; 04657 } 04658 04659 if (a->argc < 4) 04660 return CLI_SHOWUSAGE; 04661 04662 /* ... go through all applications ... */ 04663 AST_RWLIST_RDLOCK(&apps); 04664 AST_RWLIST_TRAVERSE(&apps, aa, list) { 04665 /* ... compare this application name with all arguments given 04666 * to 'show application' command ... */ 04667 for (app = 3; app < a->argc; app++) { 04668 if (!strcasecmp(aa->name, a->argv[app])) { 04669 /* Maximum number of characters added by terminal coloring is 22 */ 04670 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 04671 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 04672 int synopsis_size, description_size; 04673 04674 no_registered_app = 0; 04675 04676 if (aa->synopsis) 04677 synopsis_size = strlen(aa->synopsis) + 23; 04678 else 04679 synopsis_size = strlen("Not available") + 23; 04680 synopsis = alloca(synopsis_size); 04681 04682 if (aa->description) 04683 description_size = strlen(aa->description) + 23; 04684 else 04685 description_size = strlen("Not available") + 23; 04686 description = alloca(description_size); 04687 04688 if (synopsis && description) { 04689 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", aa->name); 04690 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 04691 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 04692 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 04693 term_color(synopsis, 04694 aa->synopsis ? aa->synopsis : "Not available", 04695 COLOR_CYAN, 0, synopsis_size); 04696 term_color(description, 04697 aa->description ? aa->description : "Not available", 04698 COLOR_CYAN, 0, description_size); 04699 04700 ast_cli(a->fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 04701 } else { 04702 /* ... one of our applications, show info ...*/ 04703 ast_cli(a->fd,"\n -= Info about application '%s' =- \n\n" 04704 "[Synopsis]\n %s\n\n" 04705 "[Description]\n%s\n", 04706 aa->name, 04707 aa->synopsis ? aa->synopsis : "Not available", 04708 aa->description ? aa->description : "Not available"); 04709 } 04710 } 04711 } 04712 } 04713 AST_RWLIST_UNLOCK(&apps); 04714 04715 /* we found at least one app? no? */ 04716 if (no_registered_app) { 04717 ast_cli(a->fd, "Your application(s) is (are) not registered\n"); 04718 return CLI_FAILURE; 04719 } 04720 04721 return CLI_SUCCESS; 04722 }
| static char* handle_show_applications | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4880 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.
04881 { 04882 struct ast_app *aa; 04883 int like = 0, describing = 0; 04884 int total_match = 0; /* Number of matches in like clause */ 04885 int total_apps = 0; /* Number of apps registered */ 04886 static char* choices[] = { "like", "describing", NULL }; 04887 04888 switch (cmd) { 04889 case CLI_INIT: 04890 e->command = "core show applications [like|describing]"; 04891 e->usage = 04892 "Usage: core show applications [{like|describing} <text>]\n" 04893 " List applications which are currently available.\n" 04894 " If 'like', <text> will be a substring of the app name\n" 04895 " If 'describing', <text> will be a substring of the description\n"; 04896 return NULL; 04897 case CLI_GENERATE: 04898 return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n); 04899 } 04900 04901 AST_RWLIST_RDLOCK(&apps); 04902 04903 if (AST_RWLIST_EMPTY(&apps)) { 04904 ast_cli(a->fd, "There are no registered applications\n"); 04905 AST_RWLIST_UNLOCK(&apps); 04906 return CLI_SUCCESS; 04907 } 04908 04909 /* core list applications like <keyword> */ 04910 if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) { 04911 like = 1; 04912 } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) { 04913 describing = 1; 04914 } 04915 04916 /* core list applications describing <keyword1> [<keyword2>] [...] */ 04917 if ((!like) && (!describing)) { 04918 ast_cli(a->fd, " -= Registered Asterisk Applications =-\n"); 04919 } else { 04920 ast_cli(a->fd, " -= Matching Asterisk Applications =-\n"); 04921 } 04922 04923 AST_RWLIST_TRAVERSE(&apps, aa, list) { 04924 int printapp = 0; 04925 total_apps++; 04926 if (like) { 04927 if (strcasestr(aa->name, a->argv[4])) { 04928 printapp = 1; 04929 total_match++; 04930 } 04931 } else if (describing) { 04932 if (aa->description) { 04933 /* Match all words on command line */ 04934 int i; 04935 printapp = 1; 04936 for (i = 4; i < a->argc; i++) { 04937 if (!strcasestr(aa->description, a->argv[i])) { 04938 printapp = 0; 04939 } else { 04940 total_match++; 04941 } 04942 } 04943 } 04944 } else { 04945 printapp = 1; 04946 } 04947 04948 if (printapp) { 04949 ast_cli(a->fd," %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>"); 04950 } 04951 } 04952 if ((!like) && (!describing)) { 04953 ast_cli(a->fd, " -= %d Applications Registered =-\n",total_apps); 04954 } else { 04955 ast_cli(a->fd, " -= %d Applications Matching =-\n",total_match); 04956 } 04957 04958 AST_RWLIST_UNLOCK(&apps); 04959 04960 return CLI_SUCCESS; 04961 }
| 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 5623 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.
05624 { 05625 struct ast_channel *chan = NULL; 05626 struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */ 05627 05628 switch (cmd) { 05629 case CLI_INIT: 05630 e->command = "dialplan show chanvar"; 05631 e->usage = 05632 "Usage: dialplan show chanvar <channel>\n" 05633 " List current channel variables and their values\n"; 05634 return NULL; 05635 case CLI_GENERATE: 05636 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 05637 } 05638 05639 if (a->argc != e->args + 1) 05640 return CLI_SHOWUSAGE; 05641 05642 if (!(chan = ast_get_channel_by_name_locked(a->argv[e->args]))) { 05643 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]); 05644 return CLI_FAILURE; 05645 } 05646 05647 pbx_builtin_serialize_variables(chan, &vars); 05648 if (vars->str) { 05649 ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], vars->str); 05650 } 05651 ast_channel_unlock(chan); 05652 return CLI_SUCCESS; 05653 }
| static char* handle_show_dialplan | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5224 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.
05225 { 05226 char *exten = NULL, *context = NULL; 05227 /* Variables used for different counters */ 05228 struct dialplan_counters counters; 05229 const char *incstack[AST_PBX_MAX_STACK]; 05230 05231 switch (cmd) { 05232 case CLI_INIT: 05233 e->command = "dialplan show"; 05234 e->usage = 05235 "Usage: dialplan show [[exten@]context]\n" 05236 " Show dialplan\n"; 05237 return NULL; 05238 case CLI_GENERATE: 05239 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 05240 } 05241 05242 memset(&counters, 0, sizeof(counters)); 05243 05244 if (a->argc != 2 && a->argc != 3) 05245 return CLI_SHOWUSAGE; 05246 05247 /* we obtain [exten@]context? if yes, split them ... */ 05248 if (a->argc == 3) { 05249 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 05250 context = ast_strdupa(a->argv[2]); 05251 exten = strsep(&context, "@"); 05252 /* change empty strings to NULL */ 05253 if (ast_strlen_zero(exten)) 05254 exten = NULL; 05255 } else { /* no '@' char, only context given */ 05256 context = a->argv[2]; 05257 } 05258 if (ast_strlen_zero(context)) 05259 context = NULL; 05260 } 05261 /* else Show complete dial plan, context and exten are NULL */ 05262 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 05263 05264 /* check for input failure and throw some error messages */ 05265 if (context && !counters.context_existence) { 05266 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 05267 return CLI_FAILURE; 05268 } 05269 05270 if (exten && !counters.extension_existence) { 05271 if (context) 05272 ast_cli(a->fd, "There is no existence of %s@%s extension\n", 05273 exten, context); 05274 else 05275 ast_cli(a->fd, 05276 "There is no existence of '%s' extension in all contexts\n", 05277 exten); 05278 return CLI_FAILURE; 05279 } 05280 05281 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n", 05282 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 05283 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 05284 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 05285 05286 /* everything ok */ 05287 return CLI_SUCCESS; 05288 }
| static char* handle_show_function | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2685 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.
02686 { 02687 struct ast_custom_function *acf; 02688 /* Maximum number of characters added by terminal coloring is 22 */ 02689 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 02690 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 02691 char stxtitle[40], *syntax = NULL; 02692 int synopsis_size, description_size, syntax_size; 02693 char *ret = NULL; 02694 int which = 0; 02695 int wordlen; 02696 02697 switch (cmd) { 02698 case CLI_INIT: 02699 e->command = "core show function"; 02700 e->usage = 02701 "Usage: core show function <function>\n" 02702 " Describe a particular dialplan function.\n"; 02703 return NULL; 02704 case CLI_GENERATE: 02705 wordlen = strlen(a->word); 02706 /* case-insensitive for convenience in this 'complete' function */ 02707 AST_RWLIST_RDLOCK(&acf_root); 02708 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 02709 if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) { 02710 ret = ast_strdup(acf->name); 02711 break; 02712 } 02713 } 02714 AST_RWLIST_UNLOCK(&acf_root); 02715 02716 return ret; 02717 } 02718 02719 if (a->argc < 4) 02720 return CLI_SHOWUSAGE; 02721 02722 if (!(acf = ast_custom_function_find(a->argv[3]))) { 02723 ast_cli(a->fd, "No function by that name registered.\n"); 02724 return CLI_FAILURE; 02725 02726 } 02727 02728 if (acf->synopsis) 02729 synopsis_size = strlen(acf->synopsis) + 23; 02730 else 02731 synopsis_size = strlen("Not available") + 23; 02732 synopsis = alloca(synopsis_size); 02733 02734 if (acf->desc) 02735 description_size = strlen(acf->desc) + 23; 02736 else 02737 description_size = strlen("Not available") + 23; 02738 description = alloca(description_size); 02739 02740 if (acf->syntax) 02741 syntax_size = strlen(acf->syntax) + 23; 02742 else 02743 syntax_size = strlen("Not available") + 23; 02744 syntax = alloca(syntax_size); 02745 02746 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name); 02747 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 02748 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 02749 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 02750 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 02751 term_color(syntax, 02752 acf->syntax ? acf->syntax : "Not available", 02753 COLOR_CYAN, 0, syntax_size); 02754 term_color(synopsis, 02755 acf->synopsis ? acf->synopsis : "Not available", 02756 COLOR_CYAN, 0, synopsis_size); 02757 term_color(description, 02758 acf->desc ? acf->desc : "Not available", 02759 COLOR_CYAN, 0, description_size); 02760 02761 ast_cli(a->fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description); 02762 02763 return CLI_SUCCESS; 02764 }
| static char* handle_show_functions | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2646 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.
02647 { 02648 struct ast_custom_function *acf; 02649 int count_acf = 0; 02650 int like = 0; 02651 02652 switch (cmd) { 02653 case CLI_INIT: 02654 e->command = "core show functions [like]"; 02655 e->usage = 02656 "Usage: core show functions [like <text>]\n" 02657 " List builtin functions, optionally only those matching a given string\n"; 02658 return NULL; 02659 case CLI_GENERATE: 02660 return NULL; 02661 } 02662 02663 if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) { 02664 like = 1; 02665 } else if (a->argc != 3) { 02666 return CLI_SHOWUSAGE; 02667 } 02668 02669 ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 02670 02671 AST_RWLIST_RDLOCK(&acf_root); 02672 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 02673 if (!like || strstr(acf->name, a->argv[4])) { 02674 count_acf++; 02675 ast_cli(a->fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis); 02676 } 02677 } 02678 AST_RWLIST_UNLOCK(&acf_root); 02679 02680 ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 02681 02682 return CLI_SUCCESS; 02683 }
| 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 5556 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().
05557 { 05558 int i = 0; 05559 struct ast_var_t *newvariable; 05560 05561 switch (cmd) { 05562 case CLI_INIT: 05563 e->command = "dialplan show globals"; 05564 e->usage = 05565 "Usage: dialplan show globals\n" 05566 " List current global dialplan variables and their values\n"; 05567 return NULL; 05568 case CLI_GENERATE: 05569 return NULL; 05570 } 05571 05572 ast_rwlock_rdlock(&globalslock); 05573 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 05574 i++; 05575 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 05576 } 05577 ast_rwlock_unlock(&globalslock); 05578 ast_cli(a->fd, "\n -- %d variable(s)\n", i); 05579 05580 return CLI_SUCCESS; 05581 }
| static char* handle_show_globals_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5583 of file pbx.c.
References CLI_INIT, ast_cli_entry::command, and handle_show_globals().
05584 { 05585 05586 char *res = handle_show_globals(e, cmd, a); 05587 if (cmd == CLI_INIT) 05588 e->command = "core show globals"; 05589 return res; 05590 }
| 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 4796 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.
04797 { 04798 struct ast_hint *hint; 04799 int watchers; 04800 int num = 0, extenlen; 04801 struct ast_state_cb *watcher; 04802 04803 switch (cmd) { 04804 case CLI_INIT: 04805 e->command = "core show hint"; 04806 e->usage = 04807 "Usage: core show hint <exten>\n" 04808 " List registered hint\n"; 04809 return NULL; 04810 case CLI_GENERATE: 04811 return complete_core_show_hint(a->line, a->word, a->pos, a->n); 04812 } 04813 04814 if (a->argc < 4) 04815 return CLI_SHOWUSAGE; 04816 04817 AST_RWLIST_RDLOCK(&hints); 04818 if (AST_RWLIST_EMPTY(&hints)) { 04819 ast_cli(a->fd, "There are no registered dialplan hints\n"); 04820 AST_RWLIST_UNLOCK(&hints); 04821 return CLI_SUCCESS; 04822 } 04823 extenlen = strlen(a->argv[3]); 04824 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04825 if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) { 04826 watchers = 0; 04827 AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) { 04828 watchers++; 04829 } 04830 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 04831 ast_get_extension_name(hint->exten), 04832 ast_get_context_name(ast_get_extension_context(hint->exten)), 04833 ast_get_extension_app(hint->exten), 04834 ast_extension_state2str(hint->laststate), watchers); 04835 num++; 04836 } 04837 } 04838 AST_RWLIST_UNLOCK(&hints); 04839 if (!num) 04840 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]); 04841 else 04842 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]); 04843 return CLI_SUCCESS; 04844 }
| 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 4725 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.
04726 { 04727 struct ast_hint *hint; 04728 int num = 0; 04729 int watchers; 04730 struct ast_state_cb *watcher; 04731 04732 switch (cmd) { 04733 case CLI_INIT: 04734 e->command = "core show hints"; 04735 e->usage = 04736 "Usage: core show hints\n" 04737 " List registered hints\n"; 04738 return NULL; 04739 case CLI_GENERATE: 04740 return NULL; 04741 } 04742 04743 AST_RWLIST_RDLOCK(&hints); 04744 if (AST_RWLIST_EMPTY(&hints)) { 04745 ast_cli(a->fd, "There are no registered dialplan hints\n"); 04746 AST_RWLIST_UNLOCK(&hints); 04747 return CLI_SUCCESS; 04748 } 04749 /* ... we have hints ... */ 04750 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 04751 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04752 watchers = 0; 04753 AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) { 04754 watchers++; 04755 } 04756 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 04757 ast_get_extension_name(hint->exten), 04758 ast_get_context_name(ast_get_extension_context(hint->exten)), 04759 ast_get_extension_app(hint->exten), 04760 ast_extension_state2str(hint->laststate), watchers); 04761 num++; 04762 } 04763 ast_cli(a->fd, "----------------\n"); 04764 ast_cli(a->fd, "- %d hints registered\n", num); 04765 AST_RWLIST_UNLOCK(&hints); 04766 return CLI_SUCCESS; 04767 }
| 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 4848 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.
04849 { 04850 struct ast_switch *sw; 04851 04852 switch (cmd) { 04853 case CLI_INIT: 04854 e->command = "core show switches"; 04855 e->usage = 04856 "Usage: core show switches\n" 04857 " List registered switches\n"; 04858 return NULL; 04859 case CLI_GENERATE: 04860 return NULL; 04861 } 04862 04863 AST_RWLIST_RDLOCK(&switches); 04864 04865 if (AST_RWLIST_EMPTY(&switches)) { 04866 AST_RWLIST_UNLOCK(&switches); 04867 ast_cli(a->fd, "There are no registered alternative switches\n"); 04868 return CLI_SUCCESS; 04869 } 04870 04871 ast_cli(a->fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 04872 AST_RWLIST_TRAVERSE(&switches, sw, list) 04873 ast_cli(a->fd, "%s: %s\n", sw->name, sw->description); 04874 04875 AST_RWLIST_UNLOCK(&switches); 04876 04877 return CLI_SUCCESS; 04878 }
| static int handle_statechange | ( | void * | datap | ) | [static] |
Definition at line 3332 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().
03333 { 03334 struct ast_hint *hint; 03335 struct statechange *sc = datap; 03336 03337 ast_rdlock_contexts(); 03338 AST_RWLIST_RDLOCK(&hints); 03339 03340 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03341 struct ast_state_cb *cblist; 03342 char buf[AST_MAX_EXTENSION]; 03343 char *parse = buf; 03344 char *cur; 03345 int state; 03346 03347 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf)); 03348 while ( (cur = strsep(&parse, "&")) ) { 03349 if (!strcasecmp(cur, sc->dev)) 03350 break; 03351 } 03352 if (!cur) 03353 continue; 03354 03355 /* Get device state for this hint */ 03356 state = ast_extension_state2(hint->exten); 03357 03358 if ((state == -1) || (state == hint->laststate)) 03359 continue; 03360 03361 /* Device state changed since last check - notify the watchers */ 03362 03363 /* For general callbacks */ 03364 AST_LIST_TRAVERSE(&statecbs, cblist, entry) { 03365 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 03366 } 03367 03368 /* For extension callbacks */ 03369 AST_LIST_TRAVERSE(&hint->callbacks, cblist, entry) { 03370 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 03371 } 03372 03373 hint->laststate = state; /* record we saw the change */ 03374 } 03375 AST_RWLIST_UNLOCK(&hints); 03376 ast_unlock_contexts(); 03377 ast_free(sc); 03378 return 0; 03379 }
| static char* handle_unset_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 5756 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.
05757 { 05758 int oldval = 0; 05759 05760 switch (cmd) { 05761 case CLI_INIT: 05762 e->command = "dialplan set extenpatternmatchnew false"; 05763 e->usage = 05764 "Usage: dialplan set extenpatternmatchnew true|false\n" 05765 " Use the NEW extension pattern matching algorithm, true or false.\n"; 05766 return NULL; 05767 case CLI_GENERATE: 05768 return NULL; 05769 } 05770 05771 if (a->argc != 4) 05772 return CLI_SHOWUSAGE; 05773 05774 oldval = pbx_set_extenpatternmatchnew(0); 05775 05776 if (!oldval) 05777 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n"); 05778 else 05779 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n"); 05780 05781 return CLI_SUCCESS; 05782 }
| 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 3951 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().
03952 { 03953 int failed = 0; 03954 double curloadavg; 03955 #if defined(HAVE_SYSINFO) 03956 long curfreemem; 03957 struct sysinfo sys_info; 03958 #endif 03959 03960 ast_mutex_lock(&maxcalllock); 03961 if (option_maxcalls) { 03962 if (countcalls >= option_maxcalls) { 03963 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 03964 failed = -1; 03965 } 03966 } 03967 if (option_maxload) { 03968 getloadavg(&curloadavg, 1); 03969 if (curloadavg >= option_maxload) { 03970 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 03971 failed = -1; 03972 } 03973 } 03974 #if defined(HAVE_SYSINFO) 03975 if (option_minmemfree) { 03976 if (!sysinfo(&sys_info)) { 03977 /* make sure that the free system memory is above the configured low watermark 03978 * convert the amount of freeram from mem_units to MB */ 03979 curfreemem = sys_info.freeram / sys_info.mem_unit; 03980 curfreemem /= 1024*1024; 03981 if (curfreemem < option_minmemfree) { 03982 ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree); 03983 failed = -1; 03984 } 03985 } 03986 } 03987 #endif 03988 03989 if (!failed) { 03990 countcalls++; 03991 totalcalls++; 03992 } 03993 ast_mutex_unlock(&maxcalllock); 03994 03995 return failed; 03996 }
| 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 8686 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().
08687 { 08688 int x; 08689 08690 /* Initialize the PBX */ 08691 ast_verb(1, "Asterisk PBX Core Initializing\n"); 08692 if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) { 08693 ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n"); 08694 } 08695 08696 ast_verb(1, "Registering builtin applications:\n"); 08697 ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry)); 08698 __ast_custom_function_register(&exception_function, NULL); 08699 08700 /* Register builtin applications */ 08701 for (x = 0; x < sizeof(builtins) / sizeof(struct pbx_builtin); x++) { 08702 ast_verb(1, "[%s]\n", builtins[x].name); 08703 if (ast_register_application2(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description, NULL)) { 08704 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 08705 return -1; 08706 } 08707 } 08708 08709 /* Register manager application */ 08710 ast_manager_register2("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan, "List dialplan", mandescr_show_dialplan); 08711 08712 if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, NULL, 08713 AST_EVENT_IE_END))) { 08714 return -1; 08715 } 08716 08717 return 0; 08718 }
| 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 6214 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 5347 of file pbx.c.
References astman_send_listack().
Referenced by manager_show_dialplan_helper().
05348 { 05349 astman_send_listack(s, m, "DialPlan list will follow", "start"); 05350 }
| static int manager_show_dialplan | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Manager listing of dial plan.
Definition at line 5493 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().
05494 { 05495 const char *exten, *context; 05496 const char *id = astman_get_header(m, "ActionID"); 05497 char idtext[256]; 05498 int res; 05499 05500 /* Variables used for different counters */ 05501 struct dialplan_counters counters; 05502 05503 if (!ast_strlen_zero(id)) 05504 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 05505 else 05506 idtext[0] = '\0'; 05507 05508 memset(&counters, 0, sizeof(counters)); 05509 05510 exten = astman_get_header(m, "Extension"); 05511 context = astman_get_header(m, "Context"); 05512 05513 res = manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL); 05514 05515 if (context && !counters.context_existence) { 05516 char errorbuf[BUFSIZ]; 05517 05518 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context); 05519 astman_send_error(s, m, errorbuf); 05520 return 0; 05521 } 05522 if (exten && !counters.extension_existence) { 05523 char errorbuf[BUFSIZ]; 05524 05525 if (context) 05526 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context); 05527 else 05528 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten); 05529 astman_send_error(s, m, errorbuf); 05530 return 0; 05531 } 05532 05533 manager_event(EVENT_FLAG_CONFIG, "ShowDialPlanComplete", 05534 "EventList: Complete\r\n" 05535 "ListItems: %d\r\n" 05536 "ListExtensions: %d\r\n" 05537 "ListPriorities: %d\r\n" 05538 "ListContexts: %d\r\n" 05539 "%s" 05540 "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext); 05541 05542 /* everything ok */ 05543 return 0; 05544 }
| 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 5356 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().
05360 { 05361 struct ast_context *c; 05362 int res = 0, old_total_exten = dpc->total_exten; 05363 05364 if (ast_strlen_zero(exten)) 05365 exten = NULL; 05366 if (ast_strlen_zero(context)) 05367 context = NULL; 05368 05369 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten); 05370 05371 /* try to lock contexts */ 05372 if (ast_rdlock_contexts()) { 05373 astman_send_error(s, m, "Failed to lock contexts"); 05374 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n"); 05375 return -1; 05376 } 05377 05378 c = NULL; /* walk all contexts ... */ 05379 while ( (c = ast_walk_contexts(c)) ) { 05380 struct ast_exten *e; 05381 struct ast_include *i; 05382 struct ast_ignorepat *ip; 05383 05384 if (context && strcmp(ast_get_context_name(c), context) != 0) 05385 continue; /* not the name we want */ 05386 05387 dpc->context_existence = 1; 05388 05389 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c)); 05390 05391 if (ast_rdlock_context(c)) { /* failed to lock */ 05392 ast_debug(3, "manager_show_dialplan: Failed to lock context\n"); 05393 continue; 05394 } 05395 05396 /* XXX note- an empty context is not printed */ 05397 e = NULL; /* walk extensions in context */ 05398 while ( (e = ast_walk_context_extensions(c, e)) ) { 05399 struct ast_exten *p; 05400 05401 /* looking for extension? is this our extension? */ 05402 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) { 05403 /* not the one we are looking for, continue */ 05404 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e)); 05405 continue; 05406 } 05407 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e)); 05408 05409 dpc->extension_existence = 1; 05410 05411 /* may we print context info? */ 05412 dpc->total_context++; 05413 dpc->total_exten++; 05414 05415 p = NULL; /* walk next extension peers */ 05416 while ( (p = ast_walk_extension_priorities(e, p)) ) { 05417 int prio = ast_get_extension_priority(p); 05418 05419 dpc->total_prio++; 05420 if (!dpc->total_items++) 05421 manager_dpsendack(s, m); 05422 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 05423 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) ); 05424 05425 /* XXX maybe make this conditional, if p != e ? */ 05426 if (ast_get_extension_label(p)) 05427 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p)); 05428 05429 if (prio == PRIORITY_HINT) { 05430 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p)); 05431 } else { 05432 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)); 05433 } 05434 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e)); 05435 } 05436 } 05437 05438 i = NULL; /* walk included and write info ... */ 05439 while ( (i = ast_walk_context_includes(c, i)) ) { 05440 if (exten) { 05441 /* Check all includes for the requested extension */ 05442 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i); 05443 } else { 05444 if (!dpc->total_items++) 05445 manager_dpsendack(s, m); 05446 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 05447 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)); 05448 astman_append(s, "\r\n"); 05449 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i)); 05450 } 05451 } 05452 05453 ip = NULL; /* walk ignore patterns and write info ... */ 05454 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 05455 const char *ipname = ast_get_ignorepat_name(ip); 05456 char ignorepat[AST_MAX_EXTENSION]; 05457 05458 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 05459 if (!exten || ast_extension_match(ignorepat, exten)) { 05460 if (!dpc->total_items++) 05461 manager_dpsendack(s, m); 05462 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 05463 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip)); 05464 astman_append(s, "\r\n"); 05465 } 05466 } 05467 if (!rinclude) { 05468 struct ast_sw *sw = NULL; 05469 while ( (sw = ast_walk_context_switches(c, sw)) ) { 05470 if (!dpc->total_items++) 05471 manager_dpsendack(s, m); 05472 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 05473 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)); 05474 astman_append(s, "\r\n"); 05475 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw)); 05476 } 05477 } 05478 05479 ast_unlock_context(c); 05480 } 05481 ast_unlock_contexts(); 05482 05483 if (dpc->total_exten == old_total_exten) { 05484 ast_debug(3, "manager_show_dialplan: Found nothing new\n"); 05485 /* Nothing new under the sun */ 05486 return -1; 05487 } else { 05488 return res; 05489 } 05490 }
| static int matchcid | ( | const char * | cidpattern, | |
| const char * | callerid | |||
| ) | [static] |
Definition at line 2041 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
02042 { 02043 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 02044 failing to get a number should count as a match, otherwise not */ 02045 02046 if (ast_strlen_zero(callerid)) 02047 return ast_strlen_zero(cidpattern) ? 1 : 0; 02048 02049 return ast_extension_match(cidpattern, callerid); 02050 }
| 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 2376 of file pbx.c.
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
02377 { 02378 int parens = 0; 02379 02380 *offset = 0; 02381 *length = INT_MAX; 02382 *isfunc = 0; 02383 for (; *var; var++) { 02384 if (*var == '(') { 02385 (*isfunc)++; 02386 parens++; 02387 } else if (*var == ')') { 02388 parens--; 02389 } else if (*var == ':' && parens == 0) { 02390 *var++ = '\0'; 02391 sscanf(var, "%30d:%30d", offset, length); 02392 return 1; /* offset:length valid */ 02393 } 02394 } 02395 return 0; 02396 }
| void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 8566 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().
08567 { 08568 struct ast_var_t *vardata; 08569 08570 ast_rwlock_wrlock(&globalslock); 08571 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 08572 ast_var_delete(vardata); 08573 ast_rwlock_unlock(&globalslock); 08574 }
| 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 8336 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(), 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().
08337 { 08338 struct ast_var_t *variables; 08339 const char *ret = NULL; 08340 int i; 08341 struct varshead *places[2] = { NULL, &globals }; 08342 08343 if (!name) 08344 return NULL; 08345 08346 if (chan) { 08347 ast_channel_lock(chan); 08348 places[0] = &chan->varshead; 08349 } 08350 08351 for (i = 0; i < 2; i++) { 08352 if (!places[i]) 08353 continue; 08354 if (places[i] == &globals) 08355 ast_rwlock_rdlock(&globalslock); 08356 AST_LIST_TRAVERSE(places[i], variables, entries) { 08357 if (!strcmp(name, ast_var_name(variables))) { 08358 ret = ast_var_value(variables); 08359 break; 08360 } 08361 } 08362 if (places[i] == &globals) 08363 ast_rwlock_unlock(&globalslock); 08364 if (ret) 08365 break; 08366 } 08367 08368 if (chan) 08369 ast_channel_unlock(chan); 08370 08371 return ret; 08372 }
| static int pbx_builtin_gotoif | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 8588 of file pbx.c.
References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), pbx_checkcondition(), and strsep().
08589 { 08590 char *condition, *branch1, *branch2, *branch; 08591 char *stringp; 08592 08593 if (ast_strlen_zero(data)) { 08594 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 08595 return 0; 08596 } 08597 08598 stringp = ast_strdupa(data); 08599 condition = strsep(&stringp,"?"); 08600 branch1 = strsep(&stringp,":"); 08601 branch2 = strsep(&stringp,""); 08602 branch = pbx_checkcondition(condition) ? branch1 : branch2; 08603 08604 if (ast_strlen_zero(branch)) { 08605 ast_debug(1, "Not taking any branch\n"); 08606 return 0; 08607 } 08608 08609 return pbx_builtin_goto(chan, branch); 08610 }
| int pbx_builtin_importvar | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 8524 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.
08525 { 08526 char *name; 08527 char *value; 08528 char *channel; 08529 char tmp[VAR_BUF_SIZE]; 08530 static int deprecation_warning = 0; 08531 08532 if (ast_strlen_zero(data)) { 08533 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 08534 return 0; 08535 } 08536 tmp[0] = 0; 08537 if (!deprecation_warning) { 08538 ast_log(LOG_WARNING, "ImportVar is deprecated. Please use Set(varname=${IMPORT(channel,variable)}) instead.\n"); 08539 deprecation_warning = 1; 08540 } 08541 08542 value = ast_strdupa(data); 08543 name = strsep(&value,"="); 08544 channel = strsep(&value,","); 08545 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 08546 struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel); 08547 if (chan2) { 08548 char *s = alloca(strlen(value) + 4); 08549 if (s) { 08550 sprintf(s, "${%s}", value); 08551 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 08552 } 08553 ast_channel_unlock(chan2); 08554 } 08555 pbx_builtin_setvar_helper(chan, name, tmp); 08556 } 08557 08558 return(0); 08559 }
| static int pbx_builtin_incomplete | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 7942 of file pbx.c.
References __ast_answer(), ast_channel::_state, ast_check_hangup(), AST_PBX_INCOMPLETE, AST_STATE_UP, and ast_strlen_zero().
07943 { 07944 char *options = data; 07945 int answer = 1; 07946 07947 /* Some channels can receive DTMF in unanswered state; some cannot */ 07948 if (!ast_strlen_zero(options) && strchr(options, 'n')) { 07949 answer = 0; 07950 } 07951 07952 /* If the channel is hungup, stop waiting */ 07953 if (ast_check_hangup(chan)) { 07954 return -1; 07955 } else if (chan->_state != AST_STATE_UP && answer) { 07956 __ast_answer(chan, 0, 1); 07957 } 07958 07959 return AST_PBX_INCOMPLETE; 07960 }
| 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 8374 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().
08375 { 08376 struct ast_var_t *newvariable; 08377 struct varshead *headp; 08378 08379 if (name[strlen(name)-1] == ')') { 08380 char *function = ast_strdupa(name); 08381 08382 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 08383 ast_func_write(chan, function, value); 08384 return; 08385 } 08386 08387 if (chan) { 08388 ast_channel_lock(chan); 08389 headp = &chan->varshead; 08390 } else { 08391 ast_rwlock_wrlock(&globalslock); 08392 headp = &globals; 08393 } 08394 08395 if (value) { 08396 if (headp == &globals) 08397 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 08398 newvariable = ast_var_assign(name, value); 08399 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 08400 } 08401 08402 if (chan) 08403 ast_channel_unlock(chan); 08404 else 08405 ast_rwlock_unlock(&globalslock); 08406 }
| int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
| void * | vreason | |||
| ) |
Definition at line 2579 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().
02580 { 02581 const char *reason = vreason; 02582 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 02583 struct pbx_exception *exception = NULL; 02584 02585 if (!ds) { 02586 ds = ast_datastore_alloc(&exception_store_info, NULL); 02587 if (!ds) 02588 return -1; 02589 exception = ast_calloc(1, sizeof(struct pbx_exception)); 02590 if (!exception) { 02591 ast_datastore_free(ds); 02592 return -1; 02593 } 02594 if (ast_string_field_init(exception, 128)) { 02595 ast_free(exception); 02596 ast_datastore_free(ds); 02597 return -1; 02598 } 02599 ds->data = exception; 02600 ast_channel_datastore_add(chan, ds); 02601 } else 02602 exception = ds->data; 02603 02604 ast_string_field_set(exception, reason, reason); 02605 ast_string_field_set(exception, context, chan->context); 02606 ast_string_field_set(exception, exten, chan->exten); 02607 exception->priority = chan->priority; 02608 set_ext_pri(chan, "e", 0); 02609 return 0; 02610 }
| static int pbx_builtin_saycharacters | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 8649 of file pbx.c.
References ast_say_character_str().
08650 { 08651 int res = 0; 08652 08653 if (data) 08654 res = ast_say_character_str(chan, data, "", chan->language); 08655 return res; 08656 }
| static int pbx_builtin_saydigits | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 8640 of file pbx.c.
References ast_say_digit_str().
08641 { 08642 int res = 0; 08643 08644 if (data) 08645 res = ast_say_digit_str(chan, data, "", chan->language); 08646 return res; 08647 }
| static int pbx_builtin_saynumber | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 8612 of file pbx.c.
References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), LOG_WARNING, and strsep().
08613 { 08614 char tmp[256]; 08615 char *number = tmp; 08616 char *options; 08617 08618 if (ast_strlen_zero(data)) { 08619 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 08620 return -1; 08621 } 08622 ast_copy_string(tmp, data, sizeof(tmp)); 08623 strsep(&number, ","); 08624 options = strsep(&number, ","); 08625 if (options) { 08626 if ( strcasecmp(options, "f") && strcasecmp(options, "m") && 08627 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 08628 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 08629 return -1; 08630 } 08631 } 08632 08633 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 08634 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 08635 } 08636 08637 return 0; 08638 }
| static int pbx_builtin_sayphonetic | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 8658 of file pbx.c.
References ast_say_phonetic_str().
08659 { 08660 int res = 0; 08661 08662 if (data) 08663 res = ast_say_phonetic_str(chan, data, "", chan->language); 08664 return res; 08665 }
| int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
| struct ast_str ** | buf | |||
| ) |
Definition at line 8304 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().
08305 { 08306 struct ast_var_t *variables; 08307 const char *var, *val; 08308 int total = 0; 08309 08310 if (!chan) 08311 return 0; 08312 08313 (*buf)->used = 0; 08314 (*buf)->str[0] = '\0'; 08315 08316 ast_channel_lock(chan); 08317 08318 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 08319 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 08320 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 08321 ) { 08322 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 08323 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 08324 break; 08325 } else 08326 total++; 08327 } else 08328 break; 08329 } 08330 08331 ast_channel_unlock(chan); 08332 08333 return total; 08334 }
| int pbx_builtin_setvar | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) |
Definition at line 8465 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().
08466 { 08467 char *name, *value, *mydata; 08468 08469 if (ast_compat_app_set) { 08470 return pbx_builtin_setvar_multiple(chan, data); 08471 } 08472 08473 if (ast_strlen_zero(data)) { 08474 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 08475 return 0; 08476 } 08477 08478 mydata = ast_strdupa(data); 08479 name = strsep(&mydata, "="); 08480 value = mydata; 08481 if (strchr(name, ' ')) 08482 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 08483 08484 pbx_builtin_setvar_helper(chan, name, value); 08485 return(0); 08486 }
| void pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| const char * | value | |||
| ) |
Definition at line 8408 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(), 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().
08409 { 08410 struct ast_var_t *newvariable; 08411 struct varshead *headp; 08412 const char *nametail = name; 08413 08414 if (name[strlen(name) - 1] == ')') { 08415 char *function = ast_strdupa(name); 08416 08417 ast_func_write(chan, function, value); 08418 return; 08419 } 08420 08421 if (chan) { 08422 ast_channel_lock(chan); 08423 headp = &chan->varshead; 08424 } else { 08425 ast_rwlock_wrlock(&globalslock); 08426 headp = &globals; 08427 } 08428 08429 /* For comparison purposes, we have to strip leading underscores */ 08430 if (*nametail == '_') { 08431 nametail++; 08432 if (*nametail == '_') 08433 nametail++; 08434 } 08435 08436 AST_LIST_TRAVERSE (headp, newvariable, entries) { 08437 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) { 08438 /* there is already such a variable, delete it */ 08439 AST_LIST_REMOVE(headp, newvariable, entries); 08440 ast_var_delete(newvariable); 08441 break; 08442 } 08443 } 08444 08445 if (value) { 08446 if (headp == &globals) 08447 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 08448 newvariable = ast_var_assign(name, value); 08449 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 08450 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 08451 "Channel: %s\r\n" 08452 "Variable: %s\r\n" 08453 "Value: %s\r\n" 08454 "Uniqueid: %s\r\n", 08455 chan ? chan->name : "none", name, value, 08456 chan ? chan->uniqueid : "none"); 08457 } 08458 08459 if (chan) 08460 ast_channel_unlock(chan); 08461 else 08462 ast_rwlock_unlock(&globalslock); 08463 }
| int pbx_builtin_setvar_multiple | ( | struct ast_channel * | chan, | |
| void * | vdata | |||
| ) |
Definition at line 8488 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().
08489 { 08490 char *data; 08491 int x; 08492 AST_DECLARE_APP_ARGS(args, 08493 AST_APP_ARG(pair)[24]; 08494 ); 08495 AST_DECLARE_APP_ARGS(pair, 08496 AST_APP_ARG(name); 08497 AST_APP_ARG(value); 08498 ); 08499 08500 if (ast_strlen_zero(vdata)) { 08501 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 08502 return 0; 08503 } 08504 08505 data = ast_strdupa(vdata); 08506 AST_STANDARD_APP_ARGS(args, data); 08507 08508 for (x = 0; x < args.argc; x++) { 08509 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 08510 if (pair.argc == 2) { 08511 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 08512 if (strchr(pair.name, ' ')) 08513 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); 08514 } else if (!chan) { 08515 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 08516 } else { 08517 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 08518 } 08519 } 08520 08521 return 0; 08522 }
| 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 8576 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().
08577 { 08578 int res; 08579 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 08580 return 0; 08581 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 08582 return res; 08583 } else { /* Strings are true */ 08584 return 1; 08585 } 08586 }
| 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_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, ',')) { 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 3137 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, 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().
03140 { 03141 struct ast_exten *e; 03142 struct ast_app *app; 03143 int res; 03144 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 03145 char passdata[EXT_DATA_SIZE]; 03146 03147 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 03148 03149 ast_rdlock_contexts(); 03150 if (found) 03151 *found = 0; 03152 03153 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 03154 if (e) { 03155 if (found) 03156 *found = 1; 03157 if (matching_action) { 03158 ast_unlock_contexts(); 03159 return -1; /* success, we found it */ 03160 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 03161 res = e->priority; 03162 ast_unlock_contexts(); 03163 return res; /* the priority we were looking for */ 03164 } else { /* spawn */ 03165 if (!e->cached_app) 03166 e->cached_app = pbx_findapp(e->app); 03167 app = e->cached_app; 03168 ast_unlock_contexts(); 03169 if (!app) { 03170 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 03171 return -1; 03172 } 03173 if (c->context != context) 03174 ast_copy_string(c->context, context, sizeof(c->context)); 03175 if (c->exten != exten) 03176 ast_copy_string(c->exten, exten, sizeof(c->exten)); 03177 c->priority = priority; 03178 pbx_substitute_variables(passdata, sizeof(passdata), c, e); 03179 #ifdef CHANNEL_TRACE 03180 ast_channel_trace_update(c); 03181 #endif 03182 ast_debug(1, "Launching '%s'\n", app->name); 03183 if (VERBOSITY_ATLEAST(3)) { 03184 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 03185 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 03186 exten, context, priority, 03187 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 03188 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 03189 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 03190 "in new stack"); 03191 } 03192 manager_event(EVENT_FLAG_DIALPLAN, "Newexten", 03193 "Channel: %s\r\n" 03194 "Context: %s\r\n" 03195 "Extension: %s\r\n" 03196 "Priority: %d\r\n" 03197 "Application: %s\r\n" 03198 "AppData: %s\r\n" 03199 "Uniqueid: %s\r\n", 03200 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 03201 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 03202 } 03203 } else if (q.swo) { /* not found here, but in another switch */ 03204 if (found) 03205 *found = 1; 03206 ast_unlock_contexts(); 03207 if (matching_action) { 03208 return -1; 03209 } else { 03210 if (!q.swo->exec) { 03211 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 03212 res = -1; 03213 } 03214 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 03215 } 03216 } else { /* not found anywhere, see what happened */ 03217 ast_unlock_contexts(); 03218 switch (q.status) { 03219 case STATUS_NO_CONTEXT: 03220 if (!matching_action && !combined_find_spawn) 03221 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context); 03222 break; 03223 case STATUS_NO_EXTENSION: 03224 if (!matching_action && !combined_find_spawn) 03225 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context); 03226 break; 03227 case STATUS_NO_PRIORITY: 03228 if (!matching_action && !combined_find_spawn) 03229 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context); 03230 break; 03231 case STATUS_NO_LABEL: 03232 if (context && !combined_find_spawn) 03233 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context); 03234 break; 03235 default: 03236 ast_debug(1, "Shouldn't happen!\n"); 03237 } 03238 03239 return (matching_action) ? 0 : -1; 03240 } 03241 }
| 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 2052 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().
02056 { 02057 int x, res; 02058 struct ast_context *tmp = NULL; 02059 struct ast_exten *e = NULL, *eroot = NULL; 02060 struct ast_include *i = NULL; 02061 struct ast_sw *sw = NULL; 02062 struct ast_exten pattern = {NULL, }; 02063 struct scoreboard score = {0, }; 02064 struct ast_str *tmpdata = NULL; 02065 02066 pattern.label = label; 02067 pattern.priority = priority; 02068 #ifdef NEED_DEBUG_HERE 02069 ast_log(LOG_NOTICE,"Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int)action); 02070 #endif 02071 02072 /* Initialize status if appropriate */ 02073 if (q->stacklen == 0) { 02074 q->status = STATUS_NO_CONTEXT; 02075 q->swo = NULL; 02076 q->data = NULL; 02077 q->foundcontext = NULL; 02078 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02079 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02080 return NULL; 02081 } 02082 02083 /* Check first to see if we've already been checked */ 02084 for (x = 0; x < q->stacklen; x++) { 02085 if (!strcasecmp(q->incstack[x], context)) 02086 return NULL; 02087 } 02088 02089 if (bypass) /* bypass means we only look there */ 02090 tmp = bypass; 02091 else { /* look in contexts */ 02092 struct fake_context item; 02093 02094 ast_copy_string(item.name, context, sizeof(item.name)); 02095 02096 tmp = ast_hashtab_lookup(contexts_table, &item); 02097 #ifdef NOTNOW 02098 tmp = NULL; 02099 while ((tmp = ast_walk_contexts(tmp)) ) { 02100 if (!strcmp(tmp->name, context)) 02101 break; 02102 } 02103 #endif 02104 if (!tmp) 02105 return NULL; 02106 02107 } 02108 02109 if (q->status < STATUS_NO_EXTENSION) 02110 q->status = STATUS_NO_EXTENSION; 02111 02112 /* Do a search for matching extension */ 02113 02114 eroot = NULL; 02115 score.total_specificity = 0; 02116 score.exten = 0; 02117 score.total_length = 0; 02118 if (!tmp->pattern_tree && tmp->root_table) 02119 { 02120 create_match_char_tree(tmp); 02121 #ifdef NEED_DEBUG 02122 ast_log(LOG_DEBUG,"Tree Created in context %s:\n", context); 02123 log_match_char_tree(tmp->pattern_tree," "); 02124 #endif 02125 } 02126 #ifdef NEED_DEBUG 02127 ast_log(LOG_NOTICE,"The Trie we are searching in:\n"); 02128 log_match_char_tree(tmp->pattern_tree, ":: "); 02129 #endif 02130 02131 do { 02132 if (!ast_strlen_zero(overrideswitch)) { 02133 char *osw = ast_strdupa(overrideswitch), *name; 02134 struct ast_switch *asw; 02135 ast_switch_f *aswf = NULL; 02136 char *datap; 02137 int eval = 0; 02138 02139 name = strsep(&osw, "/"); 02140 asw = pbx_findswitch(name); 02141 02142 if (!asw) { 02143 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 02144 break; 02145 } 02146 02147 if (osw && strchr(osw, '$')) { 02148 eval = 1; 02149 } 02150 02151 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02152 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!"); 02153 break; 02154 } else if (eval) { 02155 /* Substitute variables now */ 02156 pbx_substitute_variables_helper(chan, osw, tmpdata->str, tmpdata->len); 02157 datap = tmpdata->str; 02158 } else { 02159 datap = osw; 02160 } 02161 02162 /* equivalent of extension_match_core() at the switch level */ 02163 if (action == E_CANMATCH) 02164 aswf = asw->canmatch; 02165 else if (action == E_MATCHMORE) 02166 aswf = asw->matchmore; 02167 else /* action == E_MATCH */ 02168 aswf = asw->exists; 02169 if (!aswf) { 02170 res = 0; 02171 } else { 02172 if (chan) { 02173 ast_autoservice_start(chan); 02174 } 02175 res = aswf(chan, context, exten, priority, callerid, datap); 02176 if (chan) { 02177 ast_autoservice_stop(chan); 02178 } 02179 } 02180 if (res) { /* Got a match */ 02181 q->swo = asw; 02182 q->data = datap; 02183 q->foundcontext = context; 02184 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02185 return NULL; 02186 } 02187 } 02188 } while (0); 02189 02190 if (extenpatternmatchnew) { 02191 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02192 eroot = score.exten; 02193 02194 if (score.last_char == '!' && action == E_MATCHMORE) { 02195 /* We match an extension ending in '!'. 02196 * The decision in this case is final and is NULL (no match). 02197 */ 02198 #ifdef NEED_DEBUG_HERE 02199 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02200 #endif 02201 return NULL; 02202 } 02203 02204 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02205 q->status = STATUS_SUCCESS; 02206 #ifdef NEED_DEBUG_HERE 02207 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02208 #endif 02209 return score.canmatch_exten; 02210 } 02211 02212 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02213 if (score.node) { 02214 struct ast_exten *z = trie_find_next_match(score.node); 02215 if (z) { 02216 #ifdef NEED_DEBUG_HERE 02217 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02218 #endif 02219 } else { 02220 if (score.canmatch_exten) { 02221 #ifdef NEED_DEBUG_HERE 02222 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02223 #endif 02224 return score.canmatch_exten; 02225 } else { 02226 #ifdef NEED_DEBUG_HERE 02227 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02228 #endif 02229 } 02230 } 02231 return z; 02232 } 02233 #ifdef NEED_DEBUG_HERE 02234 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02235 #endif 02236 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02237 } 02238 02239 if (eroot) { 02240 /* found entry, now look for the right priority */ 02241 if (q->status < STATUS_NO_PRIORITY) 02242 q->status = STATUS_NO_PRIORITY; 02243 e = NULL; 02244 if (action == E_FINDLABEL && label ) { 02245 if (q->status < STATUS_NO_LABEL) 02246 q->status = STATUS_NO_LABEL; 02247 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02248 } else { 02249 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02250 } 02251 if (e) { /* found a valid match */ 02252 q->status = STATUS_SUCCESS; 02253 q->foundcontext = context; 02254 #ifdef NEED_DEBUG_HERE 02255 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 02256 #endif 02257 return e; 02258 } 02259 } 02260 } else { /* the old/current default exten pattern match algorithm */ 02261 02262 /* scan the list trying to match extension and CID */ 02263 eroot = NULL; 02264 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 02265 int match = extension_match_core(eroot->exten, exten, action); 02266 /* 0 on fail, 1 on match, 2 on earlymatch */ 02267 02268 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 02269 continue; /* keep trying */ 02270 if (match == 2 && action == E_MATCHMORE) { 02271 /* We match an extension ending in '!'. 02272 * The decision in this case is final and is NULL (no match). 02273 */ 02274 return NULL; 02275 } 02276 /* found entry, now look for the right priority */ 02277 if (q->status < STATUS_NO_PRIORITY) 02278 q->status = STATUS_NO_PRIORITY; 02279 e = NULL; 02280 if (action == E_FINDLABEL && label ) { 02281 if (q->status < STATUS_NO_LABEL) 02282 q->status = STATUS_NO_LABEL; 02283 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02284 } else { 02285 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02286 } 02287 #ifdef NOTNOW 02288 while ( (e = ast_walk_extension_priorities(eroot, e)) ) { 02289 /* Match label or priority */ 02290 if (action == E_FINDLABEL) { 02291 if (q->status < STATUS_NO_LABEL) 02292 q->status = STATUS_NO_LABEL; 02293 if (label && e->label && !strcmp(label, e->label)) 02294 break; /* found it */ 02295 } else if (e->priority == priority) { 02296 break; /* found it */ 02297 } /* else keep searching */ 02298 } 02299 #endif 02300 if (e) { /* found a valid match */ 02301 q->status = STATUS_SUCCESS; 02302 q->foundcontext = context; 02303 return e; 02304 } 02305 } 02306 } 02307 02308 02309 /* Check alternative switches */ 02310 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 02311 struct ast_switch *asw = pbx_findswitch(sw->name); 02312 ast_switch_f *aswf = NULL; 02313 char *datap; 02314 02315 if (!asw) { 02316 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 02317 continue; 02318 } 02319 /* Substitute variables now */ 02320 02321 if (sw->eval) { 02322 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02323 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 02324 continue; 02325 } 02326 pbx_substitute_variables_helper(chan, sw->data, tmpdata->str, tmpdata->len); 02327 } 02328 02329 /* equivalent of extension_match_core() at the switch level */ 02330 if (action == E_CANMATCH) 02331 aswf = asw->canmatch; 02332 else if (action == E_MATCHMORE) 02333 aswf = asw->matchmore; 02334 else /* action == E_MATCH */ 02335 aswf = asw->exists; 02336 datap = sw->eval ? tmpdata->str : sw->data; 02337 if (!aswf) 02338 res = 0; 02339 else { 02340 if (chan) 02341 ast_autoservice_start(chan); 02342 res = aswf(chan, context, exten, priority, callerid, datap); 02343 if (chan) 02344 ast_autoservice_stop(chan); 02345 } 02346 if (res) { /* Got a match */ 02347 q->swo = asw; 02348 q->data = datap; 02349 q->foundcontext = context; 02350 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02351 return NULL; 02352 } 02353 } 02354 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 02355 /* Now try any includes we have in this context */ 02356 for (i = tmp->includes; i; i = i->next) { 02357 if (include_valid(i)) { 02358 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 02359 #ifdef NEED_DEBUG_HERE 02360 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 02361 #endif 02362 return e; 02363 } 02364 if (q->swo) 02365 return NULL; 02366 } 02367 } 02368 return NULL; 02369 }
| 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 8964 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().
08965 { 08966 char *exten, *pri, *context; 08967 char *stringp; 08968 int ipri; 08969 int mode = 0; 08970 08971 if (ast_strlen_zero(goto_string)) { 08972 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n"); 08973 return -1; 08974 } 08975 stringp = ast_strdupa(goto_string); 08976 context = strsep(&stringp, ","); /* guaranteed non-null */ 08977 exten = strsep(&stringp, ","); 08978 pri = strsep(&stringp, ","); 08979 if (!exten) { /* Only a priority in this one */ 08980 pri = context; 08981 exten = NULL; 08982 context = NULL; 08983 } else if (!pri) { /* Only an extension and priority in this one */ 08984 pri = exten; 08985 exten = context; 08986 context = NULL; 08987 } 08988 if (*pri == '+') { 08989 mode = 1; 08990 pri++; 08991 } else if (*pri == '-') { 08992 mode = -1; 08993 pri++; 08994 } 08995 if (sscanf(pri, "%30d", &ipri) != 1) { 08996 if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten, 08997 pri, chan->cid.cid_num)) < 1) { 08998 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 08999 return -1; 09000 } else 09001 mode = 0; 09002 } 09003 /* At this point we have a priority and maybe an extension and a context */ 09004 09005 if (mode) 09006 ipri = chan->priority + (ipri * mode); 09007 09008 if (async) 09009 ast_async_goto(chan, context, exten, ipri); 09010 else 09011 ast_explicit_goto(chan, context, exten, ipri); 09012 09013 return 0; 09014 09015 }
| 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 2451 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().
02452 { 02453 const char not_found = '\0'; 02454 char *tmpvar; 02455 const char *s; /* the result */ 02456 int offset, length; 02457 int i, need_substring; 02458 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 02459 02460 if (c) { 02461 ast_channel_lock(c); 02462 places[0] = &c->varshead; 02463 } 02464 /* 02465 * Make a copy of var because parse_variable_name() modifies the string. 02466 * Then if called directly, we might need to run substring() on the result; 02467 * remember this for later in 'need_substring', 'offset' and 'length' 02468 */ 02469 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 02470 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 02471 02472 /* 02473 * Look first into predefined variables, then into variable lists. 02474 * Variable 's' points to the result, according to the following rules: 02475 * s == ¬_found (set at the beginning) means that we did not find a 02476 * matching variable and need to look into more places. 02477 * If s != ¬_found, s is a valid result string as follows: 02478 * s = NULL if the variable does not have a value; 02479 * you typically do this when looking for an unset predefined variable. 02480 * s = workspace if the result has been assembled there; 02481 * typically done when the result is built e.g. with an snprintf(), 02482 * so we don't need to do an additional copy. 02483 * s != workspace in case we have a string, that needs to be copied 02484 * (the ast_copy_string is done once for all at the end). 02485 * Typically done when the result is already available in some string. 02486 */ 02487 s = ¬_found; /* default value */ 02488 if (c) { /* This group requires a valid channel */ 02489 /* Names with common parts are looked up a piece at a time using strncmp. */ 02490 if (!strncmp(var, "CALL", 4)) { 02491 if (!strncmp(var + 4, "ING", 3)) { 02492 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 02493 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres); 02494 s = workspace; 02495 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 02496 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2); 02497 s = workspace; 02498 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 02499 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton); 02500 s = workspace; 02501 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 02502 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns); 02503 s = workspace; 02504 } 02505 } 02506 } else if (!strcmp(var, "HINT")) { 02507 s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL; 02508 } else if (!strcmp(var, "HINTNAME")) { 02509 s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL; 02510 } else if (!strcmp(var, "EXTEN")) { 02511 s = c->exten; 02512 } else if (!strcmp(var, "CONTEXT")) { 02513 s = c->context; 02514 } else if (!strcmp(var, "PRIORITY")) { 02515 snprintf(workspace, workspacelen, "%d", c->priority); 02516 s = workspace; 02517 } else if (!strcmp(var, "CHANNEL")) { 02518 s = c->name; 02519 } else if (!strcmp(var, "UNIQUEID")) { 02520 s = c->uniqueid; 02521 } else if (!strcmp(var, "HANGUPCAUSE")) { 02522 snprintf(workspace, workspacelen, "%d", c->hangupcause); 02523 s = workspace; 02524 } 02525 } 02526 if (s == ¬_found) { /* look for more */ 02527 if (!strcmp(var, "EPOCH")) { 02528 snprintf(workspace, workspacelen, "%u",(int)time(NULL)); 02529 s = workspace; 02530 } else if (!strcmp(var, "SYSTEMNAME")) { 02531 s = ast_config_AST_SYSTEM_NAME; 02532 } else if (!strcmp(var, "ENTITYID")) { 02533 ast_eid_to_str(workspace, workspacelen, &ast_eid_default); 02534 s = workspace; 02535 } 02536 } 02537 /* if not found, look into chanvars or global vars */ 02538 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 02539 struct ast_var_t *variables; 02540 if (!places[i]) 02541 continue; 02542 if (places[i] == &globals) 02543 ast_rwlock_rdlock(&globalslock); 02544 AST_LIST_TRAVERSE(places[i], variables, entries) { 02545 if (!strcasecmp(ast_var_name(variables), var)) { 02546 s = ast_var_value(variables); 02547 break; 02548 } 02549 } 02550 if (places[i] == &globals) 02551 ast_rwlock_unlock(&globalslock); 02552 } 02553 if (s == ¬_found || s == NULL) 02554 *ret = NULL; 02555 else { 02556 if (s != workspace) 02557 ast_copy_string(workspace, s, workspacelen); 02558 *ret = workspace; 02559 if (need_substring) 02560 *ret = substring(*ret, offset, length, workspace, workspacelen); 02561 } 02562 02563 if (c) 02564 ast_channel_unlock(c); 02565 }
| 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 4092 of file pbx.c.
Referenced by pbx_load_module().
04093 { 04094 int oldval = autofallthrough; 04095 autofallthrough = newval; 04096 return oldval; 04097 }
| 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 4099 of file pbx.c.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
04100 { 04101 int oldval = extenpatternmatchnew; 04102 extenpatternmatchnew = newval; 04103 return oldval; 04104 }
| 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 4106 of file pbx.c.
References ast_free, ast_strdup, and ast_strlen_zero().
Referenced by pbx_load_module().
04107 { 04108 if (overrideswitch) { 04109 ast_free(overrideswitch); 04110 } 04111 if (!ast_strlen_zero(newval)) { 04112 overrideswitch = ast_strdup(newval); 04113 } else { 04114 overrideswitch = NULL; 04115 } 04116 }
| static void pbx_substitute_variables | ( | char * | passdata, | |
| int | datalen, | |||
| struct ast_channel * | c, | |||
| struct ast_exten * | e | |||
| ) | [static] |
Definition at line 3102 of file pbx.c.
References ast_copy_string(), ast_exten::data, and pbx_substitute_variables_helper().
Referenced by pbx_extension_helper().
03103 { 03104 const char *tmp; 03105 03106 /* Nothing more to do */ 03107 if (!e->data) 03108 return; 03109 03110 /* No variables or expressions in e->data, so why scan it? */ 03111 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) { 03112 ast_copy_string(passdata, e->data, datalen); 03113 return; 03114 } 03115 03116 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1); 03117 }
| void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) |
Definition at line 3092 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().
03093 { 03094 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count); 03095 }
| 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 2900 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().
02901 { 02902 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 02903 char *cp4; 02904 const char *tmp, *whereweare; 02905 int length, offset, offset2, isfunction; 02906 char *workspace = NULL; 02907 char *ltmp = NULL, *var = NULL; 02908 char *nextvar, *nextexp, *nextthing; 02909 char *vars, *vare; 02910 int pos, brackets, needsub, len; 02911 02912 *cp2 = 0; /* just in case nothing ends up there */ 02913 whereweare=tmp=cp1; 02914 while (!ast_strlen_zero(whereweare) && count) { 02915 /* Assume we're copying the whole remaining string */ 02916 pos = strlen(whereweare); 02917 nextvar = NULL; 02918 nextexp = NULL; 02919 nextthing = strchr(whereweare, '$'); 02920 if (nextthing) { 02921 switch (nextthing[1]) { 02922 case '{': 02923 nextvar = nextthing; 02924 pos = nextvar - whereweare; 02925 break; 02926 case '[': 02927 nextexp = nextthing; 02928 pos = nextexp - whereweare; 02929 break; 02930 default: 02931 pos = 1; 02932 } 02933 } 02934 02935 if (pos) { 02936 /* Can't copy more than 'count' bytes */ 02937 if (pos > count) 02938 pos = count; 02939 02940 /* Copy that many bytes */ 02941 memcpy(cp2, whereweare, pos); 02942 02943 count -= pos; 02944 cp2 += pos; 02945 whereweare += pos; 02946 *cp2 = 0; 02947 } 02948 02949 if (nextvar) { 02950 /* We have a variable. Find the start and end, and determine 02951 if we are going to have to recursively call ourselves on the 02952 contents */ 02953 vars = vare = nextvar + 2; 02954 brackets = 1; 02955 needsub = 0; 02956 02957 /* Find the end of it */ 02958 while (brackets && *vare) { 02959 if ((vare[0] == '$') && (vare[1] == '{')) { 02960 needsub++; 02961 } else if (vare[0] == '{') { 02962 brackets++; 02963 } else if (vare[0] == '}') { 02964 brackets--; 02965 } else if ((vare[0] == '$') && (vare[1] == '[')) 02966 needsub++; 02967 vare++; 02968 } 02969 if (brackets) 02970 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 02971 len = vare - vars - 1; 02972 02973 /* Skip totally over variable string */ 02974 whereweare += (len + 3); 02975 02976 if (!var) 02977 var = alloca(VAR_BUF_SIZE); 02978 02979 /* Store variable name (and truncate) */ 02980 ast_copy_string(var, vars, len + 1); 02981 02982 /* Substitute if necessary */ 02983 if (needsub) { 02984 if (!ltmp) 02985 ltmp = alloca(VAR_BUF_SIZE); 02986 02987 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 02988 vars = ltmp; 02989 } else { 02990 vars = var; 02991 } 02992 02993 if (!workspace) 02994 workspace = alloca(VAR_BUF_SIZE); 02995 02996 workspace[0] = '\0'; 02997 02998 parse_variable_name(vars, &offset, &offset2, &isfunction); 02999 if (isfunction) { 03000 /* Evaluate function */ 03001 if (c || !headp) 03002 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03003 else { 03004 struct varshead old; 03005 struct ast_channel *bogus = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars); 03006 if (bogus) { 03007 memcpy(&old, &bogus->varshead, sizeof(old)); 03008 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 03009 cp4 = ast_func_read(bogus, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03010 /* Don't deallocate the varshead that was passed in */ 03011 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 03012 ast_channel_free(bogus); 03013 } else 03014 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03015 } 03016 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03017 } else { 03018 /* Retrieve variable value */ 03019 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 03020 } 03021 if (cp4) { 03022 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 03023 03024 length = strlen(cp4); 03025 if (length > count) 03026 length = count; 03027 memcpy(cp2, cp4, length); 03028 count -= length; 03029 cp2 += length; 03030 *cp2 = 0; 03031 } 03032 } else if (nextexp) { 03033 /* We have an expression. Find the start and end, and determine 03034 if we are going to have to recursively call ourselves on the 03035 contents */ 03036 vars = vare = nextexp + 2; 03037 brackets = 1; 03038 needsub = 0; 03039 03040 /* Find the end of it */ 03041 while (brackets && *vare) { 03042 if ((vare[0] == '$') && (vare[1] == '[')) { 03043 needsub++; 03044 brackets++; 03045 vare++; 03046 } else if (vare[0] == '[') { 03047 brackets++; 03048 } else if (vare[0] == ']') { 03049 brackets--; 03050 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03051 needsub++; 03052 vare++; 03053 } 03054 vare++; 03055 } 03056 if (brackets) 03057 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03058 len = vare - vars - 1; 03059 03060 /* Skip totally over expression */ 03061 whereweare += (len + 3); 03062 03063 if (!var) 03064 var = alloca(VAR_BUF_SIZE); 03065 03066 /* Store variable name (and truncate) */ 03067 ast_copy_string(var, vars, len + 1); 03068 03069 /* Substitute if necessary */ 03070 if (needsub) { 03071 if (!ltmp) 03072 ltmp = alloca(VAR_BUF_SIZE); 03073 03074 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 03075 vars = ltmp; 03076 } else { 03077 vars = var; 03078 } 03079 03080 length = ast_expr(vars, cp2, count, c); 03081 03082 if (length) { 03083 ast_debug(1, "Expression result is '%s'\n", cp2); 03084 count -= length; 03085 cp2 += length; 03086 *cp2 = 0; 03087 } 03088 } 03089 } 03090 }
| void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) |
Definition at line 3097 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().
03098 { 03099 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count); 03100 }
| static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 4020 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
04021 { 04022 /* Oh joyeous kernel, we're a new thread, with nothing to do but 04023 answer this channel and get it going. 04024 */ 04025 /* NOTE: 04026 The launcher of this function _MUST_ increment 'countcalls' 04027 before invoking the function; it will be decremented when the 04028 PBX has finished running on the channel 04029 */ 04030 struct ast_channel *c = data; 04031 04032 __ast_pbx_run(c, NULL); 04033 decrease_call_count(); 04034 04035 pthread_exit(NULL); 04036 04037 return NULL; 04038 }
| static void print_ext | ( | struct ast_exten * | e, | |
| char * | buf, | |||
| int | buflen | |||
| ) | [static] |
helper function to print an extension
Definition at line 5006 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().
05007 { 05008 int prio = ast_get_extension_priority(e); 05009 if (prio == PRIORITY_HINT) { 05010 snprintf(buf, buflen, "hint: %s", 05011 ast_get_extension_app(e)); 05012 } else { 05013 snprintf(buf, buflen, "%d. %s(%s)", 05014 prio, ast_get_extension_app(e), 05015 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 05016 } 05017 }
| 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 3660 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().
03661 { 03662 ast_channel_lock(c); 03663 ast_copy_string(c->exten, exten, sizeof(c->exten)); 03664 c->priority = pri; 03665 ast_channel_unlock(c); 03666 }
| 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 5171 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().
05172 { 05173 struct ast_context *c = NULL; 05174 int res = 0, old_total_exten = dpc->total_exten; 05175 05176 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n"); 05177 05178 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n"); 05179 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n"); 05180 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n"); 05181 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n"); 05182 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n"); 05183 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n"); 05184 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n"); 05185 ast_rdlock_contexts(); 05186 05187 /* walk all contexts ... */ 05188 while ( (c = ast_walk_contexts(c)) ) { 05189 int context_info_printed = 0; 05190 05191 if (context && strcmp(ast_get_context_name(c), context)) 05192 continue; /* skip this one, name doesn't match */ 05193 05194 dpc->context_existence = 1; 05195 05196 if (!c->pattern_tree) 05197 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */ 05198 05199 ast_rdlock_context(c); 05200 05201 dpc->total_context++; 05202 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 05203 ast_get_context_name(c), ast_get_context_registrar(c)); 05204 context_info_printed = 1; 05205 05206 if (c->pattern_tree) 05207 { 05208 cli_match_char_tree(c->pattern_tree, " ", fd); 05209 } else { 05210 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n"); 05211 } 05212 05213 ast_unlock_context(c); 05214 05215 /* if we print something in context, make an empty line */ 05216 if (context_info_printed) 05217 ast_cli(fd, "\n"); 05218 } 05219 ast_unlock_contexts(); 05220 05221 return (dpc->total_exten == old_total_exten) ? -1 : res; 05222 }
| 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 5020 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().
05021 { 05022 struct ast_context *c = NULL; 05023 int res = 0, old_total_exten = dpc->total_exten; 05024 05025 ast_rdlock_contexts(); 05026 05027 /* walk all contexts ... */ 05028 while ( (c = ast_walk_contexts(c)) ) { 05029 struct ast_exten *e; 05030 struct ast_include *i; 05031 struct ast_ignorepat *ip; 05032 char buf[256], buf2[256]; 05033 int context_info_printed = 0; 05034 05035 if (context && strcmp(ast_get_context_name(c), context)) 05036 continue; /* skip this one, name doesn't match */ 05037 05038 dpc->context_existence = 1; 05039 05040 ast_rdlock_context(c); 05041 05042 /* are we looking for exten too? if yes, we print context 05043 * only if we find our extension. 05044 * Otherwise print context even if empty ? 05045 * XXX i am not sure how the rinclude is handled. 05046 * I think it ought to go inside. 05047 */ 05048 if (!exten) { 05049 dpc->total_context++; 05050 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 05051 ast_get_context_name(c), ast_get_context_registrar(c)); 05052 context_info_printed = 1; 05053 } 05054 05055 /* walk extensions ... */ 05056 e = NULL; 05057 while ( (e = ast_walk_context_extensions(c, e)) ) { 05058 struct ast_exten *p; 05059 05060 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 05061 continue; /* skip, extension match failed */ 05062 05063 dpc->extension_existence = 1; 05064 05065 /* may we print context info? */ 05066 if (!context_info_printed) { 05067 dpc->total_context++; 05068 if (rinclude) { /* TODO Print more info about rinclude */ 05069 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 05070 ast_get_context_name(c), ast_get_context_registrar(c)); 05071 } else { 05072 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 05073 ast_get_context_name(c), ast_get_context_registrar(c)); 05074 } 05075 context_info_printed = 1; 05076 } 05077 dpc->total_prio++; 05078 05079 /* write extension name and first peer */ 05080 if (e->matchcid) 05081 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch); 05082 else 05083 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 05084 05085 print_ext(e, buf2, sizeof(buf2)); 05086 05087 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 05088 ast_get_extension_registrar(e)); 05089 05090 dpc->total_exten++; 05091 /* walk next extension peers */ 05092 p = e; /* skip the first one, we already got it */ 05093 while ( (p = ast_walk_extension_priorities(e, p)) ) { 05094 const char *el = ast_get_extension_label(p); 05095 dpc->total_prio++; 05096 if (el) 05097 snprintf(buf, sizeof(buf), " [%s]", el); 05098 else 05099 buf[0] = '\0'; 05100 print_ext(p, buf2, sizeof(buf2)); 05101 05102 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 05103 ast_get_extension_registrar(p)); 05104 } 05105 } 05106 05107 /* walk included and write info ... */ 05108 i = NULL; 05109 while ( (i = ast_walk_context_includes(c, i)) ) { 05110 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 05111 if (exten) { 05112 /* Check all includes for the requested extension */ 05113 if (includecount >= AST_PBX_MAX_STACK) { 05114 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n"); 05115 } else { 05116 int dupe = 0; 05117 int x; 05118 for (x = 0; x < includecount; x++) { 05119 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 05120 dupe++; 05121 break; 05122 } 05123 } 05124 if (!dupe) { 05125 includes[includecount] = ast_get_include_name(i); 05126 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 05127 } else { 05128 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 05129 } 05130 } 05131 } else { 05132 ast_cli(fd, " Include => %-45s [%s]\n", 05133 buf, ast_get_include_registrar(i)); 05134 } 05135 } 05136 05137 /* walk ignore patterns and write info ... */ 05138 ip = NULL; 05139 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 05140 const char *ipname = ast_get_ignorepat_name(ip); 05141 char ignorepat[AST_MAX_EXTENSION]; 05142 snprintf(buf, sizeof(buf), "'%s'", ipname); 05143 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 05144 if (!exten || ast_extension_match(ignorepat, exten)) { 05145 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 05146 buf, ast_get_ignorepat_registrar(ip)); 05147 } 05148 } 05149 if (!rinclude) { 05150 struct ast_sw *sw = NULL; 05151 while ( (sw = ast_walk_context_switches(c, sw)) ) { 05152 snprintf(buf, sizeof(buf), "'%s/%s'", 05153 ast_get_switch_name(sw), 05154 ast_get_switch_data(sw)); 05155 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 05156 buf, ast_get_switch_registrar(sw)); 05157 } 05158 } 05159 05160 ast_unlock_context(c); 05161 05162 /* if we print something in context, make an empty line */ 05163 if (context_info_printed) 05164 ast_cli(fd, "\n"); 05165 } 05166 ast_unlock_contexts(); 05167 05168 return (dpc->total_exten == old_total_exten) ? -1 : res; 05169 }
| 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 2409 of file pbx.c.
References ast_copy_string().
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
02410 { 02411 char *ret = workspace; 02412 int lr; /* length of the input string after the copy */ 02413 02414 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 02415 02416 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 02417 02418 /* Quick check if no need to do anything */ 02419 if (offset == 0 && length >= lr) /* take the whole string */ 02420 return ret; 02421 02422 if (offset < 0) { /* translate negative offset into positive ones */ 02423 offset = lr + offset; 02424 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 02425 offset = 0; 02426 } 02427 02428 /* too large offset result in empty string so we know what to return */ 02429 if (offset >= lr) 02430 return ret + lr; /* the final '\0' */ 02431 02432 ret += offset; /* move to the start position */ 02433 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 02434 ret[length] = '\0'; 02435 else if (length < 0) { 02436 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 02437 ret[lr + length - offset] = '\0'; 02438 else 02439 ret[0] = '\0'; 02440 } 02441 02442 return ret; 02443 }
| 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 5816 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().
05817 { 05818 struct ast_context *context = NULL; 05819 struct ast_exten *eroot = NULL, *e = NULL; 05820 05821 ast_rdlock_contexts(); 05822 while ((context = ast_walk_contexts(context))) { 05823 while ((eroot = ast_walk_context_extensions(context, eroot))) { 05824 while ((e = ast_walk_extension_priorities(eroot, e))) { 05825 if (e->cached_app == app) 05826 e->cached_app = NULL; 05827 } 05828 } 05829 } 05830 ast_unlock_contexts(); 05831 05832 return; 05833 }
| 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 7846 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().
07847 { 07848 int res; 07849 struct ast_frame *f; 07850 double waitsec; 07851 int waittime; 07852 07853 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0)) 07854 waitsec = -1; 07855 if (waitsec > -1) { 07856 waittime = waitsec * 1000.0; 07857 ast_safe_sleep(chan, waittime); 07858 } else do { 07859 res = ast_waitfor(chan, -1); 07860 if (res < 0) 07861 return; 07862 f = ast_read(chan); 07863 if (f) 07864 ast_frfree(f); 07865 } while(f); 07866 }
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 8719 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 6363 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 2632 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 2574 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 5546 of file pbx.c.
Referenced by load_pbx().
char* months[] [static] |
Definition at line 6375 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 5795 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