#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/cel.h"
#include "asterisk/config.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/ast_expr.h"
#include "asterisk/linkedlists.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/devicestate.h"
#include "asterisk/event.h"
#include "asterisk/hashtab.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/xmldoc.h"
#include "asterisk/astobj2.h"

Go to the source code of this file.
Data Structures | |
| struct | acf_root |
| struct | app_tmp |
| struct | apps |
| struct | ast_app |
| ast_app: A registered application More... | |
| struct | ast_context |
| ast_context: An extension context More... | |
| struct | ast_exten |
| ast_exten: An extension The dialplan is saved as a linked list with each context having it's own linked list of extensions - one item per priority. More... | |
| struct | ast_hint |
| Structure for dial plan hints. More... | |
| struct | ast_hintdevice |
| Structure for dial plan hint devices. More... | |
| struct | ast_ignorepat |
| ast_ignorepat: Ignore patterns in dial plan More... | |
| struct | ast_include |
| ast_include: include= support in extensions.conf More... | |
| struct | ast_state_cb |
| ast_state_cb: An extension state notify register item More... | |
| struct | ast_sw |
| ast_sw: Switch statement in extensions.conf More... | |
| struct | async_stat |
| struct | cfextension_states |
| struct | dialplan_counters |
| Counters for the show dialplan manager command. More... | |
| struct | fake_context |
| struct | match_char |
| match_char: forms a syntax tree for quick matching of extension patterns More... | |
| struct | pattern_node |
| struct | pbx_builtin |
| Declaration of builtin applications. More... | |
| struct | pbx_exception |
| struct | scoreboard |
| struct | statechange |
| struct | store_hint |
| struct | store_hints |
| struct | switches |
Defines | |
| #define | AST_PBX_MAX_STACK 128 |
| #define | BACKGROUND_MATCHEXTEN (1 << 2) |
| #define | BACKGROUND_NOANSWER (1 << 1) |
| #define | BACKGROUND_PLAYBACK (1 << 3) |
| #define | BACKGROUND_SKIP (1 << 0) |
| #define | EXT_DATA_SIZE 8192 |
| #define | HASH_EXTENHINT_SIZE 563 |
| #define | HINTDEVICE_DATA_LENGTH 16 |
| #define | INC_DST_OVERFLOW_CHECK |
| #define | NEW_MATCHER_CHK_MATCH |
| #define | NEW_MATCHER_RECURSE |
| #define | SAY_STUBS |
| #define | STATUS_NO_CONTEXT 1 |
| #define | STATUS_NO_EXTENSION 2 |
| #define | STATUS_NO_LABEL 4 |
| #define | STATUS_NO_PRIORITY 3 |
| #define | STATUS_SUCCESS 5 |
| #define | SWITCH_DATA_LENGTH 256 |
| #define | VAR_BUF_SIZE 4096 |
| #define | VAR_HARDTRAN 3 |
| #define | VAR_NORMAL 1 |
| #define | VAR_SOFTTRAN 2 |
| #define | WAITEXTEN_DIALTONE (1 << 1) |
| #define | WAITEXTEN_MOH (1 << 0) |
Functions | |
| void | __ast_context_destroy (struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar) |
| int | __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod) |
| Register a custom function. | |
| static int | __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async) |
| static void | __ast_internal_context_destroy (struct ast_context *con) |
| static enum ast_pbx_result | __ast_pbx_run (struct ast_channel *c, struct ast_pbx_args *args) |
| static void | __fini_acf_root (void) |
| static void | __fini_apps (void) |
| static void | __fini_switches (void) |
| static void | __init_acf_root (void) |
| static void | __init_apps (void) |
| static void | __init_extensionstate_buf (void) |
| static void | __init_hintdevice_data (void) |
| static void | __init_switch_data (void) |
| static void | __init_switches (void) |
| static int | _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
| static int | acf_exception_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen) |
| static int | acf_retrieve_docs (struct ast_custom_function *acf) |
| static struct match_char * | add_exten_to_pattern_tree (struct ast_context *con, struct ast_exten *e1, int findonly) |
| static int | add_hintdevice (struct ast_hint *hint, const char *devicelist) |
| add hintdevice structure and link it into the container. | |
| static struct match_char * | add_pattern_node (struct ast_context *con, struct match_char *current, const struct pattern_node *pattern, int is_pattern, int already, struct match_char **nextcharptr) |
| static int | add_priority (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace) |
| add the extension in the priority chain. | |
| static struct match_char * | already_in_tree (struct match_char *current, char *pat, int is_pattern) |
| int | ast_active_calls (void) |
| Retrieve the number of active calls. | |
| int | ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
| Add and extension to an extension context. | |
| int | ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
| Main interface to add extensions to the list for out context. | |
| static int | ast_add_extension2_lockopt (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, int lock_context) |
| Same as ast_add_extension2() but controls the context locking. | |
| static int | ast_add_extension_nolock (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
| static int | ast_add_hint (struct ast_exten *e) |
| Add hint to hint list, check initial extension state. | |
| int | ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| Set the channel to next execute the specified dialplan location. | |
| int | ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority) |
| Set the channel to next execute the specified dialplan location. | |
| int | ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string) |
| int | ast_build_timing (struct ast_timing *i, const char *info_in) |
| Construct a timing bitmap, for use in time-based conditionals. | |
| int | ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Looks for a valid matching extension. | |
| static int | ast_change_hint (struct ast_exten *oe, struct ast_exten *ne) |
| Change hint for an extension. | |
| int | ast_check_timing (const struct ast_timing *i) |
| Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified. | |
| int | ast_check_timing2 (const struct ast_timing *i, const struct timeval tv) |
| Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified. | |
| char * | ast_complete_applications (const char *line, const char *word, int state) |
| Command completion for the list of installed applications. | |
| int | ast_context_add_ignorepat (const char *context, const char *value, const char *registrar) |
| Add an ignorepat. | |
| int | ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar) |
| int | ast_context_add_include (const char *context, const char *include, const char *registrar) |
| Add a context include. | |
| int | ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar) |
| Add a context include. | |
| int | ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar) |
| Add a switch. | |
| int | ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar) |
| Adds a switch (first param is a ast_context). | |
| void | ast_context_destroy (struct ast_context *con, const char *registrar) |
| Destroy a context (matches the specified context (or ANY context if NULL). | |
| struct ast_context * | ast_context_find (const char *name) |
| Find a context. | |
| struct ast_context * | ast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar) |
| Register a new context or find an existing one. | |
| int | ast_context_lockmacro (const char *context) |
| locks the macrolock in the given given context | |
| int | ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar) |
| Simply remove extension from context. | |
| int | ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked) |
| This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return. | |
| int | ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar) |
| int | ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked) |
| int | ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
| int | ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
| int | ast_context_remove_include (const char *context, const char *include, const char *registrar) |
| Remove included contexts. This function locks contexts list by &conlist, search for the right context structure, leave context list locked and call ast_context_remove_include2 which removes include, unlock contexts list and return ... | |
| int | ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar) |
| Locks context, remove included contexts, unlocks context. When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault. | |
| int | ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar) |
| Remove a switch. | |
| int | ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar) |
| This function locks given context, removes switch, unlock context and return. | |
| int | ast_context_unlockmacro (const char *context) |
| Unlocks the macrolock in the given context. | |
| int | ast_context_verify_includes (struct ast_context *con) |
| Verifies includes in an ast_contect structure. | |
| struct ast_custom_function * | ast_custom_function_find (const char *name) |
| int | ast_custom_function_unregister (struct ast_custom_function *acf) |
| Unregister a custom function. | |
| int | ast_destroy_timing (struct ast_timing *i) |
| Deallocates memory structures associated with a timing bitmap. | |
| enum ast_extension_states | ast_devstate_to_extenstate (enum ast_device_state devstate) |
| Map devstate to an extension state. | |
| int | ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Determine whether an extension exists. | |
| int | ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_extension_close (const char *pattern, const char *data, int needmore) |
| int | ast_extension_cmp (const char *a, const char *b) |
| Determine if one extension should match before another. | |
| int | ast_extension_match (const char *pattern, const char *data) |
| Determine if a given extension matches a given pattern (in NXX format). | |
| int | ast_extension_state (struct ast_channel *c, const char *context, const char *exten) |
| Check extension state for an extension by using hint. | |
| static int | ast_extension_state2 (struct ast_exten *e) |
| Check state of extension by using hints. | |
| const char * | ast_extension_state2str (int extension_state) |
| Return extension_state as string. | |
| static int | ast_extension_state3 (struct ast_str *hint_app) |
| int | ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type change_cb, void *data) |
| Add watcher for extension states. | |
| int | ast_extension_state_add_destroy (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data) |
| Add watcher for extension states with destructor. | |
| int | ast_extension_state_del (int id, ast_state_cb_type change_cb) |
| ast_extension_state_del: Remove a watcher from the callback list | |
| int | ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid) |
| Find the priority of an extension that has the specified label. | |
| int | ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid) |
| Find the priority of an extension that has the specified label. | |
| int | ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len) |
| executes a read operation on a function | |
| int | ast_func_read2 (struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen) |
| executes a read operation on a function | |
| int | ast_func_write (struct ast_channel *chan, const char *function, const char *value) |
| executes a write operation on a function | |
| const char * | ast_get_context_name (struct ast_context *con) |
| const char * | ast_get_context_registrar (struct ast_context *c) |
| const char * | ast_get_extension_app (struct ast_exten *e) |
| void * | ast_get_extension_app_data (struct ast_exten *e) |
| const char * | ast_get_extension_cidmatch (struct ast_exten *e) |
| struct ast_context * | ast_get_extension_context (struct ast_exten *exten) |
| const char * | ast_get_extension_label (struct ast_exten *exten) |
| int | ast_get_extension_matchcid (struct ast_exten *e) |
| const char * | ast_get_extension_name (struct ast_exten *exten) |
| int | ast_get_extension_priority (struct ast_exten *exten) |
| const char * | ast_get_extension_registrar (struct ast_exten *e) |
| int | ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten) |
| Get hint for channel. | |
| const char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
| const char * | ast_get_ignorepat_registrar (struct ast_ignorepat *ip) |
| const char * | ast_get_include_name (struct ast_include *inc) |
| const char * | ast_get_include_registrar (struct ast_include *i) |
| const char * | ast_get_switch_data (struct ast_sw *sw) |
| int | ast_get_switch_eval (struct ast_sw *sw) |
| const char * | ast_get_switch_name (struct ast_sw *sw) |
| const char * | ast_get_switch_registrar (struct ast_sw *sw) |
| int | ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_hashtab_compare_contexts (const void *ah_a, const void *ah_b) |
| hashtable functions for contexts | |
| unsigned int | ast_hashtab_hash_contexts (const void *obj) |
| static struct ast_exten * | ast_hint_extension (struct ast_channel *c, const char *context, const char *exten) |
| static struct ast_exten * | ast_hint_extension_nolock (struct ast_channel *c, const char *context, const char *exten) |
| Find hint for given extension in context. | |
| int | ast_ignore_pattern (const char *context, const char *pattern) |
| Checks to see if a number should be ignored. | |
| int | ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Looks to see if adding anything to this extension might match something. (exists ^ canmatch). | |
| void | ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar) |
| Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added. | |
| int | ast_parseable_goto (struct ast_channel *chan, const char *goto_string) |
| int | ast_pbx_init (void) |
| int | ast_pbx_outgoing_app (const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) |
| 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, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel) |
| enum ast_pbx_result | ast_pbx_run (struct ast_channel *c) |
| Execute the PBX in the current thread. | |
| static void * | ast_pbx_run_app (void *data) |
| run the application and free the descriptor once done | |
| enum ast_pbx_result | ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args) |
| Execute the PBX in the current thread. | |
| enum ast_pbx_result | ast_pbx_start (struct ast_channel *c) |
| Create a new thread and start the PBX. | |
| int | ast_processed_calls (void) |
| Retrieve the total number of calls processed through the PBX since last restart. | |
| int | ast_rdlock_context (struct ast_context *con) |
| Read locks a given context. | |
| int | ast_rdlock_contexts (void) |
| Read locks the context list. | |
| int | ast_register_application2 (const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod) |
| Dynamically register a new dial plan application. | |
| int | ast_register_switch (struct ast_switch *sw) |
| Register an alternative dialplan switch. | |
| static int | ast_remove_hint (struct ast_exten *e) |
| Remove hint from extension. | |
| int | ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn) |
| Launch a new extension (i.e. new stack). | |
| int | ast_str_get_hint (struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten) |
| Get hint for channel. | |
| const char * | ast_str_retrieve_variable (struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var) |
| void | ast_str_substitute_variables (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ) |
| void | ast_str_substitute_variables_full (struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used) |
| void | ast_str_substitute_variables_varshead (struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ) |
| static const char * | ast_str_substring (struct ast_str *value, int offset, int length) |
| int | ast_unlock_context (struct ast_context *con) |
| int | ast_unlock_contexts (void) |
| Unlocks contexts. | |
| int | ast_unregister_application (const char *app) |
| Unregister an application. | |
| void | ast_unregister_switch (struct ast_switch *sw) |
| Unregister an alternative switch. | |
| struct ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten) |
| struct ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
| struct ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
| struct ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
| struct ast_context * | ast_walk_contexts (struct ast_context *con) |
| struct ast_exten * | ast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority) |
| int | ast_wrlock_context (struct ast_context *con) |
| Write locks a given context. | |
| int | ast_wrlock_contexts (void) |
| Write locks the context list. | |
| static void * | async_wait (void *data) |
| static void | cli_match_char_tree (struct match_char *node, char *prefix, int fd) |
| static int | collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos) |
| collect digits from the channel into the buffer. | |
| static int | compare_char (const void *a, const void *b) |
| static char * | complete_core_show_hint (const char *line, const char *word, int pos, int state) |
| autocomplete for CLI command 'core show hint' | |
| static char * | complete_show_dialplan_context (const char *line, const char *word, int pos, int state) |
| static void | context_merge (struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar) |
| static void | context_merge_incls_swits_igps_other_registrars (struct ast_context *new, struct ast_context *old, const char *registrar) |
| static void | create_match_char_tree (struct ast_context *con) |
| static void | decrease_call_count (void) |
| static void | destroy_exten (struct ast_exten *e) |
| static void | destroy_hint (void *obj) |
| static void | destroy_pattern_tree (struct match_char *pattern_tree) |
| static void | destroy_state_cb (void *doomed) |
| static void | device_state_cb (const struct ast_event *event, void *unused) |
| static void | exception_store_free (void *data) |
| static int | ext_cmp (const char *a, const char *b) |
| the full routine to compare extensions in rules. | |
| static int | ext_cmp1 (const char **p, unsigned char *bitwise) |
| helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first. | |
| static int | ext_strncpy (char *dst, const char *src, int len) |
| copy a string skipping whitespace | |
| static int | extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
| static struct ast_context * | find_context (const char *context) |
| lookup for a context with a given name, | |
| static struct ast_context * | find_context_locked (const char *context) |
| lookup for a context with a given name, | |
| static int | find_hint_by_cb_id (void *obj, void *arg, int flags) |
| Find Hint by callback id. | |
| static char * | func_args (char *function) |
| return a pointer to the arguments of the function, and terminates the function name with '\0' | |
| static struct ast_exten * | get_canmatch_exten (struct match_char *node) |
| static const char * | get_pattern_node (struct pattern_node *node, const char *src, int pattern, const char *extenbuf) |
| static unsigned | get_range (char *src, int max, const char *const names[], const char *msg) |
| helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers. | |
| static void | get_timerange (struct ast_timing *i, char *times) |
| store a bitmask of valid times, one bit each 1 minute | |
| static char * | handle_debug_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Send ack once. | |
| static char * | handle_set_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_set_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_set_global (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_show_application (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_show_applications (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_show_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI support for listing chanvar's variables in a parseable way. | |
| static char * | handle_show_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_show_function (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_show_functions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_show_globals (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI support for listing global variables in a parseable way. | |
| static char * | handle_show_hint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| handle_show_hint: CLI support for listing registered dial plan hint | |
| static char * | handle_show_hints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| handle_show_hints: CLI support for listing registered dial plan hints | |
| static char * | handle_show_switches (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| handle_show_switches: CLI support for listing registered dial plan switches | |
| static int | handle_statechange (void *datap) |
| static char * | handle_unset_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | hashtab_compare_exten_labels (const void *ah_a, const void *ah_b) |
| static int | hashtab_compare_exten_numbers (const void *ah_a, const void *ah_b) |
| static int | hashtab_compare_extens (const void *ha_a, const void *ah_b) |
| static unsigned int | hashtab_hash_extens (const void *obj) |
| static unsigned int | hashtab_hash_labels (const void *obj) |
| static unsigned int | hashtab_hash_priority (const void *obj) |
| static int | hint_cmp (void *obj, void *arg, int flags) |
| static int | hint_hash (const void *obj, const int flags) |
| static int | hint_id_cmp (void *obj, void *arg, int flags) |
| static int | hintdevice_cmp_multiple (void *obj, void *arg, int flags) |
| static void | hintdevice_destroy (void *obj) |
| static int | hintdevice_hash_cb (const void *obj, const int flags) |
| static int | hintdevice_remove_cb (void *deviceobj, void *arg, int flags) |
| static int | hints_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root) |
| static int | include_valid (struct ast_include *i) |
| static int | increase_call_count (const struct ast_channel *c) |
| Increase call count for channel. | |
| static void | insert_in_next_chars_alt_char_list (struct match_char **parent_ptr, struct match_char *node) |
| int | load_pbx (void) |
| static int | lookup_name (const char *s, const char *const names[], int max) |
| Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values. | |
| static void | manager_dpsendack (struct mansession *s, const struct message *m) |
| Send ack once. | |
| static int | manager_show_dialplan (struct mansession *s, const struct message *m) |
| Manager listing of dial plan. | |
| static int | manager_show_dialplan_helper (struct mansession *s, const struct message *m, const char *actionidtext, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude) |
| Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dialplan. Must check whether the difference is intentional or not. | |
| static int | matchcid (const char *cidpattern, const char *callerid) |
| static void | new_find_extension (const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action) |
| static int | parse_variable_name (char *var, int *offset, int *length, int *isfunc) |
| extract offset:length from variable name. | |
| static int | pbx_builtin_answer (struct ast_channel *, const char *) |
| static int | pbx_builtin_background (struct ast_channel *, const char *) |
| static int | pbx_builtin_busy (struct ast_channel *, const char *) |
| void | pbx_builtin_clear_globals (void) |
| static int | pbx_builtin_congestion (struct ast_channel *, const char *) |
| static int | pbx_builtin_execiftime (struct ast_channel *, const char *) |
| const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
| Return a pointer to the value of the corresponding channel variable. | |
| static int | pbx_builtin_goto (struct ast_channel *, const char *) |
| static int | pbx_builtin_gotoif (struct ast_channel *, const char *) |
| static int | pbx_builtin_gotoiftime (struct ast_channel *, const char *) |
| static int | pbx_builtin_hangup (struct ast_channel *, const char *) |
| static int | pbx_builtin_importvar (struct ast_channel *, const char *) |
| static int | pbx_builtin_incomplete (struct ast_channel *, const char *) |
| static int | pbx_builtin_noop (struct ast_channel *, const char *) |
| static int | pbx_builtin_proceeding (struct ast_channel *, const char *) |
| static int | pbx_builtin_progress (struct ast_channel *, const char *) |
| void | pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value) |
| Add a variable to the channel variable stack, without removing any previously set value. | |
| int | pbx_builtin_raise_exception (struct ast_channel *chan, const char *reason) |
| static int | pbx_builtin_resetcdr (struct ast_channel *, const char *) |
| static int | pbx_builtin_ringing (struct ast_channel *, const char *) |
| static int | pbx_builtin_saycharacters (struct ast_channel *, const char *) |
| static int | pbx_builtin_saydigits (struct ast_channel *, const char *) |
| static int | pbx_builtin_saynumber (struct ast_channel *, const char *) |
| static int | pbx_builtin_sayphonetic (struct ast_channel *, const char *) |
| int | pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf) |
| Create a human-readable string, specifying all variables and their corresponding values. | |
| static int | pbx_builtin_setamaflags (struct ast_channel *, const char *) |
| int | pbx_builtin_setvar (struct ast_channel *chan, const char *data) |
| Parse and set a single channel variable, where the name and value are separated with an '=' character. | |
| int | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
| Add a variable to the channel variable stack, removing the most recently set value for the same name. | |
| int | pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *vdata) |
| Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character. | |
| static int | pbx_builtin_wait (struct ast_channel *, const char *) |
| static int | pbx_builtin_waitexten (struct ast_channel *, const char *) |
| int | pbx_checkcondition (const char *condition) |
| Evaluate a condition. | |
| static void | pbx_destroy (struct ast_pbx *p) |
| int | pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data) |
| Execute an application. | |
| static int | pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn) |
| The return value depends on the action:. | |
| struct ast_exten * | pbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action) |
| struct ast_app * | pbx_findapp (const char *app) |
| Find application handle in linked list. | |
| static struct ast_switch * | pbx_findswitch (const char *sw) |
| static int | pbx_parseable_goto (struct ast_channel *chan, const char *goto_string, int async) |
| void | pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp) |
| Support for Asterisk built-in variables in the dialplan. | |
| int | pbx_set_autofallthrough (int newval) |
| int | pbx_set_extenpatternmatchnew (int newval) |
| void | pbx_set_overrideswitch (const char *newval) |
| static void | pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e) |
| void | pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count) |
| void | pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used) |
| void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
| static void * | pbx_thread (void *data) |
| static void | print_app_docs (struct ast_app *aa, int fd) |
| static void | print_ext (struct ast_exten *e, char *buf, int buflen) |
| helper function to print an extension | |
| static int | raise_exception (struct ast_channel *chan, const char *reason, int priority) |
| static int | remove_hintdevice (struct ast_hint *hint) |
| static void | set_ext_pri (struct ast_channel *c, const char *exten, int pri) |
| static int | show_debug_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[]) |
| static int | show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[]) |
| static int | statecbs_cmp (void *obj, void *arg, int flags) |
| static char * | substring (const char *value, int offset, int length, char *workspace, size_t workspace_len) |
| takes a substring. It is ok to call with value == workspace. | |
| static int | testtime_write (struct ast_channel *chan, const char *cmd, char *var, const char *value) |
| static struct ast_exten * | trie_find_next_match (struct match_char *node) |
| static void | unreference_cached_app (struct ast_app *app) |
| static void | update_scoreboard (struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node) |
| static void | wait_for_hangup (struct ast_channel *chan, const void *data) |
Variables | |
| static int | autofallthrough = 1 |
| static struct ast_app_option | background_opts [128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },} |
| static struct pbx_builtin | builtins [] |
| Declaration of builtin applications. | |
| static ast_mutex_t | conlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } |
| Lock for the ast_context list. | |
| static ast_mutex_t | context_merge_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } |
| Lock to hold off restructuring of hints by ast_merge_contexts_and_delete. | |
| static struct ast_context * | contexts |
| static struct ast_hashtab * | contexts_table = NULL |
| static int | countcalls |
| static const char *const | days [] |
| static struct ast_event_sub * | device_state_sub |
| Subscription for device state change events. | |
| static struct ast_taskprocessor * | device_state_tps |
| static struct ast_custom_function | exception_function |
| static struct ast_datastore_info | exception_store_info |
| static int | extenpatternmatchnew = 0 |
| static struct cfextension_states | extension_states [] |
| static struct ast_threadstorage | extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , } |
| static struct varshead | globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE |
| static ast_rwlock_t | globalslock = { {0} , NULL, 1 } |
| static struct ast_threadstorage | hintdevice_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_hintdevice_data , .custom_init = NULL , } |
| static struct ao2_container * | hintdevices |
| Container for hint devices. | |
| static struct ao2_container * | hints |
| static struct ast_data_handler | hints_data_provider |
| static ast_mutex_t | maxcalllock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } |
| static const char *const | months [] |
| static char * | overrideswitch = NULL |
| static struct ast_cli_entry | pbx_cli [] |
| static struct ast_data_entry | pbx_data_providers [] |
| static struct ast_app_option | resetcdr_opts [128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },} |
| static struct ao2_container * | statecbs |
| static int | stateid = 1 |
| static struct ast_threadstorage | switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , } |
| static struct ast_custom_function | testtime_function |
| static int | totalcalls |
| static struct ast_app_option | waitexten_opts [128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },} |
Definition in file pbx.c.
| #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 |
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 770 of file pbx.c.
Referenced by pbx_extension_helper(), and realtime_exec().
| #define HASH_EXTENHINT_SIZE 563 |
| #define INC_DST_OVERFLOW_CHECK |
Referenced by get_pattern_node().
| #define NEW_MATCHER_CHK_MATCH |
Referenced by new_find_extension().
| #define NEW_MATCHER_RECURSE |
Referenced by new_find_extension().
| #define VAR_BUF_SIZE 4096 |
Definition at line 775 of file pbx.c.
Referenced by ast_add_extension2_lockopt(), ast_func_read2(), pbx_builtin_importvar(), and pbx_substitute_variables_helper_full().
| #define WAITEXTEN_DIALTONE (1 << 1) |
| #define WAITEXTEN_MOH (1 << 0) |
| void __ast_context_destroy | ( | struct ast_context * | list, | |
| struct ast_hashtab * | contexttab, | |||
| struct ast_context * | con, | |||
| const char * | registrar | |||
| ) |
Definition at line 9280 of file pbx.c.
References __ast_internal_context_destroy(), ast_context::alts, ast_context_remove_extension_callerid2(), ast_copy_string(), ast_debug, ast_free, ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_remove_this_object(), ast_hashtab_start_traversal(), AST_LIST_EMPTY, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_MAX_EXTENSION, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, contexts, ast_exten::exten, ast_context::ignorepats, ast_context::includes, ast_context::name, ast_include::next, ast_ignorepat::next, ast_context::next, ast_sw::next, ast_exten::peer_table, ast_exten::priority, ast_context::refcount, ast_exten::registrar, ast_sw::registrar, ast_include::registrar, ast_ignorepat::registrar, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by ast_context_destroy().
09281 { 09282 struct ast_context *tmp, *tmpl=NULL; 09283 struct ast_exten *exten_item, *prio_item; 09284 09285 for (tmp = list; tmp; ) { 09286 struct ast_context *next = NULL; /* next starting point */ 09287 /* The following code used to skip forward to the next 09288 context with matching registrar, but this didn't 09289 make sense; individual priorities registrar'd to 09290 the matching registrar could occur in any context! */ 09291 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar); 09292 if (con) { 09293 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */ 09294 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar); 09295 if ( !strcasecmp(tmp->name, con->name) ) { 09296 break; /* found it */ 09297 } 09298 } 09299 } 09300 09301 if (!tmp) /* not found, we are done */ 09302 break; 09303 ast_wrlock_context(tmp); 09304 09305 if (registrar) { 09306 /* then search thru and remove any extens that match registrar. */ 09307 struct ast_hashtab_iter *exten_iter; 09308 struct ast_hashtab_iter *prio_iter; 09309 struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL; 09310 struct ast_include *i, *pi = NULL, *ni = NULL; 09311 struct ast_sw *sw = NULL; 09312 09313 /* remove any ignorepats whose registrar matches */ 09314 for (ip = tmp->ignorepats; ip; ip = ipn) { 09315 ipn = ip->next; 09316 if (!strcmp(ip->registrar, registrar)) { 09317 if (ipl) { 09318 ipl->next = ip->next; 09319 ast_free(ip); 09320 continue; /* don't change ipl */ 09321 } else { 09322 tmp->ignorepats = ip->next; 09323 ast_free(ip); 09324 continue; /* don't change ipl */ 09325 } 09326 } 09327 ipl = ip; 09328 } 09329 /* remove any includes whose registrar matches */ 09330 for (i = tmp->includes; i; i = ni) { 09331 ni = i->next; 09332 if (strcmp(i->registrar, registrar) == 0) { 09333 /* remove from list */ 09334 if (pi) { 09335 pi->next = i->next; 09336 /* free include */ 09337 ast_free(i); 09338 continue; /* don't change pi */ 09339 } else { 09340 tmp->includes = i->next; 09341 /* free include */ 09342 ast_free(i); 09343 continue; /* don't change pi */ 09344 } 09345 } 09346 pi = i; 09347 } 09348 /* remove any switches whose registrar matches */ 09349 AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) { 09350 if (strcmp(sw->registrar,registrar) == 0) { 09351 AST_LIST_REMOVE_CURRENT(list); 09352 ast_free(sw); 09353 } 09354 } 09355 AST_LIST_TRAVERSE_SAFE_END; 09356 09357 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */ 09358 exten_iter = ast_hashtab_start_traversal(tmp->root_table); 09359 while ((exten_item=ast_hashtab_next(exten_iter))) { 09360 int end_traversal = 1; 09361 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 09362 while ((prio_item=ast_hashtab_next(prio_iter))) { 09363 char extension[AST_MAX_EXTENSION]; 09364 char cidmatch[AST_MAX_EXTENSION]; 09365 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) { 09366 continue; 09367 } 09368 ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n", 09369 tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL); 09370 /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */ 09371 ast_copy_string(extension, prio_item->exten, sizeof(extension)); 09372 if (prio_item->cidmatch) { 09373 ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch)); 09374 } 09375 end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, prio_item->cidmatch ? cidmatch : NULL, 1, NULL, 1); 09376 } 09377 /* Explanation: 09378 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This 09379 * destruction includes destroying the exten's peer_table, which we are currently traversing. If 09380 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed 09381 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result 09382 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply 09383 * free the iterator 09384 */ 09385 if (end_traversal) { 09386 ast_hashtab_end_traversal(prio_iter); 09387 } else { 09388 ast_free(prio_iter); 09389 } 09390 } 09391 ast_hashtab_end_traversal(exten_iter); 09392 } 09393 09394 /* delete the context if it's registrar matches, is empty, has refcount of 1, */ 09395 /* it's not empty, if it has includes, ignorepats, or switches that are registered from 09396 another registrar. It's not empty if there are any extensions */ 09397 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) { 09398 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 09399 ast_hashtab_remove_this_object(contexttab, tmp); 09400 09401 next = tmp->next; 09402 if (tmpl) 09403 tmpl->next = next; 09404 else 09405 contexts = next; 09406 /* Okay, now we're safe to let it go -- in a sense, we were 09407 ready to let it go as soon as we locked it. */ 09408 ast_unlock_context(tmp); 09409 __ast_internal_context_destroy(tmp); 09410 } else { 09411 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar, 09412 tmp->refcount, tmp->root); 09413 ast_unlock_context(tmp); 09414 next = tmp->next; 09415 tmpl = tmp; 09416 } 09417 } else if (con) { 09418 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar); 09419 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 09420 ast_hashtab_remove_this_object(contexttab, tmp); 09421 09422 next = tmp->next; 09423 if (tmpl) 09424 tmpl->next = next; 09425 else 09426 contexts = next; 09427 /* Okay, now we're safe to let it go -- in a sense, we were 09428 ready to let it go as soon as we locked it. */ 09429 ast_unlock_context(tmp); 09430 __ast_internal_context_destroy(tmp); 09431 } 09432 09433 /* if we have a specific match, we are done, otherwise continue */ 09434 tmp = con ? NULL : next; 09435 } 09436 }
| int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
| struct ast_module * | mod | |||
| ) |
Register a custom function.
Definition at line 3715 of file pbx.c.
References acf_retrieve_docs(), ast_custom_function::acflist, ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_verb, COLOR_BRCYAN, ast_custom_function::docsrc, LOG_ERROR, ast_custom_function::mod, ast_custom_function::name, and term_color().
Referenced by ast_msg_init(), and load_pbx().
03716 { 03717 struct ast_custom_function *cur; 03718 char tmps[80]; 03719 03720 if (!acf) { 03721 return -1; 03722 } 03723 03724 acf->mod = mod; 03725 #ifdef AST_XML_DOCS 03726 acf->docsrc = AST_STATIC_DOC; 03727 #endif 03728 03729 if (acf_retrieve_docs(acf)) { 03730 return -1; 03731 } 03732 03733 AST_RWLIST_WRLOCK(&acf_root); 03734 03735 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03736 if (!strcmp(acf->name, cur->name)) { 03737 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03738 AST_RWLIST_UNLOCK(&acf_root); 03739 return -1; 03740 } 03741 } 03742 03743 /* Store in alphabetical order */ 03744 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03745 if (strcasecmp(acf->name, cur->name) < 0) { 03746 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03747 break; 03748 } 03749 } 03750 AST_RWLIST_TRAVERSE_SAFE_END; 03751 03752 if (!cur) { 03753 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03754 } 03755 03756 AST_RWLIST_UNLOCK(&acf_root); 03757 03758 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03759 03760 return 0; 03761 }
| static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| int | async | |||
| ) | [static] |
Definition at line 10682 of file pbx.c.
References ast_async_goto(), ast_exists_extension(), ast_explicit_goto(), AST_PBX_GOTO_FAILED, ast_channel::caller, ast_channel::context, ast_channel::exten, ast_party_caller::id, ast_party_id::number, S_COR, ast_party_number::str, and ast_party_number::valid.
Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().
10683 { 10684 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 10685 10686 if (!chan) 10687 return -2; 10688 10689 if (context == NULL) 10690 context = chan->context; 10691 if (exten == NULL) 10692 exten = chan->exten; 10693 10694 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 10695 if (ast_exists_extension(chan, context, exten, priority, 10696 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) 10697 return goto_func(chan, context, exten, priority); 10698 else { 10699 return AST_PBX_GOTO_FAILED; 10700 } 10701 }
| static void __ast_internal_context_destroy | ( | struct ast_context * | con | ) | [static] |
Definition at line 9233 of file pbx.c.
References ast_context::alts, ast_free, ast_hashtab_destroy(), AST_LIST_REMOVE_HEAD, ast_rwlock_destroy, destroy_exten(), destroy_pattern_tree(), el, ast_context::ignorepats, ast_context::includes, ast_context::lock, ast_exten::next, ast_ignorepat::next, ast_include::next, ast_context::pattern_tree, ast_exten::peer, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by __ast_context_destroy(), and ast_merge_contexts_and_delete().
09234 { 09235 struct ast_include *tmpi; 09236 struct ast_sw *sw; 09237 struct ast_exten *e, *el, *en; 09238 struct ast_ignorepat *ipi; 09239 struct ast_context *tmp = con; 09240 09241 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 09242 struct ast_include *tmpil = tmpi; 09243 tmpi = tmpi->next; 09244 ast_free(tmpil); 09245 } 09246 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 09247 struct ast_ignorepat *ipl = ipi; 09248 ipi = ipi->next; 09249 ast_free(ipl); 09250 } 09251 if (tmp->registrar) 09252 ast_free(tmp->registrar); 09253 09254 /* destroy the hash tabs */ 09255 if (tmp->root_table) { 09256 ast_hashtab_destroy(tmp->root_table, 0); 09257 } 09258 /* and destroy the pattern tree */ 09259 if (tmp->pattern_tree) 09260 destroy_pattern_tree(tmp->pattern_tree); 09261 09262 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 09263 ast_free(sw); 09264 for (e = tmp->root; e;) { 09265 for (en = e->peer; en;) { 09266 el = en; 09267 en = en->peer; 09268 destroy_exten(el); 09269 } 09270 el = e; 09271 e = e->next; 09272 destroy_exten(el); 09273 } 09274 tmp->root = NULL; 09275 ast_rwlock_destroy(&tmp->lock); 09276 ast_free(tmp); 09277 }
| static enum ast_pbx_result __ast_pbx_run | ( | struct ast_channel * | c, | |
| struct ast_pbx_args * | args | |||
| ) | [static] |
If there is no match at priority 1, it is not a valid extension anymore. Try to continue at "i" (for invalid) or "e" (for exception) or exit if neither exist.
Definition at line 5099 of file pbx.c.
References ast_channel::_softhangup, ast_calloc, ast_cdr_end(), ast_cdr_update(), ast_channel_clear_softhangup(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_check_hangup(), ast_clear_flag, ast_copy_string(), ast_debug, ast_exists_extension(), AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, ast_free, ast_hangup(), ast_log(), ast_matchmore_extension(), ast_opt_end_cdr_before_h_exten, AST_PBX_ERROR, AST_PBX_INCOMPLETE, ast_set2_flag, ast_set_flag, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_strlen_zero(), ast_test_flag, ast_verb, autofallthrough, ast_channel::caller, ast_channel::cdr, collect_digits(), ast_channel::context, ast_pbx::dtimeoutms, ast_channel::exten, ast_party_caller::id, LOG_WARNING, ast_pbx_args::no_hangup_chan, ast_party_id::number, ast_channel::pbx, pbx_builtin_busy(), pbx_builtin_congestion(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_destroy(), ast_channel::priority, raise_exception(), ast_pbx::rtimeoutms, S_COR, set_ext_pri(), status, ast_party_number::str, ast_party_number::valid, and ast_channel::whentohangup.
Referenced by ast_pbx_run_args(), and pbx_thread().
05101 { 05102 int found = 0; /* set if we find at least one match */ 05103 int res = 0; 05104 int autoloopflag; 05105 int error = 0; /* set an error conditions */ 05106 05107 /* A little initial setup here */ 05108 if (c->pbx) { 05109 ast_log(LOG_WARNING, "%s already has PBX structure??\n", ast_channel_name(c)); 05110 /* XXX and now what ? */ 05111 ast_free(c->pbx); 05112 } 05113 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 05114 return -1; 05115 /* Set reasonable defaults */ 05116 c->pbx->rtimeoutms = 10000; 05117 c->pbx->dtimeoutms = 5000; 05118 05119 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 05120 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 05121 05122 if (ast_strlen_zero(c->exten)) { 05123 /* If not successful fall back to 's' - but only if there is no given exten */ 05124 ast_verb(2, "Starting %s at %s,%s,%d failed so falling back to exten 's'\n", ast_channel_name(c), c->context, c->exten, c->priority); 05125 /* XXX the original code used the existing priority in the call to 05126 * ast_exists_extension(), and reset it to 1 afterwards. 05127 * I believe the correct thing is to set it to 1 immediately. 05128 */ 05129 set_ext_pri(c, "s", 1); 05130 } 05131 05132 ast_channel_lock(c); 05133 if (c->cdr) { 05134 /* allow CDR variables that have been collected after channel was created to be visible during call */ 05135 ast_cdr_update(c); 05136 } 05137 ast_channel_unlock(c); 05138 for (;;) { 05139 char dst_exten[256]; /* buffer to accumulate digits */ 05140 int pos = 0; /* XXX should check bounds */ 05141 int digit = 0; 05142 int invalid = 0; 05143 int timeout = 0; 05144 05145 /* loop on priorities in this context/exten */ 05146 while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority, 05147 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 05148 &found, 1))) { 05149 if (!ast_check_hangup(c)) { 05150 ++c->priority; 05151 continue; 05152 } 05153 05154 /* Check softhangup flags. */ 05155 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05156 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05157 continue; 05158 } 05159 if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05160 if (ast_exists_extension(c, c->context, "T", 1, 05161 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05162 set_ext_pri(c, "T", 1); 05163 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05164 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05165 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05166 continue; 05167 } else if (ast_exists_extension(c, c->context, "e", 1, 05168 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05169 raise_exception(c, "ABSOLUTETIMEOUT", 1); 05170 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05171 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05172 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05173 continue; 05174 } 05175 05176 /* Call timed out with no special extension to jump to. */ 05177 error = 1; 05178 break; 05179 } 05180 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n", 05181 c->exten, c->priority); 05182 error = 1; 05183 break; 05184 } /* end while - from here on we can use 'break' to go out */ 05185 if (found && res) { 05186 /* Something bad happened, or a hangup has been requested. */ 05187 if (strchr("0123456789ABCDEF*#", res)) { 05188 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res); 05189 pos = 0; 05190 dst_exten[pos++] = digit = res; 05191 dst_exten[pos] = '\0'; 05192 } else if (res == AST_PBX_INCOMPLETE) { 05193 ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, ast_channel_name(c)); 05194 ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, ast_channel_name(c)); 05195 05196 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */ 05197 if (!ast_matchmore_extension(c, c->context, c->exten, 1, 05198 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05199 invalid = 1; 05200 } else { 05201 ast_copy_string(dst_exten, c->exten, sizeof(dst_exten)); 05202 digit = 1; 05203 pos = strlen(dst_exten); 05204 } 05205 } else { 05206 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, ast_channel_name(c)); 05207 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, ast_channel_name(c)); 05208 05209 if ((res == AST_PBX_ERROR) 05210 && ast_exists_extension(c, c->context, "e", 1, 05211 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05212 /* if we are already on the 'e' exten, don't jump to it again */ 05213 if (!strcmp(c->exten, "e")) { 05214 ast_verb(2, "Spawn extension (%s, %s, %d) exited ERROR while already on 'e' exten on '%s'\n", c->context, c->exten, c->priority, ast_channel_name(c)); 05215 error = 1; 05216 } else { 05217 raise_exception(c, "ERROR", 1); 05218 continue; 05219 } 05220 } 05221 05222 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05223 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05224 continue; 05225 } 05226 if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05227 if (ast_exists_extension(c, c->context, "T", 1, 05228 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05229 set_ext_pri(c, "T", 1); 05230 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05231 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05232 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05233 continue; 05234 } else if (ast_exists_extension(c, c->context, "e", 1, 05235 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05236 raise_exception(c, "ABSOLUTETIMEOUT", 1); 05237 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 05238 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 05239 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05240 continue; 05241 } 05242 /* Call timed out with no special extension to jump to. */ 05243 } 05244 ast_channel_lock(c); 05245 if (c->cdr) { 05246 ast_cdr_update(c); 05247 } 05248 ast_channel_unlock(c); 05249 error = 1; 05250 break; 05251 } 05252 } 05253 if (error) 05254 break; 05255 05256 /*!\note 05257 * We get here on a failure of some kind: non-existing extension or 05258 * hangup. We have options, here. We can either catch the failure 05259 * and continue, or we can drop out entirely. */ 05260 05261 if (invalid 05262 || !ast_exists_extension(c, c->context, c->exten, 1, 05263 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05264 /*!\note 05265 * If there is no match at priority 1, it is not a valid extension anymore. 05266 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if 05267 * neither exist. 05268 */ 05269 if (ast_exists_extension(c, c->context, "i", 1, 05270 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05271 ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, ast_channel_name(c)); 05272 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 05273 set_ext_pri(c, "i", 1); 05274 } else if (ast_exists_extension(c, c->context, "e", 1, 05275 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05276 raise_exception(c, "INVALID", 1); 05277 } else { 05278 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 05279 ast_channel_name(c), c->exten, c->context); 05280 error = 1; /* we know what to do with it */ 05281 break; 05282 } 05283 } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 05284 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 05285 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 05286 } else { /* keypress received, get more digits for a full extension */ 05287 int waittime = 0; 05288 if (digit) 05289 waittime = c->pbx->dtimeoutms; 05290 else if (!autofallthrough) 05291 waittime = c->pbx->rtimeoutms; 05292 if (!waittime) { 05293 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 05294 if (!status) 05295 status = "UNKNOWN"; 05296 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", ast_channel_name(c), status); 05297 if (!strcasecmp(status, "CONGESTION")) 05298 res = pbx_builtin_congestion(c, "10"); 05299 else if (!strcasecmp(status, "CHANUNAVAIL")) 05300 res = pbx_builtin_congestion(c, "10"); 05301 else if (!strcasecmp(status, "BUSY")) 05302 res = pbx_builtin_busy(c, "10"); 05303 error = 1; /* XXX disable message */ 05304 break; /* exit from the 'for' loop */ 05305 } 05306 05307 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 05308 break; 05309 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos])) 05310 timeout = 1; 05311 if (!timeout 05312 && ast_exists_extension(c, c->context, dst_exten, 1, 05313 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */ 05314 set_ext_pri(c, dst_exten, 1); 05315 } else { 05316 /* No such extension */ 05317 if (!timeout && !ast_strlen_zero(dst_exten)) { 05318 /* An invalid extension */ 05319 if (ast_exists_extension(c, c->context, "i", 1, 05320 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05321 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, ast_channel_name(c)); 05322 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 05323 set_ext_pri(c, "i", 1); 05324 } else if (ast_exists_extension(c, c->context, "e", 1, 05325 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05326 raise_exception(c, "INVALID", 1); 05327 } else { 05328 ast_log(LOG_WARNING, 05329 "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n", 05330 dst_exten, c->context); 05331 found = 1; /* XXX disable message */ 05332 break; 05333 } 05334 } else { 05335 /* A simple timeout */ 05336 if (ast_exists_extension(c, c->context, "t", 1, 05337 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05338 ast_verb(3, "Timeout on %s\n", ast_channel_name(c)); 05339 set_ext_pri(c, "t", 1); 05340 } else if (ast_exists_extension(c, c->context, "e", 1, 05341 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05342 raise_exception(c, "RESPONSETIMEOUT", 1); 05343 } else { 05344 ast_log(LOG_WARNING, 05345 "Timeout, but no rule 't' or 'e' in context '%s'\n", 05346 c->context); 05347 found = 1; /* XXX disable message */ 05348 break; 05349 } 05350 } 05351 } 05352 ast_channel_lock(c); 05353 if (c->cdr) { 05354 ast_verb(2, "CDR updated on %s\n",ast_channel_name(c)); 05355 ast_cdr_update(c); 05356 } 05357 ast_channel_unlock(c); 05358 } 05359 } 05360 05361 if (!found && !error) { 05362 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", ast_channel_name(c)); 05363 } 05364 05365 if (!args || !args->no_hangup_chan) { 05366 ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD); 05367 } 05368 05369 if ((!args || !args->no_hangup_chan) 05370 && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) 05371 && ast_exists_extension(c, c->context, "h", 1, 05372 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05373 set_ext_pri(c, "h", 1); 05374 if (c->cdr && ast_opt_end_cdr_before_h_exten) { 05375 ast_cdr_end(c->cdr); 05376 } 05377 while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, 05378 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 05379 &found, 1)) == 0) { 05380 c->priority++; 05381 } 05382 if (found && res) { 05383 /* Something bad happened, or a hangup has been requested. */ 05384 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, ast_channel_name(c)); 05385 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, ast_channel_name(c)); 05386 } 05387 } 05388 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 05389 ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */ 05390 pbx_destroy(c->pbx); 05391 c->pbx = NULL; 05392 05393 if (!args || !args->no_hangup_chan) { 05394 ast_hangup(c); 05395 } 05396 05397 return 0; 05398 }
| static void __init_extensionstate_buf | ( | void | ) | [static] |
| static void __init_switch_data | ( | void | ) | [static] |
| static int _extension_match_core | ( | const char * | pattern, | |
| const char * | data, | |||
| enum ext_match_t | mode | |||
| ) | [static] |
Definition at line 2573 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, LOG_NOTICE, and LOG_WARNING.
Referenced by extension_match_core().
02574 { 02575 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 02576 02577 #ifdef NEED_DEBUG_HERE 02578 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode); 02579 #endif 02580 02581 if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */ 02582 #ifdef NEED_DEBUG_HERE 02583 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n"); 02584 #endif 02585 return 1; 02586 } 02587 02588 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 02589 int ld = strlen(data), lp = strlen(pattern); 02590 02591 if (lp < ld) { /* pattern too short, cannot match */ 02592 #ifdef NEED_DEBUG_HERE 02593 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n"); 02594 #endif 02595 return 0; 02596 } 02597 /* depending on the mode, accept full or partial match or both */ 02598 if (mode == E_MATCH) { 02599 #ifdef NEED_DEBUG_HERE 02600 ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data); 02601 #endif 02602 return !strcmp(pattern, data); /* 1 on match, 0 on fail */ 02603 } 02604 if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */ 02605 #ifdef NEED_DEBUG_HERE 02606 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld); 02607 #endif 02608 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 02609 } else { 02610 #ifdef NEED_DEBUG_HERE 02611 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data); 02612 #endif 02613 return 0; 02614 } 02615 } 02616 pattern++; /* skip leading _ */ 02617 /* 02618 * XXX below we stop at '/' which is a separator for the CID info. However we should 02619 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 02620 */ 02621 while (*data && *pattern && *pattern != '/') { 02622 const char *end; 02623 02624 if (*data == '-') { /* skip '-' in data (just a separator) */ 02625 data++; 02626 continue; 02627 } 02628 switch (toupper(*pattern)) { 02629 case '[': /* a range */ 02630 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */ 02631 if (end == NULL) { 02632 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02633 return 0; /* unconditional failure */ 02634 } 02635 for (pattern++; pattern != end; pattern++) { 02636 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 02637 if (*data >= pattern[0] && *data <= pattern[2]) 02638 break; /* match found */ 02639 else { 02640 pattern += 2; /* skip a total of 3 chars */ 02641 continue; 02642 } 02643 } else if (*data == pattern[0]) 02644 break; /* match found */ 02645 } 02646 if (pattern == end) { 02647 #ifdef NEED_DEBUG_HERE 02648 ast_log(LOG_NOTICE,"return (0) when pattern==end\n"); 02649 #endif 02650 return 0; 02651 } 02652 pattern = end; /* skip and continue */ 02653 break; 02654 case 'N': 02655 if (*data < '2' || *data > '9') { 02656 #ifdef NEED_DEBUG_HERE 02657 ast_log(LOG_NOTICE,"return (0) N is matched\n"); 02658 #endif 02659 return 0; 02660 } 02661 break; 02662 case 'X': 02663 if (*data < '0' || *data > '9') { 02664 #ifdef NEED_DEBUG_HERE 02665 ast_log(LOG_NOTICE,"return (0) X is matched\n"); 02666 #endif 02667 return 0; 02668 } 02669 break; 02670 case 'Z': 02671 if (*data < '1' || *data > '9') { 02672 #ifdef NEED_DEBUG_HERE 02673 ast_log(LOG_NOTICE,"return (0) Z is matched\n"); 02674 #endif 02675 return 0; 02676 } 02677 break; 02678 case '.': /* Must match, even with more digits */ 02679 #ifdef NEED_DEBUG_HERE 02680 ast_log(LOG_NOTICE, "return (1) when '.' is matched\n"); 02681 #endif 02682 return 1; 02683 case '!': /* Early match */ 02684 #ifdef NEED_DEBUG_HERE 02685 ast_log(LOG_NOTICE, "return (2) when '!' is matched\n"); 02686 #endif 02687 return 2; 02688 case ' ': 02689 case '-': /* Ignore these in patterns */ 02690 data--; /* compensate the final data++ */ 02691 break; 02692 default: 02693 if (*data != *pattern) { 02694 #ifdef NEED_DEBUG_HERE 02695 ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern); 02696 #endif 02697 return 0; 02698 } 02699 } 02700 data++; 02701 pattern++; 02702 } 02703 if (*data) /* data longer than pattern, no match */ { 02704 #ifdef NEED_DEBUG_HERE 02705 ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n"); 02706 #endif 02707 return 0; 02708 } 02709 02710 /* 02711 * match so far, but ran off the end of the data. 02712 * Depending on what is next, determine match or not. 02713 */ 02714 if (*pattern == '\0' || *pattern == '/') { /* exact match */ 02715 #ifdef NEED_DEBUG_HERE 02716 ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1); 02717 #endif 02718 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 02719 } else if (*pattern == '!') { /* early match */ 02720 #ifdef NEED_DEBUG_HERE 02721 ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n"); 02722 #endif 02723 return 2; 02724 } else { /* partial match */ 02725 #ifdef NEED_DEBUG_HERE 02726 ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1); 02727 #endif 02728 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 02729 } 02730 }
| static int acf_exception_read | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | buflen | |||
| ) | [static] |
Definition at line 3452 of file pbx.c.
References ast_channel_datastore_find(), ast_copy_string(), pbx_exception::context, ast_datastore::data, exception_store_info, pbx_exception::exten, pbx_exception::priority, and pbx_exception::reason.
03453 { 03454 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03455 struct pbx_exception *exception = NULL; 03456 if (!ds || !ds->data) 03457 return -1; 03458 exception = ds->data; 03459 if (!strcasecmp(data, "REASON")) 03460 ast_copy_string(buf, exception->reason, buflen); 03461 else if (!strcasecmp(data, "CONTEXT")) 03462 ast_copy_string(buf, exception->context, buflen); 03463 else if (!strncasecmp(data, "EXTEN", 5)) 03464 ast_copy_string(buf, exception->exten, buflen); 03465 else if (!strcasecmp(data, "PRIORITY")) 03466 snprintf(buf, buflen, "%d", exception->priority); 03467 else 03468 return -1; 03469 return 0; 03470 }
| static int acf_retrieve_docs | ( | struct ast_custom_function * | acf | ) | [static] |
Definition at line 3670 of file pbx.c.
References ast_custom_function::arguments, ast_free, ast_module_name(), ast_string_field_init, ast_string_field_set, ast_strlen_zero(), AST_XML_DOC, desc, ast_custom_function::desc, ast_custom_function::docsrc, ast_custom_function::mod, ast_custom_function::name, ast_custom_function::seealso, synopsis, ast_custom_function::synopsis, and ast_custom_function::syntax.
Referenced by __ast_custom_function_register().
03671 { 03672 #ifdef AST_XML_DOCS 03673 char *tmpxml; 03674 03675 /* Let's try to find it in the Documentation XML */ 03676 if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) { 03677 return 0; 03678 } 03679 03680 if (ast_string_field_init(acf, 128)) { 03681 return -1; 03682 } 03683 03684 /* load synopsis */ 03685 tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod)); 03686 ast_string_field_set(acf, synopsis, tmpxml); 03687 ast_free(tmpxml); 03688 03689 /* load description */ 03690 tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod)); 03691 ast_string_field_set(acf, desc, tmpxml); 03692 ast_free(tmpxml); 03693 03694 /* load syntax */ 03695 tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod)); 03696 ast_string_field_set(acf, syntax, tmpxml); 03697 ast_free(tmpxml); 03698 03699 /* load arguments */ 03700 tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod)); 03701 ast_string_field_set(acf, arguments, tmpxml); 03702 ast_free(tmpxml); 03703 03704 /* load seealso */ 03705 tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod)); 03706 ast_string_field_set(acf, seealso, tmpxml); 03707 ast_free(tmpxml); 03708 03709 acf->docsrc = AST_XML_DOC; 03710 #endif 03711 03712 return 0; 03713 }
| static struct match_char * add_exten_to_pattern_tree | ( | struct ast_context * | con, | |
| struct ast_exten * | e1, | |||
| int | findonly | |||
| ) | [static, read] |
Definition at line 2251 of file pbx.c.
References add_pattern_node(), already_in_tree(), ARRAY_LEN, ast_copy_string(), ast_debug, ast_log(), pattern_node::buf, ast_exten::cidmatch, match_char::deleted, match_char::exten, ast_exten::exten, get_pattern_node(), LOG_ERROR, LOG_WARNING, ast_exten::matchcid, match_char::next_char, and ast_context::pattern_tree.
Referenced by add_priority(), ast_add_extension2_lockopt(), ast_context_remove_extension_callerid2(), and create_match_char_tree().
02252 { 02253 struct match_char *m1 = NULL; 02254 struct match_char *m2 = NULL; 02255 struct match_char **m0; 02256 const char *pos; 02257 int already; 02258 int pattern = 0; 02259 int idx_cur; 02260 int idx_next; 02261 char extenbuf[512]; 02262 struct pattern_node pat_node[2]; 02263 02264 if (e1->matchcid) { 02265 if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) { 02266 ast_log(LOG_ERROR, 02267 "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", 02268 e1->exten, e1->cidmatch); 02269 return NULL; 02270 } 02271 sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe. We just checked. */ 02272 } else { 02273 ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf)); 02274 } 02275 02276 #ifdef NEED_DEBUG 02277 ast_debug(1, "Adding exten %s to tree\n", extenbuf); 02278 #endif 02279 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */ 02280 m0 = &con->pattern_tree; 02281 already = 1; 02282 02283 pos = extenbuf; 02284 if (*pos == '_') { 02285 pattern = 1; 02286 ++pos; 02287 } 02288 idx_cur = 0; 02289 pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf); 02290 for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) { 02291 idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node); 02292 pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf); 02293 02294 /* See about adding node to tree. */ 02295 m2 = NULL; 02296 if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern)) 02297 && m2->next_char) { 02298 if (!pat_node[idx_next].buf[0]) { 02299 /* 02300 * This is the end of the pattern, but not the end of the tree. 02301 * Mark this node with the exten... a shorter pattern might win 02302 * if the longer one doesn't match. 02303 */ 02304 if (findonly) { 02305 return m2; 02306 } 02307 if (m2->exten) { 02308 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", 02309 m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten); 02310 } 02311 m2->exten = e1; 02312 m2->deleted = 0; 02313 } 02314 m1 = m2->next_char; /* m1 points to the node to compare against */ 02315 m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */ 02316 } else { /* not already OR not m2 OR nor m2->next_char */ 02317 if (m2) { 02318 if (findonly) { 02319 return m2; 02320 } 02321 m1 = m2; /* while m0 stays the same */ 02322 } else { 02323 if (findonly) { 02324 return m1; 02325 } 02326 m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0); 02327 if (!m1) { /* m1 is the node just added */ 02328 return NULL; 02329 } 02330 m0 = &m1->next_char; 02331 } 02332 if (!pat_node[idx_next].buf[0]) { 02333 if (m2 && m2->exten) { 02334 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", 02335 m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten); 02336 } 02337 m1->deleted = 0; 02338 m1->exten = e1; 02339 } 02340 02341 /* The 'already' variable is a mini-optimization designed to make it so that we 02342 * don't have to call already_in_tree when we know it will return false. 02343 */ 02344 already = 0; 02345 } 02346 } 02347 return m1; 02348 }
| static int add_hintdevice | ( | struct ast_hint * | hint, | |
| const char * | devicelist | |||
| ) | [static] |
add hintdevice structure and link it into the container.
Definition at line 1047 of file pbx.c.
References ao2_ref, ao2_t_alloc, ao2_t_link, ao2_t_ref, ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_hintdevice::hint, ast_hintdevice::hintdevice, hintdevice_data, hintdevice_destroy(), parse(), str, and strsep().
Referenced by ast_add_hint(), and ast_change_hint().
01048 { 01049 struct ast_str *str; 01050 char *parse; 01051 char *cur; 01052 struct ast_hintdevice *device; 01053 int devicelength; 01054 01055 if (!hint || !devicelist) { 01056 /* Trying to add garbage? Don't bother. */ 01057 return 0; 01058 } 01059 if (!(str = ast_str_thread_get(&hintdevice_data, 16))) { 01060 return -1; 01061 } 01062 ast_str_set(&str, 0, "%s", devicelist); 01063 parse = ast_str_buffer(str); 01064 01065 while ((cur = strsep(&parse, "&"))) { 01066 devicelength = strlen(cur); 01067 device = ao2_t_alloc(sizeof(*device) + devicelength, hintdevice_destroy, 01068 "allocating a hintdevice structure"); 01069 if (!device) { 01070 return -1; 01071 } 01072 strcpy(device->hintdevice, cur); 01073 ao2_ref(hint, +1); 01074 device->hint = hint; 01075 ao2_t_link(hintdevices, device, "Linking device into hintdevice container."); 01076 ao2_t_ref(device, -1, "hintdevice is linked so we can unref"); 01077 } 01078 01079 return 0; 01080 }
| static struct match_char* add_pattern_node | ( | struct ast_context * | con, | |
| struct match_char * | current, | |||
| const struct pattern_node * | pattern, | |||
| int | is_pattern, | |||
| int | already, | |||
| struct match_char ** | nextcharptr | |||
| ) | [static, read] |
Definition at line 2053 of file pbx.c.
References ast_calloc, pattern_node::buf, insert_in_next_chars_alt_char_list(), match_char::is_pattern, match_char::next_char, ast_context::pattern_tree, pattern_node::specif, match_char::specificity, and match_char::x.
Referenced by add_exten_to_pattern_tree().
02054 { 02055 struct match_char *m; 02056 02057 if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) { 02058 return NULL; 02059 } 02060 02061 /* strcpy is safe here since we know its size and have allocated 02062 * just enough space for when we allocated m 02063 */ 02064 strcpy(m->x, pattern->buf); 02065 02066 /* the specificity scores are the same as used in the old 02067 pattern matcher. */ 02068 m->is_pattern = is_pattern; 02069 if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') { 02070 m->specificity = 0x0832; 02071 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') { 02072 m->specificity = 0x0931; 02073 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') { 02074 m->specificity = 0x0a30; 02075 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') { 02076 m->specificity = 0x18000; 02077 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') { 02078 m->specificity = 0x28000; 02079 } else { 02080 m->specificity = pattern->specif; 02081 } 02082 02083 if (!con->pattern_tree) { 02084 insert_in_next_chars_alt_char_list(&con->pattern_tree, m); 02085 } else { 02086 if (already) { /* switch to the new regime (traversing vs appending)*/ 02087 insert_in_next_chars_alt_char_list(nextcharptr, m); 02088 } else { 02089 insert_in_next_chars_alt_char_list(¤t->next_char, m); 02090 } 02091 } 02092 02093 return m; 02094 }
| static int add_priority | ( | struct ast_context * | con, | |
| struct ast_exten * | tmp, | |||
| struct ast_exten * | el, | |||
| struct ast_exten * | e, | |||
| int | replace | |||
| ) | [static] |
add the extension in the priority chain.
| 0 | on success. | |
| -1 | on failure. |
Definition at line 8436 of file pbx.c.
References add_exten_to_pattern_tree(), ast_add_hint(), ast_change_hint(), ast_free, ast_hashtab_insert_safe(), ast_hashtab_remove_object_via_lookup(), ast_log(), ast_exten::data, ast_exten::datad, match_char::exten, ast_exten::exten, ast_exten::label, LOG_ERROR, LOG_WARNING, ast_context::name, ast_exten::next, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, PRIORITY_HINT, ast_context::root, ast_context::root_table, and match_char::x.
Referenced by ast_add_extension2_lockopt().
08438 { 08439 struct ast_exten *ep; 08440 struct ast_exten *eh=e; 08441 int repeated_label = 0; /* Track if this label is a repeat, assume no. */ 08442 08443 for (ep = NULL; e ; ep = e, e = e->peer) { 08444 if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) { 08445 ast_log(LOG_WARNING, "Extension '%s', priority %d in '%s', label '%s' already in use at " 08446 "priority %d\n", tmp->exten, tmp->priority, con->name, tmp->label, e->priority); 08447 repeated_label = 1; 08448 } 08449 if (e->priority >= tmp->priority) { 08450 break; 08451 } 08452 } 08453 08454 if (repeated_label) { /* Discard the label since it's a repeat. */ 08455 tmp->label = NULL; 08456 } 08457 08458 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 08459 ast_hashtab_insert_safe(eh->peer_table, tmp); 08460 08461 if (tmp->label) { 08462 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08463 } 08464 ep->peer = tmp; 08465 return 0; /* success */ 08466 } 08467 if (e->priority == tmp->priority) { 08468 /* Can't have something exactly the same. Is this a 08469 replacement? If so, replace, otherwise, bonk. */ 08470 if (!replace) { 08471 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 08472 if (tmp->datad) { 08473 tmp->datad(tmp->data); 08474 /* if you free this, null it out */ 08475 tmp->data = NULL; 08476 } 08477 08478 ast_free(tmp); 08479 return -1; 08480 } 08481 /* we are replacing e, so copy the link fields and then update 08482 * whoever pointed to e to point to us 08483 */ 08484 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 08485 tmp->peer = e->peer; /* always meaningful */ 08486 if (ep) { /* We're in the peer list, just insert ourselves */ 08487 ast_hashtab_remove_object_via_lookup(eh->peer_table,e); 08488 08489 if (e->label) { 08490 ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e); 08491 } 08492 08493 ast_hashtab_insert_safe(eh->peer_table,tmp); 08494 if (tmp->label) { 08495 ast_hashtab_insert_safe(eh->peer_label_table,tmp); 08496 } 08497 08498 ep->peer = tmp; 08499 } else if (el) { /* We're the first extension. Take over e's functions */ 08500 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 08501 tmp->peer_table = e->peer_table; 08502 tmp->peer_label_table = e->peer_label_table; 08503 ast_hashtab_remove_object_via_lookup(tmp->peer_table,e); 08504 ast_hashtab_insert_safe(tmp->peer_table,tmp); 08505 if (e->label) { 08506 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 08507 } 08508 if (tmp->label) { 08509 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08510 } 08511 08512 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08513 ast_hashtab_insert_safe(con->root_table, tmp); 08514 el->next = tmp; 08515 /* The pattern trie points to this exten; replace the pointer, 08516 and all will be well */ 08517 if (x) { /* if the trie isn't formed yet, don't sweat this */ 08518 if (x->exten) { /* this test for safety purposes */ 08519 x->exten = tmp; /* replace what would become a bad pointer */ 08520 } else { 08521 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 08522 } 08523 } 08524 } else { /* We're the very first extension. */ 08525 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 08526 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08527 ast_hashtab_insert_safe(con->root_table, tmp); 08528 tmp->peer_table = e->peer_table; 08529 tmp->peer_label_table = e->peer_label_table; 08530 ast_hashtab_remove_object_via_lookup(tmp->peer_table, e); 08531 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08532 if (e->label) { 08533 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 08534 } 08535 if (tmp->label) { 08536 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08537 } 08538 08539 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08540 ast_hashtab_insert_safe(con->root_table, tmp); 08541 con->root = tmp; 08542 /* The pattern trie points to this exten; replace the pointer, 08543 and all will be well */ 08544 if (x) { /* if the trie isn't formed yet; no problem */ 08545 if (x->exten) { /* this test for safety purposes */ 08546 x->exten = tmp; /* replace what would become a bad pointer */ 08547 } else { 08548 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 08549 } 08550 } 08551 } 08552 if (tmp->priority == PRIORITY_HINT) 08553 ast_change_hint(e,tmp); 08554 /* Destroy the old one */ 08555 if (e->datad) 08556 e->datad(e->data); 08557 ast_free(e); 08558 } else { /* Slip ourselves in just before e */ 08559 tmp->peer = e; 08560 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 08561 if (ep) { /* Easy enough, we're just in the peer list */ 08562 if (tmp->label) { 08563 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08564 } 08565 ast_hashtab_insert_safe(eh->peer_table, tmp); 08566 ep->peer = tmp; 08567 } else { /* we are the first in some peer list, so link in the ext list */ 08568 tmp->peer_table = e->peer_table; 08569 tmp->peer_label_table = e->peer_label_table; 08570 e->peer_table = 0; 08571 e->peer_label_table = 0; 08572 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08573 if (tmp->label) { 08574 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08575 } 08576 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08577 ast_hashtab_insert_safe(con->root_table, tmp); 08578 if (el) 08579 el->next = tmp; /* in the middle... */ 08580 else 08581 con->root = tmp; /* ... or at the head */ 08582 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 08583 } 08584 /* And immediately return success. */ 08585 if (tmp->priority == PRIORITY_HINT) { 08586 ast_add_hint(tmp); 08587 } 08588 } 08589 return 0; 08590 }
| static struct match_char * already_in_tree | ( | struct match_char * | current, | |
| char * | pat, | |||
| int | is_pattern | |||
| ) | [static, read] |
Definition at line 1991 of file pbx.c.
References match_char::alt_char, match_char::is_pattern, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01992 { 01993 struct match_char *t; 01994 01995 if (!current) { 01996 return 0; 01997 } 01998 01999 for (t = current; t; t = t->alt_char) { 02000 if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */ 02001 return t; 02002 } 02003 } 02004 02005 return 0; 02006 }
| int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5546 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05547 { 05548 return countcalls; 05549 }
| 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 8271 of file pbx.c.
References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_extension_state(), ast_extension_state_add_destroy(), handle_cli_dialplan_add_extension(), manage_parked_call(), park_add_hints(), park_call_full(), parkinglot_activate(), register_exten(), register_peer_exten(), and RegisterExtension().
08274 { 08275 int ret = -1; 08276 struct ast_context *c; 08277 08278 c = find_context_locked(context); 08279 if (c) { 08280 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 08281 application, data, datad, registrar); 08282 ast_unlock_contexts(); 08283 } 08284 08285 return ret; 08286 }
| 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 8617 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by add_extensions(), ast_add_extension(), context_merge(), load_module(), lua_register_hints(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().
08621 { 08622 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, 08623 application, data, datad, registrar, 1); 08624 }
| static int ast_add_extension2_lockopt | ( | struct ast_context * | con, | |
| int | replace, | |||
| const char * | extension, | |||
| int | priority, | |||
| const char * | label, | |||
| const char * | callerid, | |||
| const char * | application, | |||
| void * | data, | |||
| void(*)(void *) | datad, | |||
| const char * | registrar, | |||
| int | lock_context | |||
| ) | [static] |
Same as ast_add_extension2() but controls the context locking.
Does all the work of ast_add_extension2, but adds an arg to determine if context locking should be done.
Definition at line 8633 of file pbx.c.
References add_exten_to_pattern_tree(), add_priority(), ast_exten::app, ast_add_hint(), ast_calloc, ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_hashtab_create(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, ast_channel::context, ast_exten::data, ast_exten::datad, el, errno, ext_cmp(), ext_strncpy(), ast_exten::exten, ast_channel::exten, hashtab_compare_exten_labels(), hashtab_compare_exten_numbers(), hashtab_compare_extens(), hashtab_hash_extens(), hashtab_hash_labels(), hashtab_hash_priority(), ast_exten::label, LOG_ERROR, ast_exten::matchcid, ast_context::name, ast_exten::next, option_debug, ast_exten::parent, ast_context::pattern_tree, pbx_substitute_variables_helper(), ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, ast_context::root, ast_context::root_table, ast_exten::stuff, and VAR_BUF_SIZE.
Referenced by ast_add_extension2(), and ast_add_extension_nolock().
08637 { 08638 /* 08639 * Sort extensions (or patterns) according to the rules indicated above. 08640 * These are implemented by the function ext_cmp()). 08641 * All priorities for the same ext/pattern/cid are kept in a list, 08642 * using the 'peer' field as a link field.. 08643 */ 08644 struct ast_exten *tmp, *tmp2, *e, *el = NULL; 08645 int res; 08646 int length; 08647 char *p; 08648 char expand_buf[VAR_BUF_SIZE]; 08649 struct ast_exten dummy_exten = {0}; 08650 char dummy_name[1024]; 08651 08652 if (ast_strlen_zero(extension)) { 08653 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", 08654 con->name); 08655 return -1; 08656 } 08657 08658 /* If we are adding a hint evalulate in variables and global variables */ 08659 if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) { 08660 struct ast_channel *c = ast_dummy_channel_alloc(); 08661 08662 if (c) { 08663 ast_copy_string(c->exten, extension, sizeof(c->exten)); 08664 ast_copy_string(c->context, con->name, sizeof(c->context)); 08665 } 08666 pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf)); 08667 application = expand_buf; 08668 if (c) { 08669 ast_channel_unref(c); 08670 } 08671 } 08672 08673 length = sizeof(struct ast_exten); 08674 length += strlen(extension) + 1; 08675 length += strlen(application) + 1; 08676 if (label) 08677 length += strlen(label) + 1; 08678 if (callerid) 08679 length += strlen(callerid) + 1; 08680 else 08681 length ++; /* just the '\0' */ 08682 08683 /* Be optimistic: Build the extension structure first */ 08684 if (!(tmp = ast_calloc(1, length))) 08685 return -1; 08686 08687 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */ 08688 label = 0; 08689 08690 /* use p as dst in assignments, as the fields are const char * */ 08691 p = tmp->stuff; 08692 if (label) { 08693 tmp->label = p; 08694 strcpy(p, label); 08695 p += strlen(label) + 1; 08696 } 08697 tmp->exten = p; 08698 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 08699 tmp->priority = priority; 08700 tmp->cidmatch = p; /* but use p for assignments below */ 08701 08702 /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */ 08703 if (callerid) { 08704 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 08705 tmp->matchcid = 1; 08706 } else { 08707 *p++ = '\0'; 08708 tmp->matchcid = 0; 08709 } 08710 tmp->app = p; 08711 strcpy(p, application); 08712 tmp->parent = con; 08713 tmp->data = data; 08714 tmp->datad = datad; 08715 tmp->registrar = registrar; 08716 08717 if (lock_context) { 08718 ast_wrlock_context(con); 08719 } 08720 08721 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding 08722 an extension, and the trie exists, then we need to incrementally add this pattern to it. */ 08723 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 08724 dummy_exten.exten = dummy_name; 08725 dummy_exten.matchcid = 0; 08726 dummy_exten.cidmatch = 0; 08727 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten); 08728 if (!tmp2) { 08729 /* hmmm, not in the trie; */ 08730 add_exten_to_pattern_tree(con, tmp, 0); 08731 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */ 08732 } 08733 } 08734 res = 0; /* some compilers will think it is uninitialized otherwise */ 08735 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 08736 res = ext_cmp(e->exten, tmp->exten); 08737 if (res == 0) { /* extension match, now look at cidmatch */ 08738 if (!e->matchcid && !tmp->matchcid) 08739 res = 0; 08740 else if (tmp->matchcid && !e->matchcid) 08741 res = 1; 08742 else if (e->matchcid && !tmp->matchcid) 08743 res = -1; 08744 else 08745 res = ext_cmp(e->cidmatch, tmp->cidmatch); 08746 } 08747 if (res >= 0) 08748 break; 08749 } 08750 if (e && res == 0) { /* exact match, insert in the priority chain */ 08751 res = add_priority(con, tmp, el, e, replace); 08752 if (lock_context) { 08753 ast_unlock_context(con); 08754 } 08755 if (res < 0) { 08756 errno = EEXIST; /* XXX do we care ? */ 08757 return 0; /* XXX should we return -1 maybe ? */ 08758 } 08759 } else { 08760 /* 08761 * not an exact match, this is the first entry with this pattern, 08762 * so insert in the main list right before 'e' (if any) 08763 */ 08764 tmp->next = e; 08765 if (el) { /* there is another exten already in this context */ 08766 el->next = tmp; 08767 tmp->peer_table = ast_hashtab_create(13, 08768 hashtab_compare_exten_numbers, 08769 ast_hashtab_resize_java, 08770 ast_hashtab_newsize_java, 08771 hashtab_hash_priority, 08772 0); 08773 tmp->peer_label_table = ast_hashtab_create(7, 08774 hashtab_compare_exten_labels, 08775 ast_hashtab_resize_java, 08776 ast_hashtab_newsize_java, 08777 hashtab_hash_labels, 08778 0); 08779 if (label) { 08780 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08781 } 08782 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08783 } else { /* this is the first exten in this context */ 08784 if (!con->root_table) 08785 con->root_table = ast_hashtab_create(27, 08786 hashtab_compare_extens, 08787 ast_hashtab_resize_java, 08788 ast_hashtab_newsize_java, 08789 hashtab_hash_extens, 08790 0); 08791 con->root = tmp; 08792 con->root->peer_table = ast_hashtab_create(13, 08793 hashtab_compare_exten_numbers, 08794 ast_hashtab_resize_java, 08795 ast_hashtab_newsize_java, 08796 hashtab_hash_priority, 08797 0); 08798 con->root->peer_label_table = ast_hashtab_create(7, 08799 hashtab_compare_exten_labels, 08800 ast_hashtab_resize_java, 08801 ast_hashtab_newsize_java, 08802 hashtab_hash_labels, 08803 0); 08804 if (label) { 08805 ast_hashtab_insert_safe(con->root->peer_label_table, tmp); 08806 } 08807 ast_hashtab_insert_safe(con->root->peer_table, tmp); 08808 08809 } 08810 ast_hashtab_insert_safe(con->root_table, tmp); 08811 if (lock_context) { 08812 ast_unlock_context(con); 08813 } 08814 if (tmp->priority == PRIORITY_HINT) { 08815 ast_add_hint(tmp); 08816 } 08817 } 08818 if (option_debug) { 08819 if (tmp->matchcid) { 08820 ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 08821 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 08822 } else { 08823 ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n", 08824 tmp->exten, tmp->priority, con->name, con); 08825 } 08826 } 08827 08828 if (tmp->matchcid) { 08829 ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n", 08830 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 08831 } else { 08832 ast_verb(3, "Added extension '%s' priority %d to %s\n", 08833 tmp->exten, tmp->priority, con->name); 08834 } 08835 08836 return 0; 08837 }
| 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 8251 of file pbx.c.
References ast_add_extension2_lockopt(), and find_context().
Referenced by ast_merge_contexts_and_delete().
08254 { 08255 int ret = -1; 08256 struct ast_context *c; 08257 08258 c = find_context(context); 08259 if (c) { 08260 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid, 08261 application, data, datad, registrar, 1); 08262 } 08263 08264 return ret; 08265 }
| static int ast_add_hint | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state.
Definition at line 4888 of file pbx.c.
References add_hintdevice(), ao2_alloc, ao2_container_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_debug, ast_extension_state2(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_log(), ast_hint::callbacks, destroy_hint(), ast_hint::exten, hint_id_cmp(), hints, ast_hint::laststate, and LOG_WARNING.
Referenced by add_priority(), and ast_add_extension2_lockopt().
04889 { 04890 struct ast_hint *hint_new; 04891 struct ast_hint *hint_found; 04892 04893 if (!e) { 04894 return -1; 04895 } 04896 04897 /* 04898 * We must create the hint we wish to add before determining if 04899 * it is already in the hints container to avoid possible 04900 * deadlock when getting the current extension state. 04901 */ 04902 hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint); 04903 if (!hint_new) { 04904 return -1; 04905 } 04906 04907 /* Initialize new hint. */ 04908 hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp); 04909 if (!hint_new->callbacks) { 04910 ao2_ref(hint_new, -1); 04911 return -1; 04912 } 04913 hint_new->exten = e; 04914 hint_new->laststate = ast_extension_state2(e); 04915 04916 /* Prevent multiple add hints from adding the same hint at the same time. */ 04917 ao2_lock(hints); 04918 04919 /* Search if hint exists, do nothing */ 04920 hint_found = ao2_find(hints, e, 0); 04921 if (hint_found) { 04922 ao2_ref(hint_found, -1); 04923 ao2_unlock(hints); 04924 ao2_ref(hint_new, -1); 04925 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", 04926 ast_get_extension_name(e), ast_get_extension_app(e)); 04927 return -1; 04928 } 04929 04930 /* Add new hint to the hints container */ 04931 ast_debug(2, "HINTS: Adding hint %s: %s\n", 04932 ast_get_extension_name(e), ast_get_extension_app(e)); 04933 ao2_link(hints, hint_new); 04934 if (add_hintdevice(hint_new, ast_get_extension_app(e))) { 04935 ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n", 04936 ast_get_extension_name(e), 04937 ast_get_context_name(ast_get_extension_context(e))); 04938 } 04939 04940 ao2_unlock(hints); 04941 ao2_ref(hint_new, -1); 04942 04943 return 0; 04944 }
| int ast_async_goto | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Set the channel to next execute the specified dialplan location.
Definition at line 8311 of file pbx.c.
References ast_channel::_state, accountcode, ast_channel::amaflags, amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_accountcode(), ast_channel_alloc, ast_channel_linkedid(), ast_channel_lock, ast_channel_masquerade(), ast_channel_name(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_format_copy(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_strdupa, ast_channel::cdr, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.
Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), dahdi_handle_dtmf(), fax_detect_framehook(), handle_request_bye(), handle_request_refer(), my_handle_dtmf(), pbx_parseable_goto(), process_ast_dsp(), process_sdp(), sip_read(), and socket_process().
08312 { 08313 int res = 0; 08314 struct ast_channel *tmpchan; 08315 struct { 08316 char *accountcode; 08317 char *exten; 08318 char *context; 08319 char *linkedid; 08320 char *name; 08321 struct ast_cdr *cdr; 08322 int amaflags; 08323 int state; 08324 struct ast_format readformat; 08325 struct ast_format writeformat; 08326 } tmpvars = { 0, }; 08327 08328 ast_channel_lock(chan); 08329 if (chan->pbx) { /* This channel is currently in the PBX */ 08330 ast_explicit_goto(chan, context, exten, priority + 1); 08331 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 08332 ast_channel_unlock(chan); 08333 return res; 08334 } 08335 08336 /* In order to do it when the channel doesn't really exist within 08337 * the PBX, we have to make a new channel, masquerade, and start the PBX 08338 * at the new location */ 08339 tmpvars.accountcode = ast_strdupa(ast_channel_accountcode(chan)); 08340 tmpvars.exten = ast_strdupa(chan->exten); 08341 tmpvars.context = ast_strdupa(chan->context); 08342 tmpvars.linkedid = ast_strdupa(ast_channel_linkedid(chan)); 08343 tmpvars.name = ast_strdupa(ast_channel_name(chan)); 08344 tmpvars.amaflags = chan->amaflags; 08345 tmpvars.state = chan->_state; 08346 ast_format_copy(&tmpvars.writeformat, &chan->writeformat); 08347 ast_format_copy(&tmpvars.readformat, &chan->readformat); 08348 tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL; 08349 08350 ast_channel_unlock(chan); 08351 08352 /* Do not hold any channel locks while calling channel_alloc() since the function 08353 * locks the channel container when linking the new channel in. */ 08354 if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) { 08355 ast_cdr_discard(tmpvars.cdr); 08356 return -1; 08357 } 08358 08359 /* copy the cdr info over */ 08360 if (tmpvars.cdr) { 08361 ast_cdr_discard(tmpchan->cdr); 08362 tmpchan->cdr = tmpvars.cdr; 08363 tmpvars.cdr = NULL; 08364 } 08365 08366 /* Make formats okay */ 08367 ast_format_copy(&tmpchan->readformat, &tmpvars.readformat); 08368 ast_format_copy(&tmpchan->writeformat, &tmpvars.writeformat); 08369 08370 /* Setup proper location. Never hold another channel lock while calling this function. */ 08371 ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority); 08372 08373 /* Masquerade into tmp channel */ 08374 if (ast_channel_masquerade(tmpchan, chan)) { 08375 /* Failed to set up the masquerade. It's probably chan_local 08376 * in the middle of optimizing itself out. Sad. :( */ 08377 ast_hangup(tmpchan); 08378 tmpchan = NULL; 08379 res = -1; 08380 } else { 08381 ast_do_masquerade(tmpchan); 08382 /* Start the PBX going on our stolen channel */ 08383 if (ast_pbx_start(tmpchan)) { 08384 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmpchan)); 08385 ast_hangup(tmpchan); 08386 res = -1; 08387 } 08388 } 08389 08390 return res; 08391 }
| int ast_async_goto_by_name | ( | const char * | channame, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Set the channel to next execute the specified dialplan location.
Definition at line 8393 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
08394 { 08395 struct ast_channel *chan; 08396 int res = -1; 08397 08398 if ((chan = ast_channel_get_by_name(channame))) { 08399 res = ast_async_goto(chan, context, exten, priority); 08400 chan = ast_channel_unref(chan); 08401 } 08402 08403 return res; 08404 }
| int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 10708 of file pbx.c.
References __ast_goto_if_exists().
10709 { 10710 return __ast_goto_if_exists(chan, context, exten, priority, 1); 10711 }
| int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 10773 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
10774 { 10775 return pbx_parseable_goto(chan, goto_string, 1); 10776 }
| int ast_build_timing | ( | struct ast_timing * | i, | |
| const char * | info | |||
| ) |
Construct a timing bitmap, for use in time-based conditionals.
| i | Pointer to an ast_timing structure. | |
| info | Standard string containing a timerange, weekday range, monthday range, and month range, as well as an optional timezone. |
| Returns | 1 on success or 0 on failure. |
Definition at line 7895 of file pbx.c.
References ast_strdup, ast_strdupa, ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, strsep(), and ast_timing::timezone.
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
07896 { 07897 char *info; 07898 int j, num_fields, last_sep = -1; 07899 07900 /* Check for empty just in case */ 07901 if (ast_strlen_zero(info_in)) { 07902 return 0; 07903 } 07904 07905 /* make a copy just in case we were passed a static string */ 07906 info = ast_strdupa(info_in); 07907 07908 /* count the number of fields in the timespec */ 07909 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 07910 if (info[j] == ',') { 07911 last_sep = j; 07912 num_fields++; 07913 } 07914 } 07915 07916 /* save the timezone, if it is specified */ 07917 if (num_fields == 5) { 07918 i->timezone = ast_strdup(info + last_sep + 1); 07919 } else { 07920 i->timezone = NULL; 07921 } 07922 07923 /* Assume everything except time */ 07924 i->monthmask = 0xfff; /* 12 bits */ 07925 i->daymask = 0x7fffffffU; /* 31 bits */ 07926 i->dowmask = 0x7f; /* 7 bits */ 07927 /* on each call, use strsep() to move info to the next argument */ 07928 get_timerange(i, strsep(&info, "|,")); 07929 if (info) 07930 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 07931 if (info) 07932 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 07933 if (info) 07934 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 07935 return 1; 07936 }
| 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 5041 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), analog_ss_thread(), background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), handle_link_data(), handle_link_phone_dtmf(), leave_voicemail(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), skinny_ss(), and valid_exit().
05042 { 05043 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 05044 }
Change hint for an extension.
Definition at line 4947 of file pbx.c.
References add_hintdevice(), ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_log(), ast_hint::exten, hints, LOG_WARNING, OBJ_UNLINK, and remove_hintdevice().
Referenced by add_priority().
04948 { 04949 struct ast_hint *hint; 04950 04951 if (!oe || !ne) { 04952 return -1; 04953 } 04954 04955 ao2_lock(hints);/* Locked to hold off others while we move the hint around. */ 04956 04957 /* 04958 * Unlink the hint from the hints container as the extension 04959 * name (which is the hash value) could change. 04960 */ 04961 hint = ao2_find(hints, oe, OBJ_UNLINK); 04962 if (!hint) { 04963 ao2_unlock(hints); 04964 return -1; 04965 } 04966 04967 remove_hintdevice(hint); 04968 04969 /* Update the hint and put it back in the hints container. */ 04970 ao2_lock(hint); 04971 hint->exten = ne; 04972 ao2_unlock(hint); 04973 ao2_link(hints, hint); 04974 if (add_hintdevice(hint, ast_get_extension_app(ne))) { 04975 ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n", 04976 ast_get_extension_name(ne), 04977 ast_get_context_name(ast_get_extension_context(ne))); 04978 } 04979 04980 ao2_unlock(hints); 04981 ao2_ref(hint, -1); 04982 04983 return 0; 04984 }
| int ast_check_timing | ( | const struct ast_timing * | i | ) |
Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified.
| i | Pointer to an ast_timing structure. |
| Returns | 1, if the time matches or 0, if the current time falls outside of the specified range. |
Definition at line 7938 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
07939 { 07940 return ast_check_timing2(i, ast_tvnow()); 07941 }
| int ast_check_timing2 | ( | const struct ast_timing * | i, | |
| const struct timeval | tv | |||
| ) |
Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified.
| i | Pointer to an ast_timing structure. | |
| tv | Specified time |
| Returns | 1, if the time matches or 0, if the time falls outside of the specified range. |
Definition at line 7943 of file pbx.c.
References ast_localtime(), ast_log(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, ast_timing::monthmask, ast_timing::timezone, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and ast_tm::tm_wday.
Referenced by ast_check_timing(), and pbx_builtin_gotoiftime().
07944 { 07945 struct ast_tm tm; 07946 07947 ast_localtime(&tv, &tm, i->timezone); 07948 07949 /* If it's not the right month, return */ 07950 if (!(i->monthmask & (1 << tm.tm_mon))) 07951 return 0; 07952 07953 /* If it's not that time of the month.... */ 07954 /* Warning, tm_mday has range 1..31! */ 07955 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 07956 return 0; 07957 07958 /* If it's not the right day of the week */ 07959 if (!(i->dowmask & (1 << tm.tm_wday))) 07960 return 0; 07961 07962 /* Sanity check the hour just to be safe */ 07963 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 07964 ast_log(LOG_WARNING, "Insane time...\n"); 07965 return 0; 07966 } 07967 07968 /* Now the tough part, we calculate if it fits 07969 in the right time based on min/hour */ 07970 if (!(i->minmask[tm.tm_hour * 2 + (tm.tm_min >= 30 ? 1 : 0)] & (1 << (tm.tm_min >= 30 ? tm.tm_min - 30 : tm.tm_min)))) 07971 return 0; 07972 07973 /* If we got this far, then we're good */ 07974 return 1; 07975 }
| char* ast_complete_applications | ( | const char * | line, | |
| const char * | word, | |||
| int | state | |||
| ) |
Command completion for the list of installed applications.
This can be called from a CLI command completion function that wants to complete from the list of available applications.
Definition at line 10778 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, and ast_app::name.
Referenced by handle_orig(), and handle_show_application().
10779 { 10780 struct ast_app *app = NULL; 10781 int which = 0; 10782 char *ret = NULL; 10783 size_t wordlen = strlen(word); 10784 10785 AST_RWLIST_RDLOCK(&apps); 10786 AST_RWLIST_TRAVERSE(&apps, app, list) { 10787 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 10788 ret = ast_strdup(app->name); 10789 break; 10790 } 10791 } 10792 AST_RWLIST_UNLOCK(&apps); 10793 10794 return ret; 10795 }
| 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 |
| 0 | on success | |
| -1 | on failure |
Definition at line 8179 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
08180 { 08181 int ret = -1; 08182 struct ast_context *c; 08183 08184 c = find_context_locked(context); 08185 if (c) { 08186 ret = ast_context_add_ignorepat2(c, value, registrar); 08187 ast_unlock_contexts(); 08188 } 08189 return ret; 08190 }
| int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | value, | |||
| const char * | registrar | |||
| ) |
Definition at line 8192 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_compile_ael2(), ast_context_add_ignorepat(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
08193 { 08194 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 08195 int length; 08196 char *pattern; 08197 length = sizeof(struct ast_ignorepat); 08198 length += strlen(value) + 1; 08199 if (!(ignorepat = ast_calloc(1, length))) 08200 return -1; 08201 /* The cast to char * is because we need to write the initial value. 08202 * The field is not supposed to be modified otherwise. Also, gcc 4.2 08203 * sees the cast as dereferencing a type-punned pointer and warns about 08204 * it. This is the workaround (we're telling gcc, yes, that's really 08205 * what we wanted to do). 08206 */ 08207 pattern = (char *) ignorepat->pattern; 08208 strcpy(pattern, value); 08209 ignorepat->next = NULL; 08210 ignorepat->registrar = registrar; 08211 ast_wrlock_context(con); 08212 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 08213 ignorepatl = ignorepatc; 08214 if (!strcasecmp(ignorepatc->pattern, value)) { 08215 /* Already there */ 08216 ast_unlock_context(con); 08217 errno = EEXIST; 08218 return -1; 08219 } 08220 } 08221 if (ignorepatl) 08222 ignorepatl->next = ignorepat; 08223 else 08224 con->ignorepats = ignorepat; 08225 ast_unlock_context(con); 08226 return 0; 08227 08228 }
| 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 |
| 0 | on success | |
| -1 | on error |
Definition at line 7723 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
07724 { 07725 int ret = -1; 07726 struct ast_context *c; 07727 07728 c = find_context_locked(context); 07729 if (c) { 07730 ret = ast_context_add_include2(c, include, registrar); 07731 ast_unlock_contexts(); 07732 } 07733 return ret; 07734 }
| 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 |
| 0 | on success | |
| -1 | on failure |
Definition at line 7992 of file pbx.c.
References ast_build_timing(), ast_calloc, ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), errno, ast_include::hastime, ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, ast_include::rname, ast_include::stuff, and ast_include::timing.
Referenced by ast_compile_ael2(), ast_context_add_include(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
07994 { 07995 struct ast_include *new_include; 07996 char *c; 07997 struct ast_include *i, *il = NULL; /* include, include_last */ 07998 int length; 07999 char *p; 08000 08001 length = sizeof(struct ast_include); 08002 length += 2 * (strlen(value) + 1); 08003 08004 /* allocate new include structure ... */ 08005 if (!(new_include = ast_calloc(1, length))) 08006 return -1; 08007 /* Fill in this structure. Use 'p' for assignments, as the fields 08008 * in the structure are 'const char *' 08009 */ 08010 p = new_include->stuff; 08011 new_include->name = p; 08012 strcpy(p, value); 08013 p += strlen(value) + 1; 08014 new_include->rname = p; 08015 strcpy(p, value); 08016 /* Strip off timing info, and process if it is there */ 08017 if ( (c = strchr(p, ',')) ) { 08018 *c++ = '\0'; 08019 new_include->hastime = ast_build_timing(&(new_include->timing), c); 08020 } 08021 new_include->next = NULL; 08022 new_include->registrar = registrar; 08023 08024 ast_wrlock_context(con); 08025 08026 /* ... go to last include and check if context is already included too... */ 08027 for (i = con->includes; i; i = i->next) { 08028 if (!strcasecmp(i->name, new_include->name)) { 08029 ast_destroy_timing(&(new_include->timing)); 08030 ast_free(new_include); 08031 ast_unlock_context(con); 08032 errno = EEXIST; 08033 return -1; 08034 } 08035 il = i; 08036 } 08037 08038 /* ... include new context into context list, unlock, return */ 08039 if (il) 08040 il->next = new_include; 08041 else 08042 con->includes = new_include; 08043 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 08044 08045 ast_unlock_context(con); 08046 08047 return 0; 08048 }
| 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 |
| 0 | on success | |
| -1 | on failure |
Definition at line 8055 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
08056 { 08057 int ret = -1; 08058 struct ast_context *c; 08059 08060 c = find_context_locked(context); 08061 if (c) { /* found, add switch to this context */ 08062 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 08063 ast_unlock_contexts(); 08064 } 08065 return ret; 08066 }
| 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 8075 of file pbx.c.
References ast_context::alts, ast_calloc, ast_free, ast_get_context_name(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, errno, ast_sw::eval, ast_sw::name, ast_sw::registrar, and ast_sw::stuff.
Referenced by ast_compile_ael2(), ast_context_add_switch(), context_merge_incls_swits_igps_other_registrars(), lua_register_switches(), and pbx_load_config().
08077 { 08078 struct ast_sw *new_sw; 08079 struct ast_sw *i; 08080 int length; 08081 char *p; 08082 08083 length = sizeof(struct ast_sw); 08084 length += strlen(value) + 1; 08085 if (data) 08086 length += strlen(data); 08087 length++; 08088 08089 /* allocate new sw structure ... */ 08090 if (!(new_sw = ast_calloc(1, length))) 08091 return -1; 08092 /* ... fill in this structure ... */ 08093 p = new_sw->stuff; 08094 new_sw->name = p; 08095 strcpy(new_sw->name, value); 08096 p += strlen(value) + 1; 08097 new_sw->data = p; 08098 if (data) { 08099 strcpy(new_sw->data, data); 08100 p += strlen(data) + 1; 08101 } else { 08102 strcpy(new_sw->data, ""); 08103 p++; 08104 } 08105 new_sw->eval = eval; 08106 new_sw->registrar = registrar; 08107 08108 /* ... try to lock this context ... */ 08109 ast_wrlock_context(con); 08110 08111 /* ... go to last sw and check if context is already swd too... */ 08112 AST_LIST_TRAVERSE(&con->alts, i, list) { 08113 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 08114 ast_free(new_sw); 08115 ast_unlock_context(con); 08116 errno = EEXIST; 08117 return -1; 08118 } 08119 } 08120 08121 /* ... sw new context into context list, unlock, return */ 08122 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 08123 08124 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 08125 08126 ast_unlock_context(con); 08127 08128 return 0; 08129 }
| 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 |
Definition at line 9438 of file pbx.c.
References __ast_context_destroy(), ast_unlock_contexts(), ast_wrlock_contexts(), contexts, and contexts_table.
Referenced by __unload_module(), ast_features_reload(), cleanup_stale_contexts(), remove_dead_dialplan_useage(), sla_destroy(), and unload_module().
09439 { 09440 ast_wrlock_contexts(); 09441 __ast_context_destroy(contexts, contexts_table, con,registrar); 09442 ast_unlock_contexts(); 09443 }
| struct ast_context* ast_context_find | ( | const char * | name | ) | [read] |
Find a context.
| name | name of the context to find |
Definition at line 2777 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::name, and fake_context::name.
Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_features_reload(), ast_ignore_pattern(), cleanup_stale_contexts(), handle_cli_dialplan_add_extension(), isexten_function_read(), manage_parkinglot(), parked_call_exec(), register_exten(), register_peer_exten(), remove_dead_dialplan_useage(), unload_module(), and unregister_exten().
02778 { 02779 struct ast_context *tmp; 02780 struct fake_context item; 02781 02782 if (!name) { 02783 return NULL; 02784 } 02785 ast_rdlock_contexts(); 02786 if (contexts_table) { 02787 ast_copy_string(item.name, name, sizeof(item.name)); 02788 tmp = ast_hashtab_lookup(contexts_table, &item); 02789 } else { 02790 tmp = NULL; 02791 while ((tmp = ast_walk_contexts(tmp))) { 02792 if (!strcasecmp(name, tmp->name)) { 02793 break; 02794 } 02795 } 02796 } 02797 ast_unlock_contexts(); 02798 return tmp; 02799 }
| 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 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 7324 of file pbx.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_insert_immediate(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_mutex_init, ast_rdlock_contexts(), ast_rwlock_init, ast_strdup, ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), contexts, contexts_table, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, ast_context::macrolock, ast_context::name, fake_context::name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by ast_compile_ael2(), config_parse_variables(), context_merge(), handle_cli_dialplan_add_extension(), load_module(), lua_register_hints(), lua_register_switches(), manage_parked_call(), parkinglot_activate(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().
07325 { 07326 struct ast_context *tmp, **local_contexts; 07327 struct fake_context search; 07328 int length = sizeof(struct ast_context) + strlen(name) + 1; 07329 07330 if (!contexts_table) { 07331 /* Protect creation of contexts_table from reentrancy. */ 07332 ast_wrlock_contexts(); 07333 if (!contexts_table) { 07334 contexts_table = ast_hashtab_create(17, 07335 ast_hashtab_compare_contexts, 07336 ast_hashtab_resize_java, 07337 ast_hashtab_newsize_java, 07338 ast_hashtab_hash_contexts, 07339 0); 07340 } 07341 ast_unlock_contexts(); 07342 } 07343 07344 ast_copy_string(search.name, name, sizeof(search.name)); 07345 if (!extcontexts) { 07346 ast_rdlock_contexts(); 07347 local_contexts = &contexts; 07348 tmp = ast_hashtab_lookup(contexts_table, &search); 07349 ast_unlock_contexts(); 07350 if (tmp) { 07351 tmp->refcount++; 07352 return tmp; 07353 } 07354 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 07355 local_contexts = extcontexts; 07356 tmp = ast_hashtab_lookup(exttable, &search); 07357 if (tmp) { 07358 tmp->refcount++; 07359 return tmp; 07360 } 07361 } 07362 07363 if ((tmp = ast_calloc(1, length))) { 07364 ast_rwlock_init(&tmp->lock); 07365 ast_mutex_init(&tmp->macrolock); 07366 strcpy(tmp->name, name); 07367 tmp->root = NULL; 07368 tmp->root_table = NULL; 07369 tmp->registrar = ast_strdup(registrar); 07370 tmp->includes = NULL; 07371 tmp->ignorepats = NULL; 07372 tmp->refcount = 1; 07373 } else { 07374 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 07375 return NULL; 07376 } 07377 07378 if (!extcontexts) { 07379 ast_wrlock_contexts(); 07380 tmp->next = *local_contexts; 07381 *local_contexts = tmp; 07382 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 07383 ast_unlock_contexts(); 07384 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 07385 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07386 } else { 07387 tmp->next = *local_contexts; 07388 if (exttable) 07389 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 07390 07391 *local_contexts = tmp; 07392 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 07393 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07394 } 07395 return tmp; 07396 }
| int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 5924 of file pbx.c.
References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
05925 { 05926 struct ast_context *c; 05927 int ret = -1; 05928 05929 c = find_context_locked(context); 05930 if (c) { 05931 ast_unlock_contexts(); 05932 05933 /* if we found context, lock macrolock */ 05934 ret = ast_mutex_lock(&c->macrolock); 05935 } 05936 05937 return ret; 05938 }
| int ast_context_remove_extension | ( | const char * | context, | |
| const char * | extension, | |||
| int | priority, | |||
| const char * | registrar | |||
| ) |
Simply remove extension from context.
Definition at line 5729 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), remove_exten_if_exist(), unregister_exten(), and UnregisterExtension().
05730 { 05731 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 05732 }
| 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 5759 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by manage_parkinglot(), parked_call_exec(), and unload_module().
05760 { 05761 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 05762 }
| 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 5734 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().
05735 { 05736 int ret = -1; /* default error return */ 05737 struct ast_context *c; 05738 05739 c = find_context_locked(context); 05740 if (c) { /* ... remove extension ... */ 05741 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, 05742 matchcallerid, registrar, 0); 05743 ast_unlock_contexts(); 05744 } 05745 05746 return ret; 05747 }
| 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 5764 of file pbx.c.
References add_exten_to_pattern_tree(), ast_copy_string(), ast_hashtab_insert_immediate(), ast_hashtab_lookup(), ast_hashtab_remove_this_object(), ast_hashtab_size(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, match_char::deleted, destroy_exten(), match_char::exten, ast_exten::exten, exten, ast_exten::label, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_context::pattern_tree, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, ast_context::root, ast_context::root_table, and match_char::x.
Referenced by __ast_context_destroy(), ast_context_remove_extension2(), and ast_context_remove_extension_callerid().
05765 { 05766 struct ast_exten *exten, *prev_exten = NULL; 05767 struct ast_exten *peer; 05768 struct ast_exten ex, *exten2, *exten3; 05769 char dummy_name[1024]; 05770 struct ast_exten *previous_peer = NULL; 05771 struct ast_exten *next_peer = NULL; 05772 int found = 0; 05773 05774 if (!already_locked) 05775 ast_wrlock_context(con); 05776 05777 /* Handle this is in the new world */ 05778 05779 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 05780 * peers, not just those matching the callerid. */ 05781 #ifdef NEED_DEBUG 05782 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 05783 #endif 05784 #ifdef CONTEXT_DEBUG 05785 check_contexts(__FILE__, __LINE__); 05786 #endif 05787 /* find this particular extension */ 05788 ex.exten = dummy_name; 05789 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 05790 ex.cidmatch = callerid; 05791 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 05792 exten = ast_hashtab_lookup(con->root_table, &ex); 05793 if (exten) { 05794 if (priority == 0) { 05795 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05796 if (!exten2) 05797 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); 05798 if (con->pattern_tree) { 05799 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05800 05801 if (x->exten) { /* this test for safety purposes */ 05802 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05803 x->exten = 0; /* get rid of what will become a bad pointer */ 05804 } else { 05805 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 05806 } 05807 } 05808 } else { 05809 ex.priority = priority; 05810 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 05811 if (exten2) { 05812 05813 if (exten2->label) { /* if this exten has a label, remove that, too */ 05814 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 05815 if (!exten3) 05816 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); 05817 } 05818 05819 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 05820 if (!exten3) 05821 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); 05822 if (exten2 == exten && exten2->peer) { 05823 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05824 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 05825 } 05826 if (ast_hashtab_size(exten->peer_table) == 0) { 05827 /* well, if the last priority of an exten is to be removed, 05828 then, the extension is removed, too! */ 05829 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 05830 if (!exten3) 05831 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 05832 if (con->pattern_tree) { 05833 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05834 if (x->exten) { /* this test for safety purposes */ 05835 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05836 x->exten = 0; /* get rid of what will become a bad pointer */ 05837 } 05838 } 05839 } 05840 } else { 05841 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 05842 priority, exten->exten, con->name); 05843 } 05844 } 05845 } else { 05846 /* hmmm? this exten is not in this pattern tree? */ 05847 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 05848 extension, con->name); 05849 } 05850 #ifdef NEED_DEBUG 05851 if (con->pattern_tree) { 05852 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 05853 log_match_char_tree(con->pattern_tree, " "); 05854 } 05855 #endif 05856 05857 /* scan the extension list to find first matching extension-registrar */ 05858 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 05859 if (!strcmp(exten->exten, extension) && 05860 (!registrar || !strcmp(exten->registrar, registrar)) && 05861 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 05862 break; 05863 } 05864 if (!exten) { 05865 /* we can't find right extension */ 05866 if (!already_locked) 05867 ast_unlock_context(con); 05868 return -1; 05869 } 05870 05871 /* scan the priority list to remove extension with exten->priority == priority */ 05872 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 05873 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))); 05874 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 05875 if ((priority == 0 || peer->priority == priority) && 05876 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 05877 (!registrar || !strcmp(peer->registrar, registrar) )) { 05878 found = 1; 05879 05880 /* we are first priority extension? */ 05881 if (!previous_peer) { 05882 /* 05883 * We are first in the priority chain, so must update the extension chain. 05884 * The next node is either the next priority or the next extension 05885 */ 05886 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 05887 if (peer->peer) { 05888 /* move the peer_table and peer_label_table down to the next peer, if 05889 it is there */ 05890 peer->peer->peer_table = peer->peer_table; 05891 peer->peer->peer_label_table = peer->peer_label_table; 05892 peer->peer_table = NULL; 05893 peer->peer_label_table = NULL; 05894 } 05895 if (!prev_exten) { /* change the root... */ 05896 con->root = next_node; 05897 } else { 05898 prev_exten->next = next_node; /* unlink */ 05899 } 05900 if (peer->peer) { /* update the new head of the pri list */ 05901 peer->peer->next = peer->next; 05902 } 05903 } else { /* easy, we are not first priority in extension */ 05904 previous_peer->peer = peer->peer; 05905 } 05906 05907 /* now, free whole priority extension */ 05908 destroy_exten(peer); 05909 } else { 05910 previous_peer = peer; 05911 } 05912 } 05913 if (!already_locked) 05914 ast_unlock_context(con); 05915 return found ? 0 : -1; 05916 }
| int ast_context_remove_ignorepat | ( | const char * | context, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 8135 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
08136 { 08137 int ret = -1; 08138 struct ast_context *c; 08139 08140 c = find_context_locked(context); 08141 if (c) { 08142 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 08143 ast_unlock_contexts(); 08144 } 08145 return ret; 08146 }
| int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
| const char * | ignorepat, | |||
| const char * | registrar | |||
| ) |
Definition at line 8148 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().
08149 { 08150 struct ast_ignorepat *ip, *ipl = NULL; 08151 08152 ast_wrlock_context(con); 08153 08154 for (ip = con->ignorepats; ip; ip = ip->next) { 08155 if (!strcmp(ip->pattern, ignorepat) && 08156 (!registrar || (registrar == ip->registrar))) { 08157 if (ipl) { 08158 ipl->next = ip->next; 08159 ast_free(ip); 08160 } else { 08161 con->ignorepats = ip->next; 08162 ast_free(ip); 08163 } 08164 ast_unlock_context(con); 08165 return 0; 08166 } 08167 ipl = ip; 08168 } 08169 08170 ast_unlock_context(con); 08171 errno = EINVAL; 08172 return -1; 08173 }
| 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 5622 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
05623 { 05624 int ret = -1; 05625 struct ast_context *c; 05626 05627 c = find_context_locked(context); 05628 if (c) { 05629 /* found, remove include from this context ... */ 05630 ret = ast_context_remove_include2(c, include, registrar); 05631 ast_unlock_contexts(); 05632 } 05633 return ret; 05634 }
| 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 5645 of file pbx.c.
References ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, and ast_include::timing.
Referenced by ast_context_remove_include().
05646 { 05647 struct ast_include *i, *pi = NULL; 05648 int ret = -1; 05649 05650 ast_wrlock_context(con); 05651 05652 /* find our include */ 05653 for (i = con->includes; i; pi = i, i = i->next) { 05654 if (!strcmp(i->name, include) && 05655 (!registrar || !strcmp(i->registrar, registrar))) { 05656 /* remove from list */ 05657 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 05658 if (pi) 05659 pi->next = i->next; 05660 else 05661 con->includes = i->next; 05662 /* free include and return */ 05663 ast_destroy_timing(&(i->timing)); 05664 ast_free(i); 05665 ret = 0; 05666 break; 05667 } 05668 } 05669 05670 ast_unlock_context(con); 05671 05672 return ret; 05673 }
| int ast_context_remove_switch | ( | const char * | context, | |
| const char * | sw, | |||
| const char * | data, | |||
| const char * | registrar | |||
| ) |
Remove a switch.
Definition at line 5680 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
05681 { 05682 int ret = -1; /* default error return */ 05683 struct ast_context *c; 05684 05685 c = find_context_locked(context); 05686 if (c) { 05687 /* remove switch from this context ... */ 05688 ret = ast_context_remove_switch2(c, sw, data, registrar); 05689 ast_unlock_contexts(); 05690 } 05691 return ret; 05692 }
| 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 5702 of file pbx.c.
References ast_context::alts, ast_free, ast_get_context_name(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, ast_sw::name, and ast_sw::registrar.
Referenced by ast_context_remove_switch().
05703 { 05704 struct ast_sw *i; 05705 int ret = -1; 05706 05707 ast_wrlock_context(con); 05708 05709 /* walk switches */ 05710 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 05711 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 05712 (!registrar || !strcmp(i->registrar, registrar))) { 05713 /* found, remove from list */ 05714 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 05715 AST_LIST_REMOVE_CURRENT(list); 05716 ast_free(i); /* free switch and return */ 05717 ret = 0; 05718 break; 05719 } 05720 } 05721 AST_LIST_TRAVERSE_SAFE_END; 05722 05723 ast_unlock_context(con); 05724 05725 return ret; 05726 }
| int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 5945 of file pbx.c.
References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
05946 { 05947 struct ast_context *c; 05948 int ret = -1; 05949 05950 c = find_context_locked(context); 05951 if (c) { 05952 ast_unlock_contexts(); 05953 05954 /* if we found context, unlock macrolock */ 05955 ret = ast_mutex_unlock(&c->macrolock); 05956 } 05957 05958 return ret; 05959 }
| 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 10663 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().
10664 { 10665 struct ast_include *inc = NULL; 10666 int res = 0; 10667 10668 while ( (inc = ast_walk_context_includes(con, inc)) ) { 10669 if (ast_context_find(inc->rname)) 10670 continue; 10671 10672 res = -1; 10673 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 10674 ast_get_context_name(con), inc->rname); 10675 break; 10676 } 10677 10678 return res; 10679 }
| struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 3626 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_read2(), ast_func_write(), config_curl(), destroy_curl(), handle_show_function(), op_func(), realtime_curl(), realtime_multi_curl(), require_curl(), store_curl(), update2_curl(), and update_curl().
03627 { 03628 struct ast_custom_function *acf = NULL; 03629 03630 AST_RWLIST_RDLOCK(&acf_root); 03631 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03632 if (!strcmp(name, acf->name)) 03633 break; 03634 } 03635 AST_RWLIST_UNLOCK(&acf_root); 03636 03637 return acf; 03638 }
| int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3640 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, AST_XML_DOC, ast_custom_function::docsrc, and ast_custom_function::name.
Referenced by _unload_module(), load_module(), reload(), and unload_module().
03641 { 03642 struct ast_custom_function *cur; 03643 03644 if (!acf) { 03645 return -1; 03646 } 03647 03648 AST_RWLIST_WRLOCK(&acf_root); 03649 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03650 #ifdef AST_XML_DOCS 03651 if (cur->docsrc == AST_XML_DOC) { 03652 ast_string_field_free_memory(acf); 03653 } 03654 #endif 03655 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03656 } 03657 AST_RWLIST_UNLOCK(&acf_root); 03658 03659 return cur ? 0 : -1; 03660 }
| int ast_destroy_timing | ( | struct ast_timing * | i | ) |
Deallocates memory structures associated with a timing bitmap.
| i | Pointer to an ast_timing structure. |
| 0 | success | |
| non-zero | failure (number suitable to pass to |
Definition at line 7977 of file pbx.c.
References ast_free, and ast_timing::timezone.
Referenced by ast_context_add_include2(), ast_context_remove_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
07978 { 07979 if (i->timezone) { 07980 ast_free(i->timezone); 07981 i->timezone = NULL; 07982 } 07983 return 0; 07984 }
| enum ast_extension_states ast_devstate_to_extenstate | ( | enum ast_device_state | devstate | ) |
Map devstate to an extension state.
| [in] | devstate | device state |
Definition at line 4449 of file pbx.c.
References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_TOTAL, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, and AST_EXTENSION_UNAVAILABLE.
Referenced by ast_extension_state3().
04450 { 04451 switch (devstate) { 04452 case AST_DEVICE_ONHOLD: 04453 return AST_EXTENSION_ONHOLD; 04454 case AST_DEVICE_BUSY: 04455 return AST_EXTENSION_BUSY; 04456 case AST_DEVICE_UNKNOWN: 04457 return AST_EXTENSION_NOT_INUSE; 04458 case AST_DEVICE_UNAVAILABLE: 04459 case AST_DEVICE_INVALID: 04460 return AST_EXTENSION_UNAVAILABLE; 04461 case AST_DEVICE_RINGINUSE: 04462 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04463 case AST_DEVICE_RINGING: 04464 return AST_EXTENSION_RINGING; 04465 case AST_DEVICE_INUSE: 04466 return AST_EXTENSION_INUSE; 04467 case AST_DEVICE_NOT_INUSE: 04468 return AST_EXTENSION_NOT_INUSE; 04469 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04470 break; 04471 } 04472 04473 return AST_EXTENSION_NOT_INUSE; 04474 }
| 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 5026 of file pbx.c.
References E_MATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), action_originate(), analog_ss_thread(), answer_call(), ast_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), fax_detect_framehook(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), 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(), my_handle_dtmf(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), rpt_exec(), setsubstate(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), try_calling(), vm_authenticate(), and waitstream_core().
05027 { 05028 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 05029 }
| int ast_explicit_goto | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 8288 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(), msg_route(), pbx_parseable_goto(), and return_exec().
08289 { 08290 if (!chan) 08291 return -1; 08292 08293 ast_channel_lock(chan); 08294 08295 if (!ast_strlen_zero(context)) 08296 ast_copy_string(chan->context, context, sizeof(chan->context)); 08297 if (!ast_strlen_zero(exten)) 08298 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08299 if (priority > -1) { 08300 chan->priority = priority; 08301 /* see flag description in channel.h for explanation */ 08302 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 08303 chan->priority--; 08304 } 08305 08306 ast_channel_unlock(chan); 08307 08308 return 0; 08309 }
| int ast_extension_close | ( | const char * | pattern, | |
| const char * | data, | |||
| int | needmore | |||
| ) |
Definition at line 2754 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().
02755 { 02756 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02757 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02758 return extension_match_core(pattern, data, needmore); 02759 }
| 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 2556 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02557 { 02558 return ext_cmp(a, b); 02559 }
| 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 2749 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().
02750 { 02751 return extension_match_core(pattern, data, E_MATCH); 02752 }
| 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 4519 of file pbx.c.
References ast_exten::app, ast_add_extension(), ast_extension_state2(), ast_free_ptr, ast_hint_extension(), ast_strdup, ast_exten::cidmatch, ast_exten::data, ast_exten::exten, ast_exten::label, ast_exten::matchcid, ast_context::name, ast_exten::parent, ast_exten::priority, and ast_exten::registrar.
Referenced by action_extensionstate(), extstate_read(), get_queue_member_status(), and handle_request_subscribe().
04520 { 04521 struct ast_exten *e; 04522 04523 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04524 return -1; /* No hint, return -1 */ 04525 } 04526 04527 if (e->exten[0] == '_') { 04528 /* Create this hint on-the-fly */ 04529 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04530 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04531 e->registrar); 04532 if (!(e = ast_hint_extension(c, context, exten))) { 04533 /* Improbable, but not impossible */ 04534 return -1; 04535 } 04536 } 04537 04538 return ast_extension_state2(e); /* Check all devices in the hint */ 04539 }
| static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
Check state of extension by using hints.
Definition at line 4494 of file pbx.c.
References ast_extension_state3(), ast_get_extension_app(), ast_str_set(), ast_str_thread_get(), and extensionstate_buf.
Referenced by ast_add_hint(), and ast_extension_state().
04495 { 04496 struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32); 04497 04498 if (!e || !hint_app) { 04499 return -1; 04500 } 04501 04502 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e)); 04503 return ast_extension_state3(hint_app); 04504 }
| 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 4507 of file pbx.c.
References ARRAY_LEN, extension_states, and cfextension_states::text.
Referenced by cb_extensionstate(), handle_request_subscribe(), handle_show_hint(), handle_show_hints(), hints_data_provider_get(), show_channels_cb(), and skinny_extensionstate_cb().
04508 { 04509 int i; 04510 04511 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04512 if (extension_states[i].extension_state == extension_state) 04513 return extension_states[i].text; 04514 } 04515 return "Unknown"; 04516 }
| static int ast_extension_state3 | ( | struct ast_str * | hint_app | ) | [static] |
Definition at line 4476 of file pbx.c.
References ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_devstate_to_extenstate(), ast_str_buffer(), and strsep().
Referenced by ast_extension_state2(), and handle_statechange().
04477 { 04478 char *cur; 04479 char *rest; 04480 struct ast_devstate_aggregate agg; 04481 04482 /* One or more devices separated with a & character */ 04483 rest = ast_str_buffer(hint_app); 04484 04485 ast_devstate_aggregate_init(&agg); 04486 while ((cur = strsep(&rest, "&"))) { 04487 ast_devstate_aggregate_add(&agg, ast_device_state(cur)); 04488 } 04489 04490 return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg)); 04491 }
| int ast_extension_state_add | ( | const char * | context, | |
| const char * | exten, | |||
| ast_state_cb_type | change_cb, | |||
| void * | data | |||
| ) |
Add watcher for extension states.
Registers a state change callback.
Definition at line 4752 of file pbx.c.
References ast_extension_state_add_destroy().
Referenced by __init_manager(), load_module(), and skinny_register().
04754 { 04755 return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data); 04756 }
| int ast_extension_state_add_destroy | ( | const char * | context, | |
| const char * | exten, | |||
| ast_state_cb_type | change_cb, | |||
| ast_state_cb_destroy_type | destroy_cb, | |||
| void * | data | |||
| ) |
Add watcher for extension states with destructor.
Registers a state change callback with destructor.
Definition at line 4665 of file pbx.c.
References ao2_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension(), ast_free_ptr, ast_hint_extension(), ast_strdup, ast_hint::callbacks, ast_state_cb::change_cb, ast_exten::cidmatch, ast_exten::data, ast_state_cb::data, ast_state_cb::destroy_cb, destroy_state_cb(), ast_exten::exten, hints, ast_state_cb::id, ast_exten::label, ast_exten::matchcid, ast_context::name, OBJ_NODATA, OBJ_UNLINK, ast_exten::parent, ast_exten::priority, ast_exten::registrar, statecbs, and stateid.
Referenced by ast_extension_state_add(), and handle_request_subscribe().
04667 { 04668 struct ast_hint *hint; 04669 struct ast_state_cb *state_cb; 04670 struct ast_exten *e; 04671 int id; 04672 04673 /* If there's no context and extension: add callback to statecbs list */ 04674 if (!context && !exten) { 04675 /* Prevent multiple adds from adding the same change_cb at the same time. */ 04676 ao2_lock(statecbs); 04677 04678 /* Remove any existing change_cb. */ 04679 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA); 04680 04681 /* Now insert the change_cb */ 04682 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 04683 ao2_unlock(statecbs); 04684 return -1; 04685 } 04686 state_cb->id = 0; 04687 state_cb->change_cb = change_cb; 04688 state_cb->destroy_cb = destroy_cb; 04689 state_cb->data = data; 04690 ao2_link(statecbs, state_cb); 04691 04692 ao2_ref(state_cb, -1); 04693 ao2_unlock(statecbs); 04694 return 0; 04695 } 04696 04697 if (!context || !exten) 04698 return -1; 04699 04700 /* This callback type is for only one hint, so get the hint */ 04701 e = ast_hint_extension(NULL, context, exten); 04702 if (!e) { 04703 return -1; 04704 } 04705 04706 /* If this is a pattern, dynamically create a new extension for this 04707 * particular match. Note that this will only happen once for each 04708 * individual extension, because the pattern will no longer match first. 04709 */ 04710 if (e->exten[0] == '_') { 04711 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04712 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04713 e->registrar); 04714 e = ast_hint_extension(NULL, context, exten); 04715 if (!e || e->exten[0] == '_') { 04716 return -1; 04717 } 04718 } 04719 04720 /* Find the hint in the hints container */ 04721 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 04722 hint = ao2_find(hints, e, 0); 04723 if (!hint) { 04724 ao2_unlock(hints); 04725 return -1; 04726 } 04727 04728 /* Now insert the callback in the callback list */ 04729 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 04730 ao2_ref(hint, -1); 04731 ao2_unlock(hints); 04732 return -1; 04733 } 04734 do { 04735 id = stateid++; /* Unique ID for this callback */ 04736 /* Do not allow id to ever be -1 or 0. */ 04737 } while (id == -1 || id == 0); 04738 state_cb->id = id; 04739 state_cb->change_cb = change_cb; /* Pointer to callback routine */ 04740 state_cb->destroy_cb = destroy_cb; 04741 state_cb->data = data; /* Data for the callback */ 04742 ao2_link(hint->callbacks, state_cb); 04743 04744 ao2_ref(state_cb, -1); 04745 ao2_ref(hint, -1); 04746 ao2_unlock(hints); 04747 04748 return id; 04749 }
| int ast_extension_state_del | ( | int | id, | |
| ast_state_cb_type | change_cb | |||
| ) |
ast_extension_state_del: Remove a watcher from the callback list
Deletes a registered state change callback by ID.
Definition at line 4774 of file pbx.c.
References ao2_callback, ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_hint::callbacks, find_hint_by_cb_id(), hints, OBJ_UNLINK, and statecbs.
Referenced by dialog_unlink_all(), handle_request_subscribe(), skinny_unregister(), and unload_module().
04775 { 04776 struct ast_state_cb *p_cur; 04777 int ret = -1; 04778 04779 if (!id) { /* id == 0 is a callback without extension */ 04780 if (!change_cb) { 04781 return ret; 04782 } 04783 p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK); 04784 if (p_cur) { 04785 ret = 0; 04786 ao2_ref(p_cur, -1); 04787 } 04788 } else { /* callback with extension, find the callback based on ID */ 04789 struct ast_hint *hint; 04790 04791 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 04792 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 04793 if (hint) { 04794 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 04795 if (p_cur) { 04796 ret = 0; 04797 ao2_ref(p_cur, -1); 04798 } 04799 ao2_ref(hint, -1); 04800 } 04801 ao2_unlock(hints); 04802 } 04803 04804 return ret; 04805 }
| 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 5031 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().
05032 { 05033 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05034 }
| 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.
This function is the same as ast_findlabel_extension, except that it accepts a pointer to an ast_context structure to specify the context instead of the name of the context. Otherwise, the functions behave the same.
Definition at line 5036 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
05037 { 05038 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05039 }
| 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 |
| 0 | success | |
| non-zero | failure |
Definition at line 3784 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_copy_string(), ast_custom_function_find(), ast_free, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_size(), ast_strdupa, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, and str.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
03785 { 03786 char *copy = ast_strdupa(function); 03787 char *args = func_args(copy); 03788 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03789 int res; 03790 struct ast_module_user *u = NULL; 03791 03792 if (acfptr == NULL) { 03793 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03794 } else if (!acfptr->read && !acfptr->read2) { 03795 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03796 } else if (acfptr->read) { 03797 if (acfptr->mod) { 03798 u = __ast_module_user_add(acfptr->mod, chan); 03799 } 03800 res = acfptr->read(chan, copy, args, workspace, len); 03801 if (acfptr->mod && u) { 03802 __ast_module_user_remove(acfptr->mod, u); 03803 } 03804 return res; 03805 } else { 03806 struct ast_str *str = ast_str_create(16); 03807 if (acfptr->mod) { 03808 u = __ast_module_user_add(acfptr->mod, chan); 03809 } 03810 res = acfptr->read2(chan, copy, args, &str, 0); 03811 if (acfptr->mod && u) { 03812 __ast_module_user_remove(acfptr->mod, u); 03813 } 03814 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 03815 ast_free(str); 03816 return res; 03817 } 03818 return -1; 03819 }
| int ast_func_read2 | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| struct ast_str ** | str, | |||
| ssize_t | maxlen | |||
| ) |
executes a read operation on a function
| chan | Channel to execute on | |
| function | Data containing the function call string (will be modified) | |
| str | A dynamic string buffer into which to place the result. | |
| maxlen | <0 if the dynamic buffer should not grow; >0 if the dynamic buffer should be limited to that number of bytes; 0 if the dynamic buffer has no upper limit |
| 0 | success | |
| non-zero | failure |
Definition at line 3821 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_str_buffer(), ast_str_make_space(), ast_str_reset(), ast_str_size(), ast_strdupa, copy(), func_args(), LOG_ERROR, maxsize, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, and VAR_BUF_SIZE.
Referenced by append_channel_vars(), and ast_str_substitute_variables_full().
03822 { 03823 char *copy = ast_strdupa(function); 03824 char *args = func_args(copy); 03825 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03826 int res; 03827 struct ast_module_user *u = NULL; 03828 03829 if (acfptr == NULL) { 03830 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03831 } else if (!acfptr->read && !acfptr->read2) { 03832 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03833 } else { 03834 if (acfptr->mod) { 03835 u = __ast_module_user_add(acfptr->mod, chan); 03836 } 03837 ast_str_reset(*str); 03838 if (acfptr->read2) { 03839 /* ast_str enabled */ 03840 res = acfptr->read2(chan, copy, args, str, maxlen); 03841 } else { 03842 /* Legacy function pointer, allocate buffer for result */ 03843 int maxsize = ast_str_size(*str); 03844 if (maxlen > -1) { 03845 if (maxlen == 0) { 03846 if (acfptr->read_max) { 03847 maxsize = acfptr->read_max; 03848 } else { 03849 maxsize = VAR_BUF_SIZE; 03850 } 03851 } else { 03852 maxsize = maxlen; 03853 } 03854 ast_str_make_space(str, maxsize); 03855 } 03856 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 03857 } 03858 if (acfptr->mod && u) { 03859 __ast_module_user_remove(acfptr->mod, u); 03860 } 03861 return res; 03862 } 03863 return -1; 03864 }
| 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 |
| 0 | success | |
| non-zero | failure |
Definition at line 3866 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_strdupa, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.
Referenced by conf_run(), confbridge_exec(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
03867 { 03868 char *copy = ast_strdupa(function); 03869 char *args = func_args(copy); 03870 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03871 03872 if (acfptr == NULL) 03873 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03874 else if (!acfptr->write) 03875 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 03876 else { 03877 int res; 03878 struct ast_module_user *u = NULL; 03879 if (acfptr->mod) 03880 u = __ast_module_user_add(acfptr->mod, chan); 03881 res = acfptr->write(chan, copy, args, value); 03882 if (acfptr->mod && u) 03883 __ast_module_user_remove(acfptr->mod, u); 03884 return res; 03885 } 03886 03887 return -1; 03888 }
| const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 10515 of file pbx.c.
References ast_context::name.
Referenced by _macro_exec(), ast_add_hint(), ast_change_hint(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_include2(), ast_context_remove_switch2(), ast_context_verify_includes(), ast_remove_hint(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), context_merge_incls_swits_igps_other_registrars(), destroy_hint(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
10516 { 10517 return con ? con->name : NULL; 10518 }
| const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 10553 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
10554 { 10555 return c ? c->registrar : NULL; 10556 }
| const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 10583 of file pbx.c.
References ast_exten::app.
Referenced by _macro_exec(), ast_add_hint(), ast_change_hint(), ast_extension_state2(), ast_get_hint(), ast_str_get_hint(), find_matching_endwhile(), get_parking_exten(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), and print_ext().
10584 { 10585 return e ? e->app : NULL; 10586 }
| void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 10588 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), ast_masq_park_call_exten(), ast_park_call_exten(), ast_str_get_hint(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), print_ext(), and xfer_park_call_helper().
10589 { 10590 return e ? e->data : NULL; 10591 }
| const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 10578 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10579 { 10580 return e ? e->cidmatch : NULL; 10581 }
| struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 10520 of file pbx.c.
References ast_exten::parent.
Referenced by ast_add_hint(), ast_change_hint(), ast_remove_hint(), destroy_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), and hints_data_provider_get().
10521 { 10522 return exten ? exten->parent : NULL; 10523 }
| const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 10530 of file pbx.c.
References ast_exten::label.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10531 { 10532 return exten ? exten->label : NULL; 10533 }
| int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 10573 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10574 { 10575 return e ? e->matchcid : 0; 10576 }
| const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 10525 of file pbx.c.
References ast_exten::exten.
Referenced by ast_add_hint(), ast_change_hint(), ast_remove_hint(), complete_core_show_hint(), complete_dialplan_remove_extension(), destroy_hint(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hint_hash(), hints_data_provider_get(), manager_show_dialplan_helper(), and show_dialplan_helper().
10526 { 10527 return exten ? exten->exten : NULL; 10528 }
| int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 10545 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().
10546 { 10547 return exten ? exten->priority : -1; 10548 }
| const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 10558 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10559 { 10560 return e ? e->registrar : NULL; 10561 }
| 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 4988 of file pbx.c.
References ast_copy_string(), ast_get_extension_app(), ast_get_extension_app_data(), and ast_hint_extension().
Referenced by action_extensionstate(), get_cid_name(), get_destination(), hint_read(), manager_state_cb(), skinny_extensionstate_cb(), and state_notify_build_xml().
04989 { 04990 struct ast_exten *e = ast_hint_extension(c, context, exten); 04991 04992 if (e) { 04993 if (hint) 04994 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 04995 if (name) { 04996 const char *tmp = ast_get_extension_app_data(e); 04997 if (tmp) 04998 ast_copy_string(name, tmp, namesize); 04999 } 05000 return -1; 05001 } 05002 return 0; 05003 }
| const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10540 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().
10541 { 10542 return ip ? ip->pattern : NULL; 10543 }
| const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10568 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().
10569 { 10570 return ip ? ip->registrar : NULL; 10571 }
| const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 10535 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().
10536 { 10537 return inc ? inc->name : NULL; 10538 }
| const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 10563 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().
10564 { 10565 return i ? i->registrar : NULL; 10566 }
| const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 10598 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().
10599 { 10600 return sw ? sw->data : NULL; 10601 }
| int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 10603 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
10604 { 10605 return sw->eval; 10606 }
| const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 10593 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().
10594 { 10595 return sw ? sw->name : NULL; 10596 }
| const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 10608 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().
10609 { 10610 return sw ? sw->registrar : NULL; 10611 }
| int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 10703 of file pbx.c.
References __ast_goto_if_exists().
Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), dial_exec_full(), goto_exten(), onedigit_goto(), priority_jump(), select_entry(), valid_exit(), vm_execmain(), and vmauthenticate().
10704 { 10705 return __ast_goto_if_exists(chan, context, exten, priority, 0); 10706 }
| int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
| const void * | ah_b | |||
| ) |
hashtable functions for contexts
Definition at line 1186 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_hints(), lua_register_switches(), and pbx_load_module().
01187 { 01188 const struct ast_context *ac = ah_a; 01189 const struct ast_context *bc = ah_b; 01190 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01191 return 1; 01192 /* assume context names are registered in a string table! */ 01193 return strcmp(ac->name, bc->name); 01194 }
| unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1229 of file pbx.c.
References ast_hashtab_hash_string(), and ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_hints(), lua_register_switches(), and pbx_load_module().
01230 { 01231 const struct ast_context *ac = obj; 01232 return ast_hashtab_hash_string(ac->name); 01233 }
| static struct ast_exten* ast_hint_extension | ( | struct ast_channel * | c, | |
| const char * | context, | |||
| const char * | exten | |||
| ) | [static, read] |
Definition at line 4440 of file pbx.c.
References ast_hint_extension_nolock(), ast_rdlock_contexts(), and ast_unlock_contexts().
Referenced by ast_extension_state(), ast_extension_state_add_destroy(), ast_get_hint(), and ast_str_get_hint().
04441 { 04442 struct ast_exten *e; 04443 ast_rdlock_contexts(); 04444 e = ast_hint_extension_nolock(c, context, exten); 04445 ast_unlock_contexts(); 04446 return e; 04447 }
| 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 4434 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().
04435 { 04436 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 04437 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 04438 }
| 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 |
| 0 | if the pattern should not be ignored | |
| non-zero | if the pattern should be ignored |
Definition at line 8230 of file pbx.c.
References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), mgcp_ss(), and skinny_ss().
08231 { 08232 struct ast_context *con = ast_context_find(context); 08233 08234 if (con) { 08235 struct ast_ignorepat *pat; 08236 08237 for (pat = con->ignorepats; pat; pat = pat->next) { 08238 if (ast_extension_match(pat->pattern, pattern)) 08239 return 1; 08240 } 08241 } 08242 08243 return 0; 08244 }
| 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 5046 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by __analog_ss_thread(), __ast_pbx_run(), analog_ss_thread(), ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), readexten_exec(), and skinny_ss().
05047 { 05048 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 05049 }
| 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 7528 of file pbx.c.
References __ast_internal_context_destroy(), ao2_callback, ao2_container_count(), ao2_find, ao2_iterator_destroy(), AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr, ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), store_hint::callbacks, ast_hint::callbacks, ast_state_cb::change_cb, store_hint::context, context_merge(), context_merge_lock, contexts, contexts_table, ast_state_cb::data, ast_exten::data, store_hint::data, E_MATCH, store_hint::exten, ast_exten::exten, ast_hint::exten, hints, ast_hint::laststate, store_hint::laststate, ast_context::name, ast_context::next, ast_sw::next, OBJ_UNLINK, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_exten::registrar, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
07529 { 07530 double ft; 07531 struct ast_context *tmp; 07532 struct ast_context *oldcontextslist; 07533 struct ast_hashtab *oldtable; 07534 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07535 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07536 struct store_hint *saved_hint; 07537 struct ast_hint *hint; 07538 struct ast_exten *exten; 07539 int length; 07540 struct ast_state_cb *thiscb; 07541 struct ast_hashtab_iter *iter; 07542 struct ao2_iterator i; 07543 struct timeval begintime; 07544 struct timeval writelocktime; 07545 struct timeval endlocktime; 07546 struct timeval enddeltime; 07547 07548 /* 07549 * It is very important that this function hold the hints 07550 * container lock _and_ the conlock during its operation; not 07551 * only do we need to ensure that the list of contexts and 07552 * extensions does not change, but also that no hint callbacks 07553 * (watchers) are added or removed during the merge/delete 07554 * process 07555 * 07556 * In addition, the locks _must_ be taken in this order, because 07557 * there are already other code paths that use this order 07558 */ 07559 07560 begintime = ast_tvnow(); 07561 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */ 07562 ast_wrlock_contexts(); 07563 iter = ast_hashtab_start_traversal(contexts_table); 07564 while ((tmp = ast_hashtab_next(iter))) { 07565 context_merge(extcontexts, exttable, tmp, registrar); 07566 } 07567 ast_hashtab_end_traversal(iter); 07568 07569 ao2_lock(hints); 07570 writelocktime = ast_tvnow(); 07571 07572 /* preserve all watchers for hints */ 07573 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07574 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 07575 if (ao2_container_count(hint->callbacks)) { 07576 ao2_lock(hint); 07577 if (!hint->exten) { 07578 /* The extension has already been destroyed. (Should never happen here) */ 07579 ao2_unlock(hint); 07580 continue; 07581 } 07582 07583 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 07584 + sizeof(*saved_hint); 07585 if (!(saved_hint = ast_calloc(1, length))) { 07586 ao2_unlock(hint); 07587 continue; 07588 } 07589 07590 /* This removes all the callbacks from the hint into saved_hint. */ 07591 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 07592 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry); 07593 /* 07594 * We intentionally do not unref thiscb to account for the 07595 * non-ao2 reference in saved_hint->callbacks 07596 */ 07597 } 07598 07599 saved_hint->laststate = hint->laststate; 07600 saved_hint->context = saved_hint->data; 07601 strcpy(saved_hint->data, hint->exten->parent->name); 07602 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1; 07603 strcpy(saved_hint->exten, hint->exten->exten); 07604 ao2_unlock(hint); 07605 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); 07606 } 07607 } 07608 ao2_iterator_destroy(&i); 07609 07610 /* save the old table and list */ 07611 oldtable = contexts_table; 07612 oldcontextslist = contexts; 07613 07614 /* move in the new table and list */ 07615 contexts_table = exttable; 07616 contexts = *extcontexts; 07617 07618 /* 07619 * Restore the watchers for hints that can be found; notify 07620 * those that cannot be restored. 07621 */ 07622 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) { 07623 struct pbx_find_info q = { .stacklen = 0 }; 07624 07625 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten, 07626 PRIORITY_HINT, NULL, "", E_MATCH); 07627 /* 07628 * If this is a pattern, dynamically create a new extension for this 07629 * particular match. Note that this will only happen once for each 07630 * individual extension, because the pattern will no longer match first. 07631 */ 07632 if (exten && exten->exten[0] == '_') { 07633 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten, 07634 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr, 07635 exten->registrar); 07636 /* rwlocks are not recursive locks */ 07637 exten = ast_hint_extension_nolock(NULL, saved_hint->context, 07638 saved_hint->exten); 07639 } 07640 07641 /* Find the hint in the hints container */ 07642 hint = exten ? ao2_find(hints, exten, 0) : NULL; 07643 if (!hint) { 07644 /* 07645 * Notify watchers of this removed hint later when we aren't 07646 * encumberd by so many locks. 07647 */ 07648 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list); 07649 } else { 07650 ao2_lock(hint); 07651 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07652 ao2_link(hint->callbacks, thiscb); 07653 /* Ref that we added when putting into saved_hint->callbacks */ 07654 ao2_ref(thiscb, -1); 07655 } 07656 hint->laststate = saved_hint->laststate; 07657 ao2_unlock(hint); 07658 ao2_ref(hint, -1); 07659 ast_free(saved_hint); 07660 } 07661 } 07662 07663 ao2_unlock(hints); 07664 ast_unlock_contexts(); 07665 07666 /* 07667 * Notify watchers of all removed hints with the same lock 07668 * environment as handle_statechange(). 07669 */ 07670 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) { 07671 /* this hint has been removed, notify the watchers */ 07672 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07673 thiscb->change_cb(saved_hint->context, saved_hint->exten, 07674 AST_EXTENSION_REMOVED, thiscb->data); 07675 /* Ref that we added when putting into saved_hint->callbacks */ 07676 ao2_ref(thiscb, -1); 07677 } 07678 ast_free(saved_hint); 07679 } 07680 07681 ast_mutex_unlock(&context_merge_lock); 07682 endlocktime = ast_tvnow(); 07683 07684 /* 07685 * The old list and hashtab no longer are relevant, delete them 07686 * while the rest of asterisk is now freely using the new stuff 07687 * instead. 07688 */ 07689 07690 ast_hashtab_destroy(oldtable, NULL); 07691 07692 for (tmp = oldcontextslist; tmp; ) { 07693 struct ast_context *next; /* next starting point */ 07694 07695 next = tmp->next; 07696 __ast_internal_context_destroy(tmp); 07697 tmp = next; 07698 } 07699 enddeltime = ast_tvnow(); 07700 07701 ft = ast_tvdiff_us(writelocktime, begintime); 07702 ft /= 1000000.0; 07703 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 07704 07705 ft = ast_tvdiff_us(endlocktime, writelocktime); 07706 ft /= 1000000.0; 07707 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 07708 07709 ft = ast_tvdiff_us(enddeltime, endlocktime); 07710 ft /= 1000000.0; 07711 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 07712 07713 ft = ast_tvdiff_us(enddeltime, begintime); 07714 ft /= 1000000.0; 07715 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 07716 }
| int ast_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string | |||
| ) |
Definition at line 10768 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().
10769 { 10770 return pbx_parseable_goto(chan, goto_string, 0); 10771 }
| int ast_pbx_init | ( | void | ) |
Provided by pbx.c
Definition at line 10833 of file pbx.c.
References ao2_container_alloc, HASH_EXTENHINT_SIZE, hint_cmp(), hint_hash(), hintdevice_cmp_multiple(), hintdevice_hash_cb(), hints, statecbs, and statecbs_cmp().
Referenced by main().
10834 { 10835 hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp); 10836 hintdevices = ao2_container_alloc(HASH_EXTENHINT_SIZE, hintdevice_hash_cb, hintdevice_cmp_multiple); 10837 statecbs = ao2_container_alloc(1, NULL, statecbs_cmp); 10838 10839 return (hints && hintdevices && statecbs) ? 0 : -1; 10840 }
| int ast_pbx_outgoing_app | ( | const char * | type, | |
| struct ast_format_cap * | cap, | |||
| const char * | addr, | |||
| int | timeout, | |||
| const char * | app, | |||
| const char * | appdata, | |||
| int * | reason, | |||
| int | 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 9107 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, async_stat::appdata, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_copy_string(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create_detached, ast_set_variables(), AST_STATE_UP, ast_string_field_free_memory, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, errno, ast_channel::hangupcause, LOG_WARNING, async_stat::p, app_tmp::t, async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_app(), and originate_exec().
09108 { 09109 struct ast_channel *chan; 09110 struct app_tmp *tmp; 09111 int res = -1, cdr_res = -1; 09112 struct outgoing_helper oh; 09113 09114 memset(&oh, 0, sizeof(oh)); 09115 oh.vars = vars; 09116 oh.account = account; 09117 09118 if (locked_channel) 09119 *locked_channel = NULL; 09120 if (ast_strlen_zero(app)) { 09121 res = -1; 09122 goto outgoing_app_cleanup; 09123 } 09124 if (synchronous) { 09125 chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh); 09126 if (chan) { 09127 ast_set_variables(chan, vars); 09128 if (account) 09129 ast_cdr_setaccount(chan, account); 09130 if (chan->_state == AST_STATE_UP) { 09131 res = 0; 09132 ast_verb(4, "Channel %s was answered.\n", ast_channel_name(chan)); 09133 tmp = ast_calloc(1, sizeof(*tmp)); 09134 if (!tmp || ast_string_field_init(tmp, 252)) { 09135 if (tmp) { 09136 ast_free(tmp); 09137 } 09138 res = -1; 09139 } else { 09140 ast_string_field_set(tmp, app, app); 09141 ast_string_field_set(tmp, data, appdata); 09142 tmp->chan = chan; 09143 if (synchronous > 1) { 09144 if (locked_channel) 09145 ast_channel_unlock(chan); 09146 ast_pbx_run_app(tmp); 09147 } else { 09148 if (locked_channel) 09149 ast_channel_lock(chan); 09150 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 09151 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", ast_channel_name(chan), strerror(errno)); 09152 ast_string_field_free_memory(tmp); 09153 ast_free(tmp); 09154 if (locked_channel) 09155 ast_channel_unlock(chan); 09156 ast_hangup(chan); 09157 res = -1; 09158 } else { 09159 if (locked_channel) 09160 *locked_channel = chan; 09161 } 09162 } 09163 } 09164 } else { 09165 ast_verb(4, "Channel %s was never answered.\n", ast_channel_name(chan)); 09166 if (chan->cdr) { /* update the cdr */ 09167 /* here we update the status of the call, which sould be busy. 09168 * if that fails then we set the status to failed */ 09169 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09170 ast_cdr_failed(chan->cdr); 09171 } 09172 ast_hangup(chan); 09173 } 09174 } 09175 09176 if (res < 0) { /* the call failed for some reason */ 09177 if (*reason == 0) { /* if the call failed (not busy or no answer) 09178 * update the cdr with the failed message */ 09179 cdr_res = ast_pbx_outgoing_cdr_failed(); 09180 if (cdr_res != 0) { 09181 res = cdr_res; 09182 goto outgoing_app_cleanup; 09183 } 09184 } 09185 } 09186 09187 } else { 09188 struct async_stat *as; 09189 if (!(as = ast_calloc(1, sizeof(*as)))) { 09190 res = -1; 09191 goto outgoing_app_cleanup; 09192 } 09193 chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh); 09194 if (!chan) { 09195 ast_free(as); 09196 res = -1; 09197 goto outgoing_app_cleanup; 09198 } 09199 as->chan = chan; 09200 ast_copy_string(as->app, app, sizeof(as->app)); 09201 if (appdata) 09202 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 09203 as->timeout = timeout; 09204 ast_set_variables(chan, vars); 09205 if (account) 09206 ast_cdr_setaccount(chan, account); 09207 /* Start a new thread, and get something handling this channel. */ 09208 if (locked_channel) 09209 ast_channel_lock(chan); 09210 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09211 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09212 ast_free(as); 09213 if (locked_channel) 09214 ast_channel_unlock(chan); 09215 ast_hangup(chan); 09216 res = -1; 09217 goto outgoing_app_cleanup; 09218 } else { 09219 if (locked_channel) 09220 *locked_channel = chan; 09221 } 09222 res = 0; 09223 } 09224 outgoing_app_cleanup: 09225 ast_variables_destroy(vars); 09226 return res; 09227 }
| static int ast_pbx_outgoing_cdr_failed | ( | void | ) | [static] |
Function to post an empty cdr after a spool call fails.
Definition at line 8911 of file pbx.c.
References ast_cdr_alloc(), ast_cdr_detach(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_start(), ast_channel_unref, ast_dummy_channel_alloc(), and ast_channel::cdr.
Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
08912 { 08913 /* allocate a channel */ 08914 struct ast_channel *chan = ast_dummy_channel_alloc(); 08915 08916 if (!chan) 08917 return -1; /* failure */ 08918 08919 chan->cdr = ast_cdr_alloc(); 08920 if (!chan->cdr) { 08921 /* allocation of the cdr failed */ 08922 chan = ast_channel_unref(chan); /* free the channel */ 08923 return -1; /* return failure */ 08924 } 08925 08926 /* allocation of the cdr was successful */ 08927 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 08928 ast_cdr_start(chan->cdr); /* record the start and stop time */ 08929 ast_cdr_end(chan->cdr); 08930 ast_cdr_failed(chan->cdr); /* set the status to failed */ 08931 ast_cdr_detach(chan->cdr); /* post and free the record */ 08932 chan->cdr = NULL; 08933 chan = ast_channel_unref(chan); /* free the channel */ 08934 08935 return 0; /* success */ 08936 }
| int ast_pbx_outgoing_exten | ( | const char * | type, | |
| struct ast_format_cap * | cap, | |||
| const char * | addr, | |||
| int | timeout, | |||
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| int * | reason, | |||
| int | 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 8938 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_name(), ast_channel_unlock, ast_copy_string(), ast_exists_extension(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create_detached, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, outgoing_helper::cid_name, outgoing_helper::cid_num, async_stat::context, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, async_stat::p, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_exten(), and originate_exec().
08939 { 08940 struct ast_channel *chan; 08941 struct async_stat *as; 08942 int res = -1, cdr_res = -1; 08943 struct outgoing_helper oh; 08944 08945 if (synchronous) { 08946 oh.context = context; 08947 oh.exten = exten; 08948 oh.priority = priority; 08949 oh.cid_num = cid_num; 08950 oh.cid_name = cid_name; 08951 oh.account = account; 08952 oh.vars = vars; 08953 oh.parent_channel = NULL; 08954 08955 chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh); 08956 if (channel) { 08957 *channel = chan; 08958 if (chan) 08959 ast_channel_lock(chan); 08960 } 08961 if (chan) { 08962 if (chan->_state == AST_STATE_UP) { 08963 res = 0; 08964 ast_verb(4, "Channel %s was answered.\n", ast_channel_name(chan)); 08965 08966 if (synchronous > 1) { 08967 if (channel) 08968 ast_channel_unlock(chan); 08969 if (ast_pbx_run(chan)) { 08970 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", ast_channel_name(chan)); 08971 if (channel) 08972 *channel = NULL; 08973 ast_hangup(chan); 08974 chan = NULL; 08975 res = -1; 08976 } 08977 } else { 08978 if (ast_pbx_start(chan)) { 08979 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", ast_channel_name(chan)); 08980 if (channel) { 08981 *channel = NULL; 08982 ast_channel_unlock(chan); 08983 } 08984 ast_hangup(chan); 08985 res = -1; 08986 } 08987 chan = NULL; 08988 } 08989 } else { 08990 ast_verb(4, "Channel %s was never answered.\n", ast_channel_name(chan)); 08991 08992 if (chan->cdr) { /* update the cdr */ 08993 /* here we update the status of the call, which sould be busy. 08994 * if that fails then we set the status to failed */ 08995 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 08996 ast_cdr_failed(chan->cdr); 08997 } 08998 08999 if (channel) { 09000 *channel = NULL; 09001 ast_channel_unlock(chan); 09002 } 09003 ast_hangup(chan); 09004 chan = NULL; 09005 } 09006 } 09007 09008 if (res < 0) { /* the call failed for some reason */ 09009 if (*reason == 0) { /* if the call failed (not busy or no answer) 09010 * update the cdr with the failed message */ 09011 cdr_res = ast_pbx_outgoing_cdr_failed(); 09012 if (cdr_res != 0) { 09013 res = cdr_res; 09014 goto outgoing_exten_cleanup; 09015 } 09016 } 09017 09018 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 09019 /* check if "failed" exists */ 09020 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 09021 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 09022 if (chan) { 09023 char failed_reason[4] = ""; 09024 if (!ast_strlen_zero(context)) 09025 ast_copy_string(chan->context, context, sizeof(chan->context)); 09026 set_ext_pri(chan, "failed", 1); 09027 ast_set_variables(chan, vars); 09028 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 09029 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 09030 if (account) 09031 ast_cdr_setaccount(chan, account); 09032 if (ast_pbx_run(chan)) { 09033 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", ast_channel_name(chan)); 09034 ast_hangup(chan); 09035 } 09036 chan = NULL; 09037 } 09038 } 09039 } 09040 } else { 09041 if (!(as = ast_calloc(1, sizeof(*as)))) { 09042 res = -1; 09043 goto outgoing_exten_cleanup; 09044 } 09045 chan = ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name); 09046 if (channel) { 09047 *channel = chan; 09048 if (chan) 09049 ast_channel_lock(chan); 09050 } 09051 if (!chan) { 09052 ast_free(as); 09053 res = -1; 09054 goto outgoing_exten_cleanup; 09055 } 09056 as->chan = chan; 09057 ast_copy_string(as->context, context, sizeof(as->context)); 09058 set_ext_pri(as->chan, exten, priority); 09059 as->timeout = timeout; 09060 ast_set_variables(chan, vars); 09061 if (account) 09062 ast_cdr_setaccount(chan, account); 09063 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09064 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09065 ast_free(as); 09066 if (channel) { 09067 *channel = NULL; 09068 ast_channel_unlock(chan); 09069 } 09070 ast_hangup(chan); 09071 res = -1; 09072 goto outgoing_exten_cleanup; 09073 } 09074 res = 0; 09075 } 09076 outgoing_exten_cleanup: 09077 ast_variables_destroy(vars); 09078 return res; 09079 }
| 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 |
| Zero | on success | |
| non-zero | on failure |
Definition at line 5541 of file pbx.c.
References ast_pbx_run_args().
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_pbx_outgoing_exten(), async_wait(), do_notify(), mgcp_ss(), skinny_newcall(), and unistim_ss().
05542 { 05543 return ast_pbx_run_args(c, NULL); 05544 }
| static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 9091 of file pbx.c.
References app_tmp::app, ast_channel_name(), ast_free, ast_hangup(), ast_log(), ast_string_field_free_memory, ast_verb, app_tmp::chan, app_tmp::data, LOG_WARNING, pbx_exec(), and pbx_findapp().
Referenced by ast_pbx_outgoing_app().
09092 { 09093 struct app_tmp *tmp = data; 09094 struct ast_app *app; 09095 app = pbx_findapp(tmp->app); 09096 if (app) { 09097 ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, ast_channel_name(tmp->chan)); 09098 pbx_exec(tmp->chan, app, tmp->data); 09099 } else 09100 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 09101 ast_hangup(tmp->chan); 09102 ast_string_field_free_memory(tmp); 09103 ast_free(tmp); 09104 return NULL; 09105 }
| 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 |
| Zero | on success | |
| non-zero | on failure |
Definition at line 5521 of file pbx.c.
References __ast_pbx_run(), ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_test_flag, decrease_call_count(), increase_call_count(), and LOG_WARNING.
Referenced by action_dialplan_exec(), ast_pbx_run(), dial_exec_full(), handle_gosub(), msg_route(), and try_calling().
05522 { 05523 enum ast_pbx_result res = AST_PBX_SUCCESS; 05524 05525 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05526 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05527 return AST_PBX_FAILED; 05528 } 05529 05530 if (increase_call_count(c)) { 05531 return AST_PBX_CALL_LIMIT; 05532 } 05533 05534 res = __ast_pbx_run(c, args); 05535 05536 decrease_call_count(); 05537 05538 return res; 05539 }
| 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 5494 of file pbx.c.
References ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, ast_test_flag, decrease_call_count(), increase_call_count(), LOG_WARNING, and pbx_thread().
Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_iax2_new(), ast_pbx_outgoing_exten(), bridge_call_thread(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), generic_recall(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), manage_parked_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), rpt_call(), skinny_new(), unistim_new(), and usbradio_new().
05495 { 05496 pthread_t t; 05497 05498 if (!c) { 05499 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05500 return AST_PBX_FAILED; 05501 } 05502 05503 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05504 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05505 return AST_PBX_FAILED; 05506 } 05507 05508 if (increase_call_count(c)) 05509 return AST_PBX_CALL_LIMIT; 05510 05511 /* Start a new thread, and get something handling this channel. */ 05512 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05513 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05514 decrease_call_count(); 05515 return AST_PBX_FAILED; 05516 } 05517 05518 return AST_PBX_SUCCESS; 05519 }
| int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5551 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05552 { 05553 return totalcalls; 05554 }
| 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 10502 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().
10503 { 10504 return ast_rwlock_rdlock(&con->lock); 10505 }
| int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 10484 of file pbx.c.
References ast_mutex_lock, and conlock.
Referenced by _macro_exec(), ast_context_find(), ast_context_find_or_create(), ast_hint_extension(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
10485 { 10486 return ast_mutex_lock(&conlock); 10487 }
| int ast_register_application2 | ( | const char * | app, | |
| int(*)(struct ast_channel *, const char *) | execute, | |||
| const char * | synopsis, | |||
| const char * | description, | |||
| void * | mod | |||
| ) |
Dynamically register a new dial plan application.
Register an application.
Definition at line 5962 of file pbx.c.
References ast_app::arguments, ast_calloc, ast_free, ast_log(), ast_module_name(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_verb, AST_XML_DOC, COLOR_BRCYAN, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, ast_app::seealso, ast_app::syntax, and term_color().
Referenced by ast_cc_init(), ast_features_init(), ast_msg_init(), and load_pbx().
05963 { 05964 struct ast_app *tmp, *cur = NULL; 05965 char tmps[80]; 05966 int length, res; 05967 #ifdef AST_XML_DOCS 05968 char *tmpxml; 05969 #endif 05970 05971 AST_RWLIST_WRLOCK(&apps); 05972 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 05973 if (!(res = strcasecmp(app, tmp->name))) { 05974 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 05975 AST_RWLIST_UNLOCK(&apps); 05976 return -1; 05977 } else if (res < 0) 05978 break; 05979 } 05980 05981 length = sizeof(*tmp) + strlen(app) + 1; 05982 05983 if (!(tmp = ast_calloc(1, length))) { 05984 AST_RWLIST_UNLOCK(&apps); 05985 return -1; 05986 } 05987 05988 if (ast_string_field_init(tmp, 128)) { 05989 AST_RWLIST_UNLOCK(&apps); 05990 ast_free(tmp); 05991 return -1; 05992 } 05993 05994 strcpy(tmp->name, app); 05995 tmp->execute = execute; 05996 tmp->module = mod; 05997 05998 #ifdef AST_XML_DOCS 05999 /* Try to lookup the docs in our XML documentation database */ 06000 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 06001 /* load synopsis */ 06002 tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module)); 06003 ast_string_field_set(tmp, synopsis, tmpxml); 06004 ast_free(tmpxml); 06005 06006 /* load description */ 06007 tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module)); 06008 ast_string_field_set(tmp, description, tmpxml); 06009 ast_free(tmpxml); 06010 06011 /* load syntax */ 06012 tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module)); 06013 ast_string_field_set(tmp, syntax, tmpxml); 06014 ast_free(tmpxml); 06015 06016 /* load arguments */ 06017 tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module)); 06018 ast_string_field_set(tmp, arguments, tmpxml); 06019 ast_free(tmpxml); 06020 06021 /* load seealso */ 06022 tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module)); 06023 ast_string_field_set(tmp, seealso, tmpxml); 06024 ast_free(tmpxml); 06025 tmp->docsrc = AST_XML_DOC; 06026 } else { 06027 #endif 06028 ast_string_field_set(tmp, synopsis, synopsis); 06029 ast_string_field_set(tmp, description, description); 06030 #ifdef AST_XML_DOCS 06031 tmp->docsrc = AST_STATIC_DOC; 06032 } 06033 #endif 06034 06035 /* Store in alphabetical order */ 06036 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 06037 if (strcasecmp(tmp->name, cur->name) < 0) { 06038 AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list); 06039 break; 06040 } 06041 } 06042 AST_RWLIST_TRAVERSE_SAFE_END; 06043 if (!cur) 06044 AST_RWLIST_INSERT_TAIL(&apps, tmp, list); 06045 06046 ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 06047 06048 AST_RWLIST_UNLOCK(&apps); 06049 06050 return 0; 06051 }
| int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
| sw | switch to register |
| 0 | success | |
| non-zero | failure |
Definition at line 6057 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().
06058 { 06059 struct ast_switch *tmp; 06060 06061 AST_RWLIST_WRLOCK(&switches); 06062 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 06063 if (!strcasecmp(tmp->name, sw->name)) { 06064 AST_RWLIST_UNLOCK(&switches); 06065 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 06066 return -1; 06067 } 06068 } 06069 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 06070 AST_RWLIST_UNLOCK(&switches); 06071 06072 return 0; 06073 }
| static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
Remove hint from extension.
Definition at line 4853 of file pbx.c.
References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), ast_get_context_name(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::context_name, ast_hint::exten, ast_hint::exten_name, hints, OBJ_UNLINK, and remove_hintdevice().
Referenced by destroy_exten().
04854 { 04855 /* Cleanup the Notifys if hint is removed */ 04856 struct ast_hint *hint; 04857 04858 if (!e) { 04859 return -1; 04860 } 04861 04862 hint = ao2_find(hints, e, OBJ_UNLINK); 04863 if (!hint) { 04864 return -1; 04865 } 04866 04867 remove_hintdevice(hint); 04868 04869 /* 04870 * The extension is being destroyed so we must save some 04871 * information to notify that the extension is deactivated. 04872 */ 04873 ao2_lock(hint); 04874 ast_copy_string(hint->context_name, 04875 ast_get_context_name(ast_get_extension_context(hint->exten)), 04876 sizeof(hint->context_name)); 04877 ast_copy_string(hint->exten_name, ast_get_extension_name(hint->exten), 04878 sizeof(hint->exten_name)); 04879 hint->exten = NULL; 04880 ao2_unlock(hint); 04881 04882 ao2_ref(hint, -1); 04883 04884 return 0; 04885 }
| 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 5051 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().
05052 { 05053 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 05054 }
| int ast_str_get_hint | ( | struct ast_str ** | hint, | |
| ssize_t | hintsize, | |||
| struct ast_str ** | name, | |||
| ssize_t | namesize, | |||
| struct ast_channel * | c, | |||
| const char * | context, | |||
| const char * | exten | |||
| ) |
Get hint for channel.
If an extension hint exists, return non-zero.
Definition at line 5006 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), and ast_str_set().
Referenced by ast_str_retrieve_variable().
05007 { 05008 struct ast_exten *e = ast_hint_extension(c, context, exten); 05009 05010 if (!e) { 05011 return 0; 05012 } 05013 05014 if (hint) { 05015 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 05016 } 05017 if (name) { 05018 const char *tmp = ast_get_extension_app_data(e); 05019 if (tmp) { 05020 ast_str_set(name, namesize, "%s", tmp); 05021 } 05022 } 05023 return -1; 05024 }
| const char* ast_str_retrieve_variable | ( | struct ast_str ** | buf, | |
| ssize_t | maxlen, | |||
| struct ast_channel * | chan, | |||
| struct varshead * | headp, | |||
| const char * | var | |||
| ) |
| buf | Result will be placed in this buffer. | |
| maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
| chan | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
| headp | If no channel is specified, a channel list from which to extract variable values | |
| var | Variable name to retrieve. |
Definition at line 3251 of file pbx.c.
References ast_party_caller::ani2, ARRAY_LEN, ast_channel_lock, ast_channel_name(), ast_channel_uniqueid(), ast_channel_unlock, ast_config_AST_AGI_DIR, ast_config_AST_CONFIG_DIR, ast_config_AST_DATA_DIR, ast_config_AST_DB, ast_config_AST_KEY_DIR, ast_config_AST_LOG_DIR, ast_config_AST_MODULE_DIR, ast_config_AST_RUN_DIR, ast_config_AST_SPOOL_DIR, ast_config_AST_SYSTEM_NAME, ast_config_AST_VAR_DIR, ast_debug, ast_eid_default, ast_eid_to_str(), AST_LIST_TRAVERSE, ast_party_id_presentation(), ast_rwlock_rdlock, ast_rwlock_unlock, ast_str_buffer(), ast_str_get_hint(), ast_str_set(), ast_str_substring(), ast_strdupa, ast_var_name(), ast_var_value(), ast_channel::caller, ast_channel::context, ast_channel::dialed, ast_var_t::entries, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_party_caller::id, ast_party_id::number, parse_variable_name(), ast_party_number::plan, ast_channel::priority, ast_party_dialed::transit_network_select, and ast_channel::varshead.
Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().
03252 { 03253 const char not_found = '\0'; 03254 char *tmpvar; 03255 const char *ret; 03256 const char *s; /* the result */ 03257 int offset, length; 03258 int i, need_substring; 03259 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 03260 03261 if (c) { 03262 ast_channel_lock(c); 03263 places[0] = &c->varshead; 03264 } 03265 /* 03266 * Make a copy of var because parse_variable_name() modifies the string. 03267 * Then if called directly, we might need to run substring() on the result; 03268 * remember this for later in 'need_substring', 'offset' and 'length' 03269 */ 03270 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03271 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03272 03273 /* 03274 * Look first into predefined variables, then into variable lists. 03275 * Variable 's' points to the result, according to the following rules: 03276 * s == ¬_found (set at the beginning) means that we did not find a 03277 * matching variable and need to look into more places. 03278 * If s != ¬_found, s is a valid result string as follows: 03279 * s = NULL if the variable does not have a value; 03280 * you typically do this when looking for an unset predefined variable. 03281 * s = workspace if the result has been assembled there; 03282 * typically done when the result is built e.g. with an snprintf(), 03283 * so we don't need to do an additional copy. 03284 * s != workspace in case we have a string, that needs to be copied 03285 * (the ast_copy_string is done once for all at the end). 03286 * Typically done when the result is already available in some string. 03287 */ 03288 s = ¬_found; /* default value */ 03289 if (c) { /* This group requires a valid channel */ 03290 /* Names with common parts are looked up a piece at a time using strncmp. */ 03291 if (!strncmp(var, "CALL", 4)) { 03292 if (!strncmp(var + 4, "ING", 3)) { 03293 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03294 ast_str_set(str, maxlen, "%d", 03295 ast_party_id_presentation(&c->caller.id)); 03296 s = ast_str_buffer(*str); 03297 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03298 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03299 s = ast_str_buffer(*str); 03300 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03301 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03302 s = ast_str_buffer(*str); 03303 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03304 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03305 s = ast_str_buffer(*str); 03306 } 03307 } 03308 } else if (!strcmp(var, "HINT")) { 03309 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03310 } else if (!strcmp(var, "HINTNAME")) { 03311 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03312 } else if (!strcmp(var, "EXTEN")) { 03313 s = c->exten; 03314 } else if (!strcmp(var, "CONTEXT")) { 03315 s = c->context; 03316 } else if (!strcmp(var, "PRIORITY")) { 03317 ast_str_set(str, maxlen, "%d", c->priority); 03318 s = ast_str_buffer(*str); 03319 } else if (!strcmp(var, "CHANNEL")) { 03320 s = ast_channel_name(c); 03321 } else if (!strcmp(var, "UNIQUEID")) { 03322 s = ast_channel_uniqueid(c); 03323 } else if (!strcmp(var, "HANGUPCAUSE")) { 03324 ast_str_set(str, maxlen, "%d", c->hangupcause); 03325 s = ast_str_buffer(*str); 03326 } 03327 } 03328 if (s == ¬_found) { /* look for more */ 03329 if (!strcmp(var, "EPOCH")) { 03330 ast_str_set(str, maxlen, "%u", (int) time(NULL)); 03331 s = ast_str_buffer(*str); 03332 } else if (!strcmp(var, "SYSTEMNAME")) { 03333 s = ast_config_AST_SYSTEM_NAME; 03334 } else if (!strcmp(var, "ASTETCDIR")) { 03335 s = ast_config_AST_CONFIG_DIR; 03336 } else if (!strcmp(var, "ASTMODDIR")) { 03337 s = ast_config_AST_MODULE_DIR; 03338 } else if (!strcmp(var, "ASTVARLIBDIR")) { 03339 s = ast_config_AST_VAR_DIR; 03340 } else if (!strcmp(var, "ASTDBDIR")) { 03341 s = ast_config_AST_DB; 03342 } else if (!strcmp(var, "ASTKEYDIR")) { 03343 s = ast_config_AST_KEY_DIR; 03344 } else if (!strcmp(var, "ASTDATADIR")) { 03345 s = ast_config_AST_DATA_DIR; 03346 } else if (!strcmp(var, "ASTAGIDIR")) { 03347 s = ast_config_AST_AGI_DIR; 03348 } else if (!strcmp(var, "ASTSPOOLDIR")) { 03349 s = ast_config_AST_SPOOL_DIR; 03350 } else if (!strcmp(var, "ASTRUNDIR")) { 03351 s = ast_config_AST_RUN_DIR; 03352 } else if (!strcmp(var, "ASTLOGDIR")) { 03353 s = ast_config_AST_LOG_DIR; 03354 } else if (!strcmp(var, "ENTITYID")) { 03355 char workspace[20]; 03356 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03357 s = workspace; 03358 } 03359 } 03360 /* if not found, look into chanvars or global vars */ 03361 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03362 struct ast_var_t *variables; 03363 if (!places[i]) 03364 continue; 03365 if (places[i] == &globals) 03366 ast_rwlock_rdlock(&globalslock); 03367 AST_LIST_TRAVERSE(places[i], variables, entries) { 03368 if (!strcasecmp(ast_var_name(variables), var)) { 03369 s = ast_var_value(variables); 03370 break; 03371 } 03372 } 03373 if (places[i] == &globals) 03374 ast_rwlock_unlock(&globalslock); 03375 } 03376 if (s == ¬_found || s == NULL) { 03377 ast_debug(5, "Result of '%s' is NULL\n", var); 03378 ret = NULL; 03379 } else { 03380 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03381 if (s != ast_str_buffer(*str)) { 03382 ast_str_set(str, maxlen, "%s", s); 03383 } 03384 ret = ast_str_buffer(*str); 03385 if (need_substring) { 03386 ret = ast_str_substring(*str, offset, length); 03387 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03388 } 03389 } 03390 03391 if (c) { 03392 ast_channel_unlock(c); 03393 } 03394 return ret; 03395 }
| void ast_str_substitute_variables | ( | struct ast_str ** | buf, | |
| ssize_t | maxlen, | |||
| struct ast_channel * | chan, | |||
| const char * | templ | |||
| ) |
| buf | Result will be placed in this buffer. | |
| maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
| chan | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
| templ | Variable template to expand. |
Definition at line 4069 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), config_curl(), custom_log(), cut_internal(), destroy_curl(), do_notify(), exec_exec(), func_mchan_read(), function_eval2(), function_fieldnum_helper(), function_fieldqty_helper(), handle_getvariablefull(), import_helper(), listfilter(), make_email_file(), realtime_curl(), realtime_multi_curl(), replace(), require_curl(), sendmail(), sendpage(), shift_pop(), store_curl(), strreplace(), syslog_log(), tryexec_exec(), unshift_push(), update2_curl(), and update_curl().
04070 { 04071 size_t used; 04072 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 04073 }
| void ast_str_substitute_variables_full | ( | struct ast_str ** | buf, | |
| ssize_t | maxlen, | |||
| struct ast_channel * | c, | |||
| struct varshead * | headp, | |||
| const char * | templ, | |||
| size_t * | used | |||
| ) |
| buf | Result will be placed in this buffer. | |
| maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
| c | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
| headp | If no channel is specified, a channel list from which to extract variable values | |
| templ | Variable template to expand. | |
| used | Number of bytes read from the template. |
Definition at line 3890 of file pbx.c.
References ast_channel_unref, ast_debug, ast_dummy_channel_alloc(), ast_free, ast_func_read2(), ast_log(), ast_str_append(), ast_str_append_substr(), ast_str_buffer(), ast_str_create(), ast_str_expr(), ast_str_reset(), ast_str_retrieve_variable(), ast_str_set_substr(), ast_str_strlen(), ast_str_substitute_variables_full(), ast_str_substring(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), and ast_channel::varshead.
Referenced by ast_str_substitute_variables(), ast_str_substitute_variables_full(), and ast_str_substitute_variables_varshead().
03891 { 03892 /* Substitutes variables into buf, based on string templ */ 03893 char *cp4 = NULL; 03894 const char *whereweare; 03895 int orig_size = 0; 03896 int offset, offset2, isfunction; 03897 const char *nextvar, *nextexp, *nextthing; 03898 const char *vars, *vare; 03899 char *finalvars; 03900 int pos, brackets, needsub, len; 03901 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 03902 03903 ast_str_reset(*buf); 03904 whereweare = templ; 03905 while (!ast_strlen_zero(whereweare)) { 03906 /* reset our buffer */ 03907 ast_str_reset(substr3); 03908 03909 /* Assume we're copying the whole remaining string */ 03910 pos = strlen(whereweare); 03911 nextvar = NULL; 03912 nextexp = NULL; 03913 nextthing = strchr(whereweare, '$'); 03914 if (nextthing) { 03915 switch (nextthing[1]) { 03916 case '{': 03917 nextvar = nextthing; 03918 pos = nextvar - whereweare; 03919 break; 03920 case '[': 03921 nextexp = nextthing; 03922 pos = nextexp - whereweare; 03923 break; 03924 default: 03925 pos = 1; 03926 } 03927 } 03928 03929 if (pos) { 03930 /* Copy that many bytes */ 03931 ast_str_append_substr(buf, maxlen, whereweare, pos); 03932 03933 templ += pos; 03934 whereweare += pos; 03935 } 03936 03937 if (nextvar) { 03938 /* We have a variable. Find the start and end, and determine 03939 if we are going to have to recursively call ourselves on the 03940 contents */ 03941 vars = vare = nextvar + 2; 03942 brackets = 1; 03943 needsub = 0; 03944 03945 /* Find the end of it */ 03946 while (brackets && *vare) { 03947 if ((vare[0] == '$') && (vare[1] == '{')) { 03948 needsub++; 03949 } else if (vare[0] == '{') { 03950 brackets++; 03951 } else if (vare[0] == '}') { 03952 brackets--; 03953 } else if ((vare[0] == '$') && (vare[1] == '[')) 03954 needsub++; 03955 vare++; 03956 } 03957 if (brackets) 03958 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 03959 len = vare - vars - 1; 03960 03961 /* Skip totally over variable string */ 03962 whereweare += (len + 3); 03963 03964 /* Store variable name (and truncate) */ 03965 ast_str_set_substr(&substr1, 0, vars, len); 03966 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 03967 03968 /* Substitute if necessary */ 03969 if (needsub) { 03970 size_t used; 03971 if (!substr2) { 03972 substr2 = ast_str_create(16); 03973 } 03974 03975 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03976 finalvars = ast_str_buffer(substr2); 03977 } else { 03978 finalvars = ast_str_buffer(substr1); 03979 } 03980 03981 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 03982 if (isfunction) { 03983 /* Evaluate function */ 03984 if (c || !headp) { 03985 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03986 } else { 03987 struct varshead old; 03988 struct ast_channel *bogus = ast_dummy_channel_alloc(); 03989 if (bogus) { 03990 memcpy(&old, &bogus->varshead, sizeof(old)); 03991 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 03992 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03993 /* Don't deallocate the varshead that was passed in */ 03994 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 03995 ast_channel_unref(bogus); 03996 } else { 03997 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03998 } 03999 } 04000 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 04001 } else { 04002 /* Retrieve variable value */ 04003 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 04004 cp4 = ast_str_buffer(substr3); 04005 } 04006 if (cp4) { 04007 ast_str_substring(substr3, offset, offset2); 04008 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04009 } 04010 } else if (nextexp) { 04011 /* We have an expression. Find the start and end, and determine 04012 if we are going to have to recursively call ourselves on the 04013 contents */ 04014 vars = vare = nextexp + 2; 04015 brackets = 1; 04016 needsub = 0; 04017 04018 /* Find the end of it */ 04019 while (brackets && *vare) { 04020 if ((vare[0] == '$') && (vare[1] == '[')) { 04021 needsub++; 04022 brackets++; 04023 vare++; 04024 } else if (vare[0] == '[') { 04025 brackets++; 04026 } else if (vare[0] == ']') { 04027 brackets--; 04028 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04029 needsub++; 04030 vare++; 04031 } 04032 vare++; 04033 } 04034 if (brackets) 04035 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04036 len = vare - vars - 1; 04037 04038 /* Skip totally over expression */ 04039 whereweare += (len + 3); 04040 04041 /* Store variable name (and truncate) */ 04042 ast_str_set_substr(&substr1, 0, vars, len); 04043 04044 /* Substitute if necessary */ 04045 if (needsub) { 04046 size_t used; 04047 if (!substr2) { 04048 substr2 = ast_str_create(16); 04049 } 04050 04051 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04052 finalvars = ast_str_buffer(substr2); 04053 } else { 04054 finalvars = ast_str_buffer(substr1); 04055 } 04056 04057 if (ast_str_expr(&substr3, 0, c, finalvars)) { 04058 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 04059 } 04060 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04061 } 04062 } 04063 *used = ast_str_strlen(*buf) - orig_size; 04064 ast_free(substr1); 04065 ast_free(substr2); 04066 ast_free(substr3); 04067 }
| void ast_str_substitute_variables_varshead | ( | struct ast_str ** | buf, | |
| ssize_t | maxlen, | |||
| struct varshead * | headp, | |||
| const char * | templ | |||
| ) |
| buf | Result will be placed in this buffer. | |
| maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
| headp | If no channel is specified, a channel list from which to extract variable values | |
| templ | Variable template to expand. |
Definition at line 4075 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by add_user_extension(), build_user_routes(), phoneprov_callback(), pp_each_extension_helper(), and pp_each_user_helper().
04076 { 04077 size_t used; 04078 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 04079 }
| static const char* ast_str_substring | ( | struct ast_str * | value, | |
| int | offset, | |||
| int | length | |||
| ) | [static] |
Definition at line 3186 of file pbx.c.
References ast_str_buffer(), ast_str_reset(), ast_str_strlen(), and ast_str_update().
Referenced by ast_str_retrieve_variable(), and ast_str_substitute_variables_full().
03187 { 03188 int lr; /* length of the input string after the copy */ 03189 03190 lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */ 03191 03192 /* Quick check if no need to do anything */ 03193 if (offset == 0 && length >= lr) /* take the whole string */ 03194 return ast_str_buffer(value); 03195 03196 if (offset < 0) { /* translate negative offset into positive ones */ 03197 offset = lr + offset; 03198 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 03199 offset = 0; 03200 } 03201 03202 /* too large offset result in empty string so we know what to return */ 03203 if (offset >= lr) { 03204 ast_str_reset(value); 03205 return ast_str_buffer(value); 03206 } 03207 03208 if (offset > 0) { 03209 /* Go ahead and chop off the beginning */ 03210 memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1); 03211 lr -= offset; 03212 } 03213 03214 if (length >= 0 && length < lr) { /* truncate if necessary */ 03215 char *tmp = ast_str_buffer(value); 03216 tmp[length] = '\0'; 03217 ast_str_update(value); 03218 } else if (length < 0) { 03219 if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */ 03220 char *tmp = ast_str_buffer(value); 03221 tmp[lr + length] = '\0'; 03222 ast_str_update(value); 03223 } else { 03224 ast_str_reset(value); 03225 } 03226 } else { 03227 /* Nothing to do, but update the buffer length */ 03228 ast_str_update(value); 03229 } 03230 03231 return ast_str_buffer(value); 03232 }
| 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 10507 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().
10508 { 10509 return ast_rwlock_unlock(&con->lock); 10510 }
| int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
| 0 | on success | |
| -1 | on failure |
Definition at line 10489 of file pbx.c.
References ast_mutex_unlock, and conlock.
Referenced by _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
10490 { 10491 return ast_mutex_unlock(&conlock); 10492 }
| 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) |
| 0 | success | |
| -1 | failure |
Definition at line 7303 of file pbx.c.
References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, ast_app::name, and unreference_cached_app().
Referenced by __unload_module(), load_module(), and unload_module().
07304 { 07305 struct ast_app *tmp; 07306 07307 AST_RWLIST_WRLOCK(&apps); 07308 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 07309 if (!strcasecmp(app, tmp->name)) { 07310 unreference_cached_app(tmp); 07311 AST_RWLIST_REMOVE_CURRENT(list); 07312 ast_verb(2, "Unregistered application '%s'\n", tmp->name); 07313 ast_string_field_free_memory(tmp); 07314 ast_free(tmp); 07315 break; 07316 } 07317 } 07318 AST_RWLIST_TRAVERSE_SAFE_END; 07319 AST_RWLIST_UNLOCK(&apps); 07320 07321 return tmp ? 0 : -1; 07322 }
| void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
| sw | switch to unregister |
Definition at line 6075 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
06076 { 06077 AST_RWLIST_WRLOCK(&switches); 06078 AST_RWLIST_REMOVE(&switches, sw, list); 06079 AST_RWLIST_UNLOCK(&switches); 06080 }
| struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
| struct ast_exten * | exten | |||
| ) | [read] |
Definition at line 10621 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().
10623 { 10624 if (!exten) 10625 return con ? con->root : NULL; 10626 else 10627 return exten->next; 10628 }
| struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
| struct ast_ignorepat * | ip | |||
| ) | [read] |
Definition at line 10654 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().
10656 { 10657 if (!ip) 10658 return con ? con->ignorepats : NULL; 10659 else 10660 return ip->next; 10661 }
| struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
| struct ast_include * | inc | |||
| ) | [read] |
Definition at line 10645 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().
10647 { 10648 if (!inc) 10649 return con ? con->includes : NULL; 10650 else 10651 return inc->next; 10652 }
| struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
| struct ast_sw * | sw | |||
| ) | [read] |
Definition at line 10630 of file pbx.c.
References ast_context::alts, 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().
10632 { 10633 if (!sw) 10634 return con ? AST_LIST_FIRST(&con->alts) : NULL; 10635 else 10636 return AST_LIST_NEXT(sw, list); 10637 }
| struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 10616 of file pbx.c.
References contexts, and ast_context::next.
Referenced by _macro_exec(), ast_context_find(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_load_module(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
| struct ast_exten* ast_walk_extension_priorities | ( | struct ast_exten * | exten, | |
| struct ast_exten * | priority | |||
| ) | [read] |
Definition at line 10639 of file pbx.c.
References ast_exten::peer.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), show_dialplan_helper(), and unreference_cached_app().
10641 { 10642 return priority ? priority->peer : exten; 10643 }
| 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 10497 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().
10498 { 10499 return ast_rwlock_wrlock(&con->lock); 10500 }
| int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
| 0 | on success | |
| -1 | on error |
Definition at line 10479 of file pbx.c.
References ast_mutex_lock, and conlock.
Referenced by ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and complete_dialplan_remove_include().
10480 { 10481 return ast_mutex_lock(&conlock); 10482 }
| static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 8850 of file pbx.c.
References ast_channel::_state, async_stat::app, async_stat::appdata, ast_channel_name(), 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, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, pbx_exec(), pbx_findapp(), ast_channel::priority, async_stat::priority, ast_frame::subclass, and async_stat::timeout.
Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
08851 { 08852 struct async_stat *as = data; 08853 struct ast_channel *chan = as->chan; 08854 int timeout = as->timeout; 08855 int res; 08856 struct ast_frame *f; 08857 struct ast_app *app; 08858 08859 while (timeout && (chan->_state != AST_STATE_UP)) { 08860 res = ast_waitfor(chan, timeout); 08861 if (res < 1) 08862 break; 08863 if (timeout > -1) 08864 timeout = res; 08865 f = ast_read(chan); 08866 if (!f) 08867 break; 08868 if (f->frametype == AST_FRAME_CONTROL) { 08869 if ((f->subclass.integer == AST_CONTROL_BUSY) || 08870 (f->subclass.integer == AST_CONTROL_CONGESTION) ) { 08871 ast_frfree(f); 08872 break; 08873 } 08874 } 08875 ast_frfree(f); 08876 } 08877 if (chan->_state == AST_STATE_UP) { 08878 if (!ast_strlen_zero(as->app)) { 08879 app = pbx_findapp(as->app); 08880 if (app) { 08881 ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, ast_channel_name(chan)); 08882 pbx_exec(chan, app, as->appdata); 08883 } else 08884 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 08885 } else { 08886 if (!ast_strlen_zero(as->context)) 08887 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 08888 if (!ast_strlen_zero(as->exten)) 08889 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 08890 if (as->priority > 0) 08891 chan->priority = as->priority; 08892 /* Run the PBX */ 08893 if (ast_pbx_run(chan)) { 08894 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(chan)); 08895 } else { 08896 /* PBX will have taken care of this */ 08897 chan = NULL; 08898 } 08899 } 08900 } 08901 ast_free(as); 08902 if (chan) 08903 ast_hangup(chan); 08904 return NULL; 08905 }
| static void cli_match_char_tree | ( | struct match_char * | node, | |
| char * | prefix, | |||
| int | fd | |||
| ) | [static] |
Definition at line 1729 of file pbx.c.
References match_char::alt_char, ast_cli(), ast_str_alloca, ast_str_buffer(), ast_str_set(), match_char::deleted, ast_exten::exten, match_char::exten, match_char::is_pattern, match_char::next_char, match_char::specificity, and match_char::x.
Referenced by show_debug_helper().
01730 { 01731 char extenstr[40]; 01732 struct ast_str *my_prefix = ast_str_alloca(1024); 01733 01734 extenstr[0] = '\0'; 01735 01736 if (node && node->exten) 01737 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01738 01739 if (strlen(node->x) > 1) { 01740 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01741 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01742 node->exten ? node->exten->exten : "", extenstr); 01743 } else { 01744 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01745 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01746 node->exten ? node->exten->exten : "", extenstr); 01747 } 01748 01749 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01750 01751 if (node->next_char) 01752 cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd); 01753 01754 if (node->alt_char) 01755 cli_match_char_tree(node->alt_char, prefix, fd); 01756 }
| static int collect_digits | ( | struct ast_channel * | c, | |
| int | waittime, | |||
| char * | buf, | |||
| int | buflen, | |||
| int | pos | |||
| ) | [static] |
collect digits from the channel into the buffer.
| c,buf,buflen,pos | ||
| waittime | is in milliseconds |
| 0 | on timeout or done. | |
| -1 | on error. |
Definition at line 5072 of file pbx.c.
References ast_channel::_softhangup, ast_channel_clear_softhangup(), ast_matchmore_extension(), AST_SOFTHANGUP_ASYNCGOTO, ast_waitfordigit(), ast_channel::caller, ast_channel::context, ast_pbx::dtimeoutms, ast_party_caller::id, ast_party_id::number, ast_channel::pbx, S_COR, ast_party_number::str, and ast_party_number::valid.
Referenced by __ast_pbx_run().
05073 { 05074 int digit; 05075 05076 buf[pos] = '\0'; /* make sure it is properly terminated */ 05077 while (ast_matchmore_extension(c, c->context, buf, 1, 05078 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 05079 /* As long as we're willing to wait, and as long as it's not defined, 05080 keep reading digits until we can't possibly get a right answer anymore. */ 05081 digit = ast_waitfordigit(c, waittime); 05082 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 05083 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 05084 } else { 05085 if (!digit) /* No entry */ 05086 break; 05087 if (digit < 0) /* Error, maybe a hangup */ 05088 return -1; 05089 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 05090 buf[pos++] = digit; 05091 buf[pos] = '\0'; 05092 } 05093 waittime = c->pbx->dtimeoutms; 05094 } 05095 } 05096 return 0; 05097 }
| static int compare_char | ( | const void * | a, | |
| const void * | b | |||
| ) | [static] |
Definition at line 1177 of file pbx.c.
Referenced by get_pattern_node().
01178 { 01179 const unsigned char *ac = a; 01180 const unsigned char *bc = b; 01181 01182 return *ac - *bc; 01183 }
| 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 6262 of file pbx.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_get_extension_name(), ast_strdup, ast_hint::exten, and hints.
Referenced by handle_show_hint().
06263 { 06264 struct ast_hint *hint; 06265 char *ret = NULL; 06266 int which = 0; 06267 int wordlen; 06268 struct ao2_iterator i; 06269 06270 if (pos != 3) 06271 return NULL; 06272 06273 wordlen = strlen(word); 06274 06275 /* walk through all hints */ 06276 i = ao2_iterator_init(hints, 0); 06277 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06278 ao2_lock(hint); 06279 if (!hint->exten) { 06280 /* The extension has already been destroyed */ 06281 ao2_unlock(hint); 06282 continue; 06283 } 06284 if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) { 06285 ret = ast_strdup(ast_get_extension_name(hint->exten)); 06286 ao2_unlock(hint); 06287 ao2_ref(hint, -1); 06288 break; 06289 } 06290 ao2_unlock(hint); 06291 } 06292 ao2_iterator_destroy(&i); 06293 06294 return ret; 06295 }
| static char* complete_show_dialplan_context | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 6472 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().
06474 { 06475 struct ast_context *c = NULL; 06476 char *ret = NULL; 06477 int which = 0; 06478 int wordlen; 06479 06480 /* we are do completion of [exten@]context on second position only */ 06481 if (pos != 2) 06482 return NULL; 06483 06484 ast_rdlock_contexts(); 06485 06486 wordlen = strlen(word); 06487 06488 /* walk through all contexts and return the n-th match */ 06489 while ( (c = ast_walk_contexts(c)) ) { 06490 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 06491 ret = ast_strdup(ast_get_context_name(c)); 06492 break; 06493 } 06494 } 06495 06496 ast_unlock_contexts(); 06497 06498 return ret; 06499 }
| static void context_merge | ( | struct ast_context ** | extcontexts, | |
| struct ast_hashtab * | exttable, | |||
| struct ast_context * | context, | |||
| const char * | registrar | |||
| ) | [static] |
Definition at line 7444 of file pbx.c.
References ast_exten::app, ast_add_extension2(), ast_context_find_or_create(), ast_hashtab_end_traversal(), ast_hashtab_lookup(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_log(), ast_strdup, ast_verb, ast_exten::cidmatch, context_merge_incls_swits_igps_other_registrars(), ast_exten::data, ast_exten::datad, ast_exten::exten, first, ast_exten::label, LOG_ERROR, ast_exten::matchcid, ast_context::name, ast_exten::peer_table, ast_exten::priority, ast_context::refcount, ast_context::registrar, ast_exten::registrar, and ast_context::root_table.
Referenced by ast_merge_contexts_and_delete().
07445 { 07446 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */ 07447 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item; 07448 struct ast_hashtab_iter *exten_iter; 07449 struct ast_hashtab_iter *prio_iter; 07450 int insert_count = 0; 07451 int first = 1; 07452 07453 /* We'll traverse all the extensions/prios, and see which are not registrar'd with 07454 the current registrar, and copy them to the new context. If the new context does not 07455 exist, we'll create it "on demand". If no items are in this context to copy, then we'll 07456 only create the empty matching context if the old one meets the criteria */ 07457 07458 if (context->root_table) { 07459 exten_iter = ast_hashtab_start_traversal(context->root_table); 07460 while ((exten_item=ast_hashtab_next(exten_iter))) { 07461 if (new) { 07462 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item); 07463 } else { 07464 new_exten_item = NULL; 07465 } 07466 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 07467 while ((prio_item=ast_hashtab_next(prio_iter))) { 07468 int res1; 07469 char *dupdstr; 07470 07471 if (new_exten_item) { 07472 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item); 07473 } else { 07474 new_prio_item = NULL; 07475 } 07476 if (strcmp(prio_item->registrar,registrar) == 0) { 07477 continue; 07478 } 07479 /* make sure the new context exists, so we have somewhere to stick this exten/prio */ 07480 if (!new) { 07481 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 */ 07482 } 07483 07484 /* copy in the includes, switches, and ignorepats */ 07485 if (first) { /* but, only need to do this once */ 07486 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07487 first = 0; 07488 } 07489 07490 if (!new) { 07491 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name); 07492 return; /* no sense continuing. */ 07493 } 07494 /* we will not replace existing entries in the new context with stuff from the old context. 07495 but, if this is because of some sort of registrar conflict, we ought to say something... */ 07496 07497 dupdstr = ast_strdup(prio_item->data); 07498 07499 res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 07500 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar); 07501 if (!res1 && new_exten_item && new_prio_item){ 07502 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n", 07503 context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar); 07504 } else { 07505 /* 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, 07506 and no double frees take place, either! */ 07507 insert_count++; 07508 } 07509 } 07510 ast_hashtab_end_traversal(prio_iter); 07511 } 07512 ast_hashtab_end_traversal(exten_iter); 07513 } 07514 07515 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 || 07516 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) { 07517 /* we could have given it the registrar of the other module who incremented the refcount, 07518 but that's not available, so we give it the registrar we know about */ 07519 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar); 07520 07521 /* copy in the includes, switches, and ignorepats */ 07522 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07523 } 07524 }
| static void context_merge_incls_swits_igps_other_registrars | ( | struct ast_context * | new, | |
| struct ast_context * | old, | |||
| const char * | registrar | |||
| ) | [static] |
Definition at line 7411 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().
07412 { 07413 struct ast_include *i; 07414 struct ast_ignorepat *ip; 07415 struct ast_sw *sw; 07416 07417 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); 07418 /* copy in the includes, switches, and ignorepats */ 07419 /* walk through includes */ 07420 for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) { 07421 if (strcmp(ast_get_include_registrar(i), registrar) == 0) 07422 continue; /* not mine */ 07423 ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i)); 07424 } 07425 07426 /* walk through switches */ 07427 for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) { 07428 if (strcmp(ast_get_switch_registrar(sw), registrar) == 0) 07429 continue; /* not mine */ 07430 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)); 07431 } 07432 07433 /* walk thru ignorepats ... */ 07434 for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) { 07435 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) 07436 continue; /* not mine */ 07437 ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip)); 07438 } 07439 }
| static void create_match_char_tree | ( | struct ast_context * | con | ) | [static] |
Definition at line 2350 of file pbx.c.
References add_exten_to_pattern_tree(), ast_debug, ast_hashtab_end_traversal(), ast_hashtab_get_stats(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_log(), ast_exten::exten, LOG_ERROR, ast_context::name, and ast_context::root_table.
Referenced by pbx_find_extension().
02351 { 02352 struct ast_hashtab_iter *t1; 02353 struct ast_exten *e1; 02354 #ifdef NEED_DEBUG 02355 int biggest_bucket, resizes, numobjs, numbucks; 02356 02357 ast_debug(1, "Creating Extension Trie for context %s(%p)\n", con->name, con); 02358 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks); 02359 ast_debug(1, "This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n", 02360 numobjs, numbucks, biggest_bucket, resizes); 02361 #endif 02362 t1 = ast_hashtab_start_traversal(con->root_table); 02363 while ((e1 = ast_hashtab_next(t1))) { 02364 if (e1->exten) { 02365 add_exten_to_pattern_tree(con, e1, 0); 02366 } else { 02367 ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n"); 02368 } 02369 } 02370 ast_hashtab_end_traversal(t1); 02371 }
| static void decrease_call_count | ( | void | ) | [static] |
Definition at line 5452 of file pbx.c.
References ast_mutex_lock, ast_mutex_unlock, countcalls, and maxcalllock.
Referenced by ast_pbx_run_args(), ast_pbx_start(), and pbx_thread().
05453 { 05454 ast_mutex_lock(&maxcalllock); 05455 if (countcalls > 0) 05456 countcalls--; 05457 ast_mutex_unlock(&maxcalllock); 05458 }
| static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 5460 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().
05461 { 05462 if (e->priority == PRIORITY_HINT) 05463 ast_remove_hint(e); 05464 05465 if (e->peer_table) 05466 ast_hashtab_destroy(e->peer_table,0); 05467 if (e->peer_label_table) 05468 ast_hashtab_destroy(e->peer_label_table, 0); 05469 if (e->datad) 05470 e->datad(e->data); 05471 ast_free(e); 05472 }
| static void destroy_hint | ( | void * | obj | ) | [static] |
Definition at line 4824 of file pbx.c.
References ao2_callback, ao2_ref, AST_EXTENSION_DEACTIVATED, ast_get_context_name(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, ast_state_cb::change_cb, ast_hint::context_name, ast_state_cb::data, ast_hint::exten, ast_hint::exten_name, and OBJ_UNLINK.
Referenced by ast_add_hint().
04825 { 04826 struct ast_hint *hint = obj; 04827 04828 if (hint->callbacks) { 04829 struct ast_state_cb *state_cb; 04830 const char *context_name; 04831 const char *exten_name; 04832 04833 if (hint->exten) { 04834 context_name = ast_get_context_name(ast_get_extension_context(hint->exten)); 04835 exten_name = ast_get_extension_name(hint->exten); 04836 hint->exten = NULL; 04837 } else { 04838 /* The extension has already been destroyed */ 04839 context_name = hint->context_name; 04840 exten_name = hint->exten_name; 04841 } 04842 while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 04843 /* Notify with -1 and remove all callbacks */ 04844 state_cb->change_cb(context_name, exten_name, AST_EXTENSION_DEACTIVATED, 04845 state_cb->data); 04846 ao2_ref(state_cb, -1); 04847 } 04848 ao2_ref(hint->callbacks, -1); 04849 } 04850 }
| static void destroy_pattern_tree | ( | struct match_char * | pattern_tree | ) | [static] |
Definition at line 2373 of file pbx.c.
References match_char::alt_char, ast_free, match_char::exten, and match_char::next_char.
Referenced by __ast_internal_context_destroy().
02374 { 02375 /* destroy all the alternates */ 02376 if (pattern_tree->alt_char) { 02377 destroy_pattern_tree(pattern_tree->alt_char); 02378 pattern_tree->alt_char = 0; 02379 } 02380 /* destroy all the nexts */ 02381 if (pattern_tree->next_char) { 02382 destroy_pattern_tree(pattern_tree->next_char); 02383 pattern_tree->next_char = 0; 02384 } 02385 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */ 02386 ast_free(pattern_tree); 02387 }
| static void destroy_state_cb | ( | void * | doomed | ) | [static] |
Definition at line 4655 of file pbx.c.
References ast_state_cb::data, ast_state_cb::destroy_cb, and ast_state_cb::id.
Referenced by ast_extension_state_add_destroy().
04656 { 04657 struct ast_state_cb *state_cb = doomed; 04658 04659 if (state_cb->destroy_cb) { 04660 state_cb->destroy_cb(state_cb->id, state_cb->data); 04661 } 04662 }
| static void device_state_cb | ( | const struct ast_event * | event, | |
| void * | unused | |||
| ) | [static] |
Definition at line 10374 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.
10375 { 10376 const char *device; 10377 struct statechange *sc; 10378 10379 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 10380 if (ast_strlen_zero(device)) { 10381 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n"); 10382 return; 10383 } 10384 10385 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1))) 10386 return; 10387 strcpy(sc->dev, device); 10388 if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) { 10389 ast_free(sc); 10390 } 10391 }
| static void exception_store_free | ( | void * | data | ) | [static] |
Definition at line 3397 of file pbx.c.
References ast_free, and ast_string_field_free_memory.
03398 { 03399 struct pbx_exception *exception = data; 03400 ast_string_field_free_memory(exception); 03401 ast_free(exception); 03402 }
| static int ext_cmp | ( | const char * | a, | |
| const char * | b | |||
| ) | [static] |
the full routine to compare extensions in rules.
Definition at line 2523 of file pbx.c.
References ext_cmp1().
Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().
02524 { 02525 /* make sure non-patterns come first. 02526 * If a is not a pattern, it either comes first or 02527 * we do a more complex pattern comparison. 02528 */ 02529 int ret = 0; 02530 02531 if (a[0] != '_') 02532 return (b[0] == '_') ? -1 : strcmp(a, b); 02533 02534 /* Now we know a is a pattern; if b is not, a comes first */ 02535 if (b[0] != '_') 02536 return 1; 02537 02538 /* ok we need full pattern sorting routine. 02539 * skip past the underscores */ 02540 ++a; ++b; 02541 do { 02542 unsigned char bitwise[2][32] = { { 0, } }; 02543 ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]); 02544 if (ret == 0) { 02545 /* Are the classes different, even though they score the same? */ 02546 ret = memcmp(bitwise[0], bitwise[1], 32); 02547 } 02548 } while (!ret && a && b); 02549 if (ret == 0) { 02550 return 0; 02551 } else { 02552 return (ret > 0) ? 1 : -1; 02553 } 02554 }
| static int ext_cmp1 | ( | const char ** | p, | |
| unsigned char * | bitwise | |||
| ) | [static] |
helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first.
ext_cmp1 compares individual characters (or sets of), returning an int where bits 0-7 are the ASCII code of the first char in the set, while bit 8-15 are the cardinality of the set minus 1. This way more specific patterns (smaller cardinality) appear first. Wildcards have a special value, so that we can directly compare them to sets by subtracting the two values. In particular: 0x000xx one character, xx 0x0yyxx yy character set starting with xx 0x10000 '.' (one or more of anything) 0x20000 '!' (zero or more of anything) 0x30000 NUL (end of string) 0x40000 error in set. The pointer to the string is advanced according to needs. NOTES: 1. the empty set is equivalent to NUL. 2. given that a full set has always 0 as the first element, we could encode the special cases as 0xffXX where XX is 1, 2, 3, 4 as used above.
Definition at line 2443 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ext_cmp().
02444 { 02445 int c, cmin = 0xff, count = 0; 02446 const char *end; 02447 02448 /* load value and advance pointer */ 02449 c = *(*p)++; 02450 02451 /* always return unless we have a set of chars */ 02452 switch (toupper(c)) { 02453 default: /* ordinary character */ 02454 bitwise[c / 8] = 1 << (c % 8); 02455 return 0x0100 | (c & 0xff); 02456 02457 case 'N': /* 2..9 */ 02458 bitwise[6] = 0xfc; 02459 bitwise[7] = 0x03; 02460 return 0x0800 | '2'; 02461 02462 case 'X': /* 0..9 */ 02463 bitwise[6] = 0xff; 02464 bitwise[7] = 0x03; 02465 return 0x0A00 | '0'; 02466 02467 case 'Z': /* 1..9 */ 02468 bitwise[6] = 0xfe; 02469 bitwise[7] = 0x03; 02470 return 0x0900 | '1'; 02471 02472 case '.': /* wildcard */ 02473 return 0x18000; 02474 02475 case '!': /* earlymatch */ 02476 return 0x28000; /* less specific than NULL */ 02477 02478 case '\0': /* empty string */ 02479 *p = NULL; 02480 return 0x30000; 02481 02482 case '[': /* pattern */ 02483 break; 02484 } 02485 /* locate end of set */ 02486 end = strchr(*p, ']'); 02487 02488 if (end == NULL) { 02489 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02490 return 0x40000; /* XXX make this entry go last... */ 02491 } 02492 02493 for (; *p < end ; (*p)++) { 02494 unsigned char c1, c2; /* first-last char in range */ 02495 c1 = (unsigned char)((*p)[0]); 02496 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 02497 c2 = (unsigned char)((*p)[2]); 02498 *p += 2; /* skip a total of 3 chars */ 02499 } else { /* individual character */ 02500 c2 = c1; 02501 } 02502 if (c1 < cmin) { 02503 cmin = c1; 02504 } 02505 for (; c1 <= c2; c1++) { 02506 unsigned char mask = 1 << (c1 % 8); 02507 /*!\note If two patterns score the same, the one with the lowest 02508 * ascii values will compare as coming first. */ 02509 /* Flag the character as included (used) and count it. */ 02510 if (!(bitwise[ c1 / 8 ] & mask)) { 02511 bitwise[ c1 / 8 ] |= mask; 02512 count += 0x100; 02513 } 02514 } 02515 } 02516 (*p)++; 02517 return count == 0 ? 0x30000 : (count | cmin); 02518 }
| static int ext_strncpy | ( | char * | dst, | |
| const char * | src, | |||
| int | len | |||
| ) | [static] |
copy a string skipping whitespace
Definition at line 8407 of file pbx.c.
Referenced by ast_add_extension2_lockopt().
08408 { 08409 int count = 0; 08410 int insquares = 0; 08411 08412 while (*src && (count < len - 1)) { 08413 if (*src == '[') { 08414 insquares = 1; 08415 } else if (*src == ']') { 08416 insquares = 0; 08417 } else if (*src == ' ' && !insquares) { 08418 src++; 08419 continue; 08420 } 08421 *dst = *src; 08422 dst++; 08423 src++; 08424 count++; 08425 } 08426 *dst = '\0'; 08427 08428 return count; 08429 }
| static int extension_match_core | ( | const char * | pattern, | |
| const char * | data, | |||
| enum ext_match_t | mode | |||
| ) | [static] |
Definition at line 2736 of file pbx.c.
References _extension_match_core(), ast_add_profile(), ast_mark(), and ast_strlen_zero().
Referenced by ast_extension_close(), ast_extension_match(), and pbx_find_extension().
02737 { 02738 int i; 02739 static int prof_id = -2; /* marker for 'unallocated' id */ 02740 if (prof_id == -2) { 02741 prof_id = ast_add_profile("ext_match", 0); 02742 } 02743 ast_mark(prof_id, 1); 02744 i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode); 02745 ast_mark(prof_id, 0); 02746 return i; 02747 }
| 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 5586 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), contexts_table, and fake_context::name.
05587 { 05588 struct fake_context item; 05589 05590 ast_copy_string(item.name, context, sizeof(item.name)); 05591 05592 return ast_hashtab_lookup(contexts_table, &item); 05593 }
| 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 5600 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), contexts_table, and fake_context::name.
Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), and ast_context_unlockmacro().
05601 { 05602 struct ast_context *c; 05603 struct fake_context item; 05604 05605 ast_copy_string(item.name, context, sizeof(item.name)); 05606 05607 ast_rdlock_contexts(); 05608 c = ast_hashtab_lookup(contexts_table, &item); 05609 if (!c) { 05610 ast_unlock_contexts(); 05611 } 05612 05613 return c; 05614 }
| static int find_hint_by_cb_id | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Find Hint by callback id.
Definition at line 4759 of file pbx.c.
References ao2_find, ao2_ref, ast_hint::callbacks, CMP_MATCH, and CMP_STOP.
Referenced by ast_extension_state_del().
04760 { 04761 struct ast_state_cb *state_cb; 04762 const struct ast_hint *hint = obj; 04763 int *id = arg; 04764 04765 if ((state_cb = ao2_find(hint->callbacks, id, 0))) { 04766 ao2_ref(state_cb, -1); 04767 return CMP_MATCH | CMP_STOP; 04768 } 04769 04770 return 0; 04771 }
| 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 3766 of file pbx.c.
References args, ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), ast_func_read2(), and ast_func_write().
03767 { 03768 char *args = strchr(function, '('); 03769 03770 if (!args) { 03771 ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function); 03772 } else { 03773 char *p; 03774 *args++ = '\0'; 03775 if ((p = strrchr(args, ')'))) { 03776 *p = '\0'; 03777 } else { 03778 ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args); 03779 } 03780 } 03781 return args; 03782 }
| static struct ast_exten * get_canmatch_exten | ( | struct match_char * | node | ) | [static, read] |
Definition at line 1758 of file pbx.c.
References ast_log(), ast_exten::exten, match_char::exten, LOG_NOTICE, match_char::next_char, and match_char::x.
01759 { 01760 /* find the exten at the end of the rope */ 01761 struct match_char *node2 = node; 01762 01763 for (node2 = node; node2; node2 = node2->next_char) { 01764 if (node2->exten) { 01765 #ifdef NEED_DEBUG_HERE 01766 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten); 01767 #endif 01768 return node2->exten; 01769 } 01770 } 01771 #ifdef NEED_DEBUG_HERE 01772 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x); 01773 #endif 01774 return 0; 01775 }
| static const char* get_pattern_node | ( | struct pattern_node * | node, | |
| const char * | src, | |||
| int | pattern, | |||
| const char * | extenbuf | |||
| ) | [static] |
Definition at line 2107 of file pbx.c.
References ast_log(), pattern_node::buf, compare_char(), first, INC_DST_OVERFLOW_CHECK, last, LOG_ERROR, LOG_WARNING, and pattern_node::specif.
Referenced by add_exten_to_pattern_tree().
02108 { 02109 #define INC_DST_OVERFLOW_CHECK \ 02110 do { \ 02111 if (dst - node->buf < sizeof(node->buf) - 1) { \ 02112 ++dst; \ 02113 } else { \ 02114 overflow = 1; \ 02115 } \ 02116 } while (0) 02117 02118 node->specif = 0; 02119 node->buf[0] = '\0'; 02120 while (*src) { 02121 if (*src == '[' && pattern) { 02122 char *dst = node->buf; 02123 const char *src_next; 02124 int length; 02125 int overflow = 0; 02126 02127 /* get past the '[' */ 02128 ++src; 02129 for (;;) { 02130 if (*src == '\\') { 02131 /* Escaped character. */ 02132 ++src; 02133 if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') { 02134 *dst = *src++; 02135 INC_DST_OVERFLOW_CHECK; 02136 } 02137 } else if (*src == '-') { 02138 unsigned char first; 02139 unsigned char last; 02140 02141 src_next = src; 02142 first = *(src_next - 1); 02143 last = *++src_next; 02144 02145 if (last == '\\') { 02146 /* Escaped character. */ 02147 last = *++src_next; 02148 } 02149 02150 /* Possible char range. */ 02151 if (node->buf[0] && last) { 02152 /* Expand the char range. */ 02153 while (++first <= last) { 02154 *dst = first; 02155 INC_DST_OVERFLOW_CHECK; 02156 } 02157 src = src_next + 1; 02158 } else { 02159 /* 02160 * There was no left or right char for the range. 02161 * It is just a '-'. 02162 */ 02163 *dst = *src++; 02164 INC_DST_OVERFLOW_CHECK; 02165 } 02166 } else if (*src == '\0') { 02167 ast_log(LOG_WARNING, 02168 "A matching ']' was not found for '[' in exten pattern '%s'\n", 02169 extenbuf); 02170 break; 02171 } else if (*src == ']') { 02172 ++src; 02173 break; 02174 } else { 02175 *dst = *src++; 02176 INC_DST_OVERFLOW_CHECK; 02177 } 02178 } 02179 /* null terminate the exploded range */ 02180 *dst = '\0'; 02181 02182 if (overflow) { 02183 ast_log(LOG_ERROR, 02184 "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n", 02185 extenbuf); 02186 node->buf[0] = '\0'; 02187 continue; 02188 } 02189 02190 /* Sort the characters in character set. */ 02191 length = strlen(node->buf); 02192 if (!length) { 02193 ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n", 02194 extenbuf); 02195 node->buf[0] = '\0'; 02196 continue; 02197 } 02198 qsort(node->buf, length, 1, compare_char); 02199 02200 /* Remove duplicate characters from character set. */ 02201 dst = node->buf; 02202 src_next = node->buf; 02203 while (*src_next++) { 02204 if (*dst != *src_next) { 02205 *++dst = *src_next; 02206 } 02207 } 02208 02209 length = strlen(node->buf); 02210 length <<= 8; 02211 node->specif = length | (unsigned char) node->buf[0]; 02212 break; 02213 } else if (*src == '-') { 02214 /* Skip dashes in all extensions. */ 02215 ++src; 02216 } else { 02217 if (*src == '\\') { 02218 /* 02219 * XXX The escape character here does not remove any special 02220 * meaning to characters except the '[', '\\', and '-' 02221 * characters since they are special only in this function. 02222 */ 02223 node->buf[0] = *++src; 02224 if (!node->buf[0]) { 02225 break; 02226 } 02227 } else { 02228 node->buf[0] = *src; 02229 if (pattern) { 02230 /* make sure n,x,z patterns are canonicalized to N,X,Z */ 02231 if (node->buf[0] == 'n') { 02232 node->buf[0] = 'N'; 02233 } else if (node->buf[0] == 'x') { 02234 node->buf[0] = 'X'; 02235 } else if (node->buf[0] == 'z') { 02236 node->buf[0] = 'Z'; 02237 } 02238 } 02239 } 02240 node->buf[1] = '\0'; 02241 node->specif = 1; 02242 ++src; 02243 break; 02244 } 02245 } 02246 return src; 02247 02248 #undef INC_DST_OVERFLOW_CHECK 02249 }
| static unsigned get_range | ( | char * | src, | |
| int | max, | |||
| const char *const | names[], | |||
| const char * | msg | |||
| ) | [static] |
helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers.
Definition at line 7763 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and strsep().
Referenced by ast_build_timing().
07764 { 07765 int start, end; /* start and ending position */ 07766 unsigned int mask = 0; 07767 char *part; 07768 07769 /* Check for whole range */ 07770 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 07771 return (1 << max) - 1; 07772 } 07773 07774 while ((part = strsep(&src, "&"))) { 07775 /* Get start and ending position */ 07776 char *endpart = strchr(part, '-'); 07777 if (endpart) { 07778 *endpart++ = '\0'; 07779 } 07780 /* Find the start */ 07781 if ((start = lookup_name(part, names, max)) < 0) { 07782 ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part); 07783 continue; 07784 } 07785 if (endpart) { /* find end of range */ 07786 if ((end = lookup_name(endpart, names, max)) < 0) { 07787 ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart); 07788 continue; 07789 } 07790 } else { 07791 end = start; 07792 } 07793 /* Fill the mask. Remember that ranges are cyclic */ 07794 mask |= (1 << end); /* initialize with last element */ 07795 while (start != end) { 07796 mask |= (1 << start); 07797 if (++start >= max) { 07798 start = 0; 07799 } 07800 } 07801 } 07802 return mask; 07803 }
| static void get_timerange | ( | struct ast_timing * | i, | |
| char * | times | |||
| ) | [static] |
store a bitmask of valid times, one bit each 1 minute
Definition at line 7806 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, ast_timing::minmask, and strsep().
Referenced by ast_build_timing().
07807 { 07808 char *endpart, *part; 07809 int x; 07810 int st_h, st_m; 07811 int endh, endm; 07812 int minute_start, minute_end; 07813 07814 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 07815 memset(i->minmask, 0, sizeof(i->minmask)); 07816 07817 /* 1-minute per bit */ 07818 /* Star is all times */ 07819 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 07820 /* 48, because each hour takes 2 integers; 30 bits each */ 07821 for (x = 0; x < 48; x++) { 07822 i->minmask[x] = 0x3fffffff; /* 30 bits */ 07823 } 07824 return; 07825 } 07826 /* Otherwise expect a range */ 07827 while ((part = strsep(×, "&"))) { 07828 if (!(endpart = strchr(part, '-'))) { 07829 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 07830 ast_log(LOG_WARNING, "%s isn't a valid time.\n", part); 07831 continue; 07832 } 07833 i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30)); 07834 continue; 07835 } 07836 *endpart++ = '\0'; 07837 /* why skip non digits? Mostly to skip spaces */ 07838 while (*endpart && !isdigit(*endpart)) { 07839 endpart++; 07840 } 07841 if (!*endpart) { 07842 ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part); 07843 continue; 07844 } 07845 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 07846 ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part); 07847 continue; 07848 } 07849 if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) { 07850 ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart); 07851 continue; 07852 } 07853 minute_start = st_h * 60 + st_m; 07854 minute_end = endh * 60 + endm; 07855 /* Go through the time and enable each appropriate bit */ 07856 for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) { 07857 i->minmask[x / 30] |= (1 << (x % 30)); 07858 } 07859 /* Do the last one */ 07860 i->minmask[x / 30] |= (1 << (x % 30)); 07861 } 07862 /* All done */ 07863 return; 07864 }
| static char* handle_debug_dialplan | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Send ack once.
Definition at line 6797 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), dialplan_counters::context_existence, exten, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_debug_helper(), strsep(), dialplan_counters::total_context, ast_cli_entry::usage, and ast_cli_args::word.
06798 { 06799 char *exten = NULL, *context = NULL; 06800 /* Variables used for different counters */ 06801 struct dialplan_counters counters; 06802 const char *incstack[AST_PBX_MAX_STACK]; 06803 06804 switch (cmd) { 06805 case CLI_INIT: 06806 e->command = "dialplan debug"; 06807 e->usage = 06808 "Usage: dialplan debug [context]\n" 06809 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n"; 06810 return NULL; 06811 case CLI_GENERATE: 06812 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 06813 } 06814 06815 memset(&counters, 0, sizeof(counters)); 06816 06817 if (a->argc != 2 && a->argc != 3) 06818 return CLI_SHOWUSAGE; 06819 06820 /* we obtain [exten@]context? if yes, split them ... */ 06821 /* note: we ignore the exten totally here .... */ 06822 if (a->argc == 3) { 06823 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 06824 context = ast_strdupa(a->argv[2]); 06825 exten = strsep(&context, "@"); 06826 /* change empty strings to NULL */ 06827 if (ast_strlen_zero(exten)) 06828 exten = NULL; 06829 } else { /* no '@' char, only context given */ 06830 context = ast_strdupa(a->argv[2]); 06831 } 06832 if (ast_strlen_zero(context)) 06833 context = NULL; 06834 } 06835 /* else Show complete dial plan, context and exten are NULL */ 06836 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 06837 06838 /* check for input failure and throw some error messages */ 06839 if (context && !counters.context_existence) { 06840 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 06841 return CLI_FAILURE; 06842 } 06843 06844 06845 ast_cli(a->fd,"-= %d %s. =-\n", 06846 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 06847 06848 /* everything ok */ 06849 return CLI_SUCCESS; 06850 }
| static char* handle_set_chanvar | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 7167 of file pbx.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_get_by_name(), ast_channel_unref, ast_cli(), ast_complete_channels(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, pbx_builtin_setvar_helper(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
07168 { 07169 struct ast_channel *chan; 07170 const char *chan_name, *var_name, *var_value; 07171 07172 switch (cmd) { 07173 case CLI_INIT: 07174 e->command = "dialplan set chanvar"; 07175 e->usage = 07176 "Usage: dialplan set chanvar <channel> <varname> <value>\n" 07177 " Set channel variable <varname> to <value>\n"; 07178 return NULL; 07179 case CLI_GENERATE: 07180 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 07181 } 07182 07183 if (a->argc != e->args + 3) 07184 return CLI_SHOWUSAGE; 07185 07186 chan_name = a->argv[e->args]; 07187 var_name = a->argv[e->args + 1]; 07188 var_value = a->argv[e->args + 2]; 07189 07190 if (!(chan = ast_channel_get_by_name(chan_name))) { 07191 ast_cli(a->fd, "Channel '%s' not found\n", chan_name); 07192 return CLI_FAILURE; 07193 } 07194 07195 pbx_builtin_setvar_helper(chan, var_name, var_value); 07196 07197 chan = ast_channel_unref(chan); 07198 07199 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name); 07200 07201 return CLI_SUCCESS; 07202 }
| static char* handle_set_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 7204 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.
07205 { 07206 int oldval = 0; 07207 07208 switch (cmd) { 07209 case CLI_INIT: 07210 e->command = "dialplan set extenpatternmatchnew true"; 07211 e->usage = 07212 "Usage: dialplan set extenpatternmatchnew true|false\n" 07213 " Use the NEW extension pattern matching algorithm, true or false.\n"; 07214 return NULL; 07215 case CLI_GENERATE: 07216 return NULL; 07217 } 07218 07219 if (a->argc != 4) 07220 return CLI_SHOWUSAGE; 07221 07222 oldval = pbx_set_extenpatternmatchnew(1); 07223 07224 if (oldval) 07225 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n"); 07226 else 07227 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n"); 07228 07229 return CLI_SUCCESS; 07230 }
| static char* handle_set_global | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 7145 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.
07146 { 07147 switch (cmd) { 07148 case CLI_INIT: 07149 e->command = "dialplan set global"; 07150 e->usage = 07151 "Usage: dialplan set global <name> <value>\n" 07152 " Set global dialplan variable <name> to <value>\n"; 07153 return NULL; 07154 case CLI_GENERATE: 07155 return NULL; 07156 } 07157 07158 if (a->argc != e->args + 2) 07159 return CLI_SHOWUSAGE; 07160 07161 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]); 07162 ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]); 07163 07164 return CLI_SUCCESS; 07165 }
| static char* handle_show_application | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6161 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_complete_applications(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_app::name, print_app_docs(), ast_cli_entry::usage, and ast_cli_args::word.
06162 { 06163 struct ast_app *aa; 06164 int app, no_registered_app = 1; 06165 06166 switch (cmd) { 06167 case CLI_INIT: 06168 e->command = "core show application"; 06169 e->usage = 06170 "Usage: core show application <application> [<application> [<application> [...]]]\n" 06171 " Describes a particular application.\n"; 06172 return NULL; 06173 case CLI_GENERATE: 06174 /* 06175 * There is a possibility to show informations about more than one 06176 * application at one time. You can type 'show application Dial Echo' and 06177 * you will see informations about these two applications ... 06178 */ 06179 return ast_complete_applications(a->line, a->word, a->n); 06180 } 06181 06182 if (a->argc < 4) { 06183 return CLI_SHOWUSAGE; 06184 } 06185 06186 AST_RWLIST_RDLOCK(&apps); 06187 AST_RWLIST_TRAVERSE(&apps, aa, list) { 06188 /* Check for each app that was supplied as an argument */ 06189 for (app = 3; app < a->argc; app++) { 06190 if (strcasecmp(aa->name, a->argv[app])) { 06191 continue; 06192 } 06193 06194 /* We found it! */ 06195 no_registered_app = 0; 06196 06197 print_app_docs(aa, a->fd); 06198 } 06199 } 06200 AST_RWLIST_UNLOCK(&apps); 06201 06202 /* we found at least one app? no? */ 06203 if (no_registered_app) { 06204 ast_cli(a->fd, "Your application(s) is (are) not registered\n"); 06205 return CLI_FAILURE; 06206 } 06207 06208 return CLI_SUCCESS; 06209 }
| static char* handle_show_applications | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6386 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_cli_complete(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_app::description, ast_cli_args::fd, ast_cli_args::n, ast_app::name, ast_cli_args::pos, strcasestr(), ast_app::synopsis, ast_cli_entry::usage, and ast_cli_args::word.
06387 { 06388 struct ast_app *aa; 06389 int like = 0, describing = 0; 06390 int total_match = 0; /* Number of matches in like clause */ 06391 int total_apps = 0; /* Number of apps registered */ 06392 static const char * const choices[] = { "like", "describing", NULL }; 06393 06394 switch (cmd) { 06395 case CLI_INIT: 06396 e->command = "core show applications [like|describing]"; 06397 e->usage = 06398 "Usage: core show applications [{like|describing} <text>]\n" 06399 " List applications which are currently available.\n" 06400 " If 'like', <text> will be a substring of the app name\n" 06401 " If 'describing', <text> will be a substring of the description\n"; 06402 return NULL; 06403 case CLI_GENERATE: 06404 return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n); 06405 } 06406 06407 AST_RWLIST_RDLOCK(&apps); 06408 06409 if (AST_RWLIST_EMPTY(&apps)) { 06410 ast_cli(a->fd, "There are no registered applications\n"); 06411 AST_RWLIST_UNLOCK(&apps); 06412 return CLI_SUCCESS; 06413 } 06414 06415 /* core list applications like <keyword> */ 06416 if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) { 06417 like = 1; 06418 } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) { 06419 describing = 1; 06420 } 06421 06422 /* core list applications describing <keyword1> [<keyword2>] [...] */ 06423 if ((!like) && (!describing)) { 06424 ast_cli(a->fd, " -= Registered Asterisk Applications =-\n"); 06425 } else { 06426 ast_cli(a->fd, " -= Matching Asterisk Applications =-\n"); 06427 } 06428 06429 AST_RWLIST_TRAVERSE(&apps, aa, list) { 06430 int printapp = 0; 06431 total_apps++; 06432 if (like) { 06433 if (strcasestr(aa->name, a->argv[4])) { 06434 printapp = 1; 06435 total_match++; 06436 } 06437 } else if (describing) { 06438 if (aa->description) { 06439 /* Match all words on command line */ 06440 int i; 06441 printapp = 1; 06442 for (i = 4; i < a->argc; i++) { 06443 if (!strcasestr(aa->description, a->argv[i])) { 06444 printapp = 0; 06445 } else { 06446 total_match++; 06447 } 06448 } 06449 } 06450 } else { 06451 printapp = 1; 06452 } 06453 06454 if (printapp) { 06455 ast_cli(a->fd," %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>"); 06456 } 06457 } 06458 if ((!like) && (!describing)) { 06459 ast_cli(a->fd, " -= %d Applications Registered =-\n",total_apps); 06460 } else { 06461 ast_cli(a->fd, " -= %d Applications Matching =-\n",total_match); 06462 } 06463 06464 AST_RWLIST_UNLOCK(&apps); 06465 06466 return CLI_SUCCESS; 06467 }
| 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 7110 of file pbx.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_get_by_name(), ast_channel_unref, ast_cli(), ast_complete_channels(), ast_str_alloca, ast_str_buffer(), ast_str_strlen(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, pbx_builtin_serialize_variables(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
07111 { 07112 struct ast_channel *chan = NULL; 07113 struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */ 07114 07115 switch (cmd) { 07116 case CLI_INIT: 07117 e->command = "dialplan show chanvar"; 07118 e->usage = 07119 "Usage: dialplan show chanvar <channel>\n" 07120 " List current channel variables and their values\n"; 07121 return NULL; 07122 case CLI_GENERATE: 07123 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 07124 } 07125 07126 if (a->argc != e->args + 1) 07127 return CLI_SHOWUSAGE; 07128 07129 if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) { 07130 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]); 07131 return CLI_FAILURE; 07132 } 07133 07134 pbx_builtin_serialize_variables(chan, &vars); 07135 07136 if (ast_str_strlen(vars)) { 07137 ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars)); 07138 } 07139 07140 chan = ast_channel_unref(chan); 07141 07142 return CLI_SUCCESS; 07143 }
| static char* handle_show_dialplan | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 6730 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), dialplan_counters::context_existence, exten, dialplan_counters::extension_existence, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_dialplan_helper(), strsep(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_prio, ast_cli_entry::usage, and ast_cli_args::word.
06731 { 06732 char *exten = NULL, *context = NULL; 06733 /* Variables used for different counters */ 06734 struct dialplan_counters counters; 06735 const char *incstack[AST_PBX_MAX_STACK]; 06736 06737 switch (cmd) { 06738 case CLI_INIT: 06739 e->command = "dialplan show"; 06740 e->usage = 06741 "Usage: dialplan show [[exten@]context]\n" 06742 " Show dialplan\n"; 06743 return NULL; 06744 case CLI_GENERATE: 06745 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 06746 } 06747 06748 memset(&counters, 0, sizeof(counters)); 06749 06750 if (a->argc != 2 && a->argc != 3) 06751 return CLI_SHOWUSAGE; 06752 06753 /* we obtain [exten@]context? if yes, split them ... */ 06754 if (a->argc == 3) { 06755 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 06756 context = ast_strdupa(a->argv[2]); 06757 exten = strsep(&context, "@"); 06758 /* change empty strings to NULL */ 06759 if (ast_strlen_zero(exten)) 06760 exten = NULL; 06761 } else { /* no '@' char, only context given */ 06762 context = ast_strdupa(a->argv[2]); 06763 } 06764 if (ast_strlen_zero(context)) 06765 context = NULL; 06766 } 06767 /* else Show complete dial plan, context and exten are NULL */ 06768 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 06769 06770 /* check for input failure and throw some error messages */ 06771 if (context && !counters.context_existence) { 06772 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 06773 return CLI_FAILURE; 06774 } 06775 06776 if (exten && !counters.extension_existence) { 06777 if (context) 06778 ast_cli(a->fd, "There is no existence of %s@%s extension\n", 06779 exten, context); 06780 else 06781 ast_cli(a->fd, 06782 "There is no existence of '%s' extension in all contexts\n", 06783 exten); 06784 return CLI_FAILURE; 06785 } 06786 06787 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n", 06788 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 06789 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 06790 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 06791 06792 /* everything ok */ 06793 return CLI_SUCCESS; 06794 }
| static char* handle_show_function | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 3519 of file pbx.c.
References ast_custom_function::acflist, ast_cli_args::argc, ast_custom_function::arguments, ast_cli_args::argv, ast_cli(), ast_custom_function_find(), ast_free, ast_malloc, AST_MAX_APP, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_CYAN, COLOR_MAGENTA, ast_cli_entry::command, ast_custom_function::desc, ast_custom_function::docsrc, ast_cli_args::fd, ast_cli_args::n, ast_custom_function::name, S_OR, ast_custom_function::seealso, ast_custom_function::synopsis, synopsis, ast_custom_function::syntax, term_color(), ast_cli_entry::usage, and ast_cli_args::word.
03520 { 03521 struct ast_custom_function *acf; 03522 /* Maximum number of characters added by terminal coloring is 22 */ 03523 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40]; 03524 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL; 03525 char stxtitle[40], *syntax = NULL, *arguments = NULL; 03526 int syntax_size, description_size, synopsis_size, arguments_size, seealso_size; 03527 char *ret = NULL; 03528 int which = 0; 03529 int wordlen; 03530 03531 switch (cmd) { 03532 case CLI_INIT: 03533 e->command = "core show function"; 03534 e->usage = 03535 "Usage: core show function <function>\n" 03536 " Describe a particular dialplan function.\n"; 03537 return NULL; 03538 case CLI_GENERATE: 03539 wordlen = strlen(a->word); 03540 /* case-insensitive for convenience in this 'complete' function */ 03541 AST_RWLIST_RDLOCK(&acf_root); 03542 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03543 if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) { 03544 ret = ast_strdup(acf->name); 03545 break; 03546 } 03547 } 03548 AST_RWLIST_UNLOCK(&acf_root); 03549 03550 return ret; 03551 } 03552 03553 if (a->argc < 4) { 03554 return CLI_SHOWUSAGE; 03555 } 03556 03557 if (!(acf = ast_custom_function_find(a->argv[3]))) { 03558 ast_cli(a->fd, "No function by that name registered.\n"); 03559 return CLI_FAILURE; 03560 } 03561 03562 syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03563 if (!(syntax = ast_malloc(syntax_size))) { 03564 ast_cli(a->fd, "Memory allocation failure!\n"); 03565 return CLI_FAILURE; 03566 } 03567 03568 snprintf(info, sizeof(info), "\n -= Info about function '%s' =- \n\n", acf->name); 03569 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 03570 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03571 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03572 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 03573 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 03574 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 03575 term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 03576 #ifdef AST_XML_DOCS 03577 if (acf->docsrc == AST_XML_DOC) { 03578 arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1); 03579 synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1); 03580 description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1); 03581 seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1); 03582 } else 03583 #endif 03584 { 03585 synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03586 synopsis = ast_malloc(synopsis_size); 03587 03588 description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03589 description = ast_malloc(description_size); 03590 03591 arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03592 arguments = ast_malloc(arguments_size); 03593 03594 seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03595 seealso = ast_malloc(seealso_size); 03596 03597 /* check allocated memory. */ 03598 if (!synopsis || !description || !arguments || !seealso) { 03599 ast_free(synopsis); 03600 ast_free(description); 03601 ast_free(arguments); 03602 ast_free(seealso); 03603 ast_free(syntax); 03604 return CLI_FAILURE; 03605 } 03606 03607 term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 03608 term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 03609 term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size); 03610 term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 03611 } 03612 03613 ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 03614 infotitle, syntitle, synopsis, destitle, description, 03615 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 03616 03617 ast_free(arguments); 03618 ast_free(synopsis); 03619 ast_free(description); 03620 ast_free(seealso); 03621 ast_free(syntax); 03622 03623 return CLI_SUCCESS; 03624 }
| static char* handle_show_functions | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 3477 of file pbx.c.
References ast_custom_function::acflist, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_custom_function::name, S_OR, ast_custom_function::synopsis, ast_custom_function::syntax, and ast_cli_entry::usage.
03478 { 03479 struct ast_custom_function *acf; 03480 int count_acf = 0; 03481 int like = 0; 03482 03483 switch (cmd) { 03484 case CLI_INIT: 03485 e->command = "core show functions [like]"; 03486 e->usage = 03487 "Usage: core show functions [like <text>]\n" 03488 " List builtin functions, optionally only those matching a given string\n"; 03489 return NULL; 03490 case CLI_GENERATE: 03491 return NULL; 03492 } 03493 03494 if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) { 03495 like = 1; 03496 } else if (a->argc != 3) { 03497 return CLI_SHOWUSAGE; 03498 } 03499 03500 ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 03501 03502 AST_RWLIST_RDLOCK(&acf_root); 03503 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03504 if (!like || strstr(acf->name, a->argv[4])) { 03505 count_acf++; 03506 ast_cli(a->fd, "%-20.20s %-35.35s %s\n", 03507 S_OR(acf->name, ""), 03508 S_OR(acf->syntax, ""), 03509 S_OR(acf->synopsis, "")); 03510 } 03511 } 03512 AST_RWLIST_UNLOCK(&acf_root); 03513 03514 ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 03515 03516 return CLI_SUCCESS; 03517 }
| 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 7052 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_var_t::entries, ast_cli_args::fd, globals, globalslock, and ast_cli_entry::usage.
07053 { 07054 int i = 0; 07055 struct ast_var_t *newvariable; 07056 07057 switch (cmd) { 07058 case CLI_INIT: 07059 e->command = "dialplan show globals"; 07060 e->usage = 07061 "Usage: dialplan show globals\n" 07062 " List current global dialplan variables and their values\n"; 07063 return NULL; 07064 case CLI_GENERATE: 07065 return NULL; 07066 } 07067 07068 ast_rwlock_rdlock(&globalslock); 07069 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 07070 i++; 07071 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 07072 } 07073 ast_rwlock_unlock(&globalslock); 07074 ast_cli(a->fd, "\n -- %d variable(s)\n", i); 07075 07076 return CLI_SUCCESS; 07077 }
| 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 6298 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_core_show_hint(), ast_hint::exten, ast_cli_args::fd, hints, ast_hint::laststate, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
06299 { 06300 struct ast_hint *hint; 06301 int watchers; 06302 int num = 0, extenlen; 06303 struct ao2_iterator i; 06304 06305 switch (cmd) { 06306 case CLI_INIT: 06307 e->command = "core show hint"; 06308 e->usage = 06309 "Usage: core show hint <exten>\n" 06310 " List registered hint\n"; 06311 return NULL; 06312 case CLI_GENERATE: 06313 return complete_core_show_hint(a->line, a->word, a->pos, a->n); 06314 } 06315 06316 if (a->argc < 4) 06317 return CLI_SHOWUSAGE; 06318 06319 if (ao2_container_count(hints) == 0) { 06320 ast_cli(a->fd, "There are no registered dialplan hints\n"); 06321 return CLI_SUCCESS; 06322 } 06323 06324 extenlen = strlen(a->argv[3]); 06325 i = ao2_iterator_init(hints, 0); 06326 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06327 ao2_lock(hint); 06328 if (!hint->exten) { 06329 /* The extension has already been destroyed */ 06330 ao2_unlock(hint); 06331 continue; 06332 } 06333 if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) { 06334 watchers = ao2_container_count(hint->callbacks); 06335 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 06336 ast_get_extension_name(hint->exten), 06337 ast_get_context_name(ast_get_extension_context(hint->exten)), 06338 ast_get_extension_app(hint->exten), 06339 ast_extension_state2str(hint->laststate), watchers); 06340 num++; 06341 } 06342 ao2_unlock(hint); 06343 } 06344 ao2_iterator_destroy(&i); 06345 if (!num) 06346 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]); 06347 else 06348 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]); 06349 return CLI_SUCCESS; 06350 }
| 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 6212 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_hint::exten, ast_cli_args::fd, hints, ast_hint::laststate, and ast_cli_entry::usage.
06213 { 06214 struct ast_hint *hint; 06215 int num = 0; 06216 int watchers; 06217 struct ao2_iterator i; 06218 06219 switch (cmd) { 06220 case CLI_INIT: 06221 e->command = "core show hints"; 06222 e->usage = 06223 "Usage: core show hints\n" 06224 " List registered hints\n"; 06225 return NULL; 06226 case CLI_GENERATE: 06227 return NULL; 06228 } 06229 06230 if (ao2_container_count(hints) == 0) { 06231 ast_cli(a->fd, "There are no registered dialplan hints\n"); 06232 return CLI_SUCCESS; 06233 } 06234 /* ... we have hints ... */ 06235 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 06236 06237 i = ao2_iterator_init(hints, 0); 06238 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 06239 ao2_lock(hint); 06240 if (!hint->exten) { 06241 /* The extension has already been destroyed */ 06242 ao2_unlock(hint); 06243 continue; 06244 } 06245 watchers = ao2_container_count(hint->callbacks); 06246 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 06247 ast_get_extension_name(hint->exten), 06248 ast_get_context_name(ast_get_extension_context(hint->exten)), 06249 ast_get_extension_app(hint->exten), 06250 ast_extension_state2str(hint->laststate), watchers); 06251 ao2_unlock(hint); 06252 num++; 06253 } 06254 ao2_iterator_destroy(&i); 06255 06256 ast_cli(a->fd, "----------------\n"); 06257 ast_cli(a->fd, "- %d hints registered\n", num); 06258 return CLI_SUCCESS; 06259 }
| 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 6354 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.
06355 { 06356 struct ast_switch *sw; 06357 06358 switch (cmd) { 06359 case CLI_INIT: 06360 e->command = "core show switches"; 06361 e->usage = 06362 "Usage: core show switches\n" 06363 " List registered switches\n"; 06364 return NULL; 06365 case CLI_GENERATE: 06366 return NULL; 06367 } 06368 06369 AST_RWLIST_RDLOCK(&switches); 06370 06371 if (AST_RWLIST_EMPTY(&switches)) { 06372 AST_RWLIST_UNLOCK(&switches); 06373 ast_cli(a->fd, "There are no registered alternative switches\n"); 06374 return CLI_SUCCESS; 06375 } 06376 06377 ast_cli(a->fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 06378 AST_RWLIST_TRAVERSE(&switches, sw, list) 06379 ast_cli(a->fd, "%s: %s\n", sw->name, sw->description); 06380 06381 AST_RWLIST_UNLOCK(&switches); 06382 06383 return CLI_SUCCESS; 06384 }
| static int handle_statechange | ( | void * | datap | ) | [static] |
Definition at line 4541 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_t_callback, ao2_t_ref, ao2_unlock, ast_copy_string(), ast_extension_state3(), ast_free, ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_str_create(), ast_str_set(), ast_hint::callbacks, ast_state_cb::change_cb, context_merge_lock, ast_state_cb::data, statechange::dev, ast_hint::exten, ast_hintdevice::hint, ast_hintdevice::hintdevice, hintdevice_cmp_multiple(), ast_hint::laststate, OBJ_MULTIPLE, OBJ_POINTER, and statecbs.
04542 { 04543 struct ast_hint *hint; 04544 struct ast_str *hint_app; 04545 struct ast_hintdevice *device; 04546 struct ast_hintdevice *cmpdevice; 04547 struct statechange *sc = datap; 04548 struct ao2_iterator *dev_iter; 04549 struct ao2_iterator cb_iter; 04550 char context_name[AST_MAX_CONTEXT]; 04551 char exten_name[AST_MAX_EXTENSION]; 04552 04553 if (ao2_container_count(hintdevices) == 0) { 04554 /* There are no hints monitoring devices. */ 04555 ast_free(sc); 04556 return 0; 04557 } 04558 04559 hint_app = ast_str_create(1024); 04560 if (!hint_app) { 04561 ast_free(sc); 04562 return -1; 04563 } 04564 04565 cmpdevice = alloca(sizeof(*cmpdevice) + strlen(sc->dev)); 04566 strcpy(cmpdevice->hintdevice, sc->dev); 04567 04568 ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */ 04569 dev_iter = ao2_t_callback(hintdevices, 04570 OBJ_POINTER | OBJ_MULTIPLE, 04571 hintdevice_cmp_multiple, 04572 cmpdevice, 04573 "find devices in container"); 04574 if (!dev_iter) { 04575 ast_mutex_unlock(&context_merge_lock); 04576 ast_free(hint_app); 04577 ast_free(sc); 04578 return -1; 04579 } 04580 04581 for (; (device = ao2_iterator_next(dev_iter)); ao2_t_ref(device, -1, "Next device")) { 04582 struct ast_state_cb *state_cb; 04583 int state; 04584 04585 if (!device->hint) { 04586 /* Should never happen. */ 04587 continue; 04588 } 04589 hint = device->hint; 04590 04591 ao2_lock(hint); 04592 if (!hint->exten) { 04593 /* The extension has already been destroyed */ 04594 ao2_unlock(hint); 04595 continue; 04596 } 04597 04598 /* 04599 * Save off strings in case the hint extension gets destroyed 04600 * while we are notifying the watchers. 04601 */ 04602 ast_copy_string(context_name, 04603 ast_get_context_name(ast_get_extension_context(hint->exten)), 04604 sizeof(context_name)); 04605 ast_copy_string(exten_name, ast_get_extension_name(hint->exten), 04606 sizeof(exten_name)); 04607 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten)); 04608 ao2_unlock(hint); 04609 04610 /* 04611 * Get device state for this hint. 04612 * 04613 * NOTE: We cannot hold any locks while determining the hint 04614 * device state or notifying the watchers without causing a 04615 * deadlock. (conlock, hints, and hint) 04616 */ 04617 state = ast_extension_state3(hint_app); 04618 if (state == hint->laststate) { 04619 continue; 04620 } 04621 04622 /* Device state changed since last check - notify the watchers. */ 04623 hint->laststate = state; /* record we saw the change */ 04624 04625 /* For general callbacks */ 04626 cb_iter = ao2_iterator_init(statecbs, 0); 04627 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) { 04628 state_cb->change_cb(context_name, exten_name, state, state_cb->data); 04629 } 04630 ao2_iterator_destroy(&cb_iter); 04631 04632 /* For extension callbacks */ 04633 cb_iter = ao2_iterator_init(hint->callbacks, 0); 04634 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) { 04635 state_cb->change_cb(context_name, exten_name, state, state_cb->data); 04636 } 04637 ao2_iterator_destroy(&cb_iter); 04638 } 04639 ast_mutex_unlock(&context_merge_lock); 04640 04641 ao2_iterator_destroy(dev_iter); 04642 ast_free(hint_app); 04643 ast_free(sc); 04644 return 0; 04645 }
| static char* handle_unset_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 7232 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.
07233 { 07234 int oldval = 0; 07235 07236 switch (cmd) { 07237 case CLI_INIT: 07238 e->command = "dialplan set extenpatternmatchnew false"; 07239 e->usage = 07240 "Usage: dialplan set extenpatternmatchnew true|false\n" 07241 " Use the NEW extension pattern matching algorithm, true or false.\n"; 07242 return NULL; 07243 case CLI_GENERATE: 07244 return NULL; 07245 } 07246 07247 if (a->argc != 4) 07248 return CLI_SHOWUSAGE; 07249 07250 oldval = pbx_set_extenpatternmatchnew(0); 07251 07252 if (!oldval) 07253 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n"); 07254 else 07255 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n"); 07256 07257 return CLI_SUCCESS; 07258 }
| 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 1215 of file pbx.c.
References ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
01216 { 01217 const struct ast_exten *ac = ah_a; 01218 const struct ast_exten *bc = ah_b; 01219 return ac->priority != bc->priority; 01220 }
| static int hashtab_compare_extens | ( | const void * | ha_a, | |
| const void * | ah_b | |||
| ) | [static] |
Definition at line 1196 of file pbx.c.
References ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
01197 { 01198 const struct ast_exten *ac = ah_a; 01199 const struct ast_exten *bc = ah_b; 01200 int x = strcmp(ac->exten, bc->exten); 01201 if (x) { /* if exten names are diff, then return */ 01202 return x; 01203 } 01204 01205 /* but if they are the same, do the cidmatch values match? */ 01206 if (ac->matchcid && bc->matchcid) { 01207 return strcmp(ac->cidmatch,bc->cidmatch); 01208 } else if (!ac->matchcid && !bc->matchcid) { 01209 return 0; /* if there's no matchcid on either side, then this is a match */ 01210 } else { 01211 return 1; /* if there's matchcid on one but not the other, they are different */ 01212 } 01213 }
| static unsigned int hashtab_hash_extens | ( | const void * | obj | ) | [static] |
Definition at line 1235 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().
01236 { 01237 const struct ast_exten *ac = obj; 01238 unsigned int x = ast_hashtab_hash_string(ac->exten); 01239 unsigned int y = 0; 01240 if (ac->matchcid) 01241 y = ast_hashtab_hash_string(ac->cidmatch); 01242 return x+y; 01243 }
| static unsigned int hashtab_hash_labels | ( | const void * | obj | ) | [static] |
Definition at line 1251 of file pbx.c.
References ast_hashtab_hash_string(), ast_exten::label, and S_OR.
Referenced by ast_add_extension2_lockopt().
01252 { 01253 const struct ast_exten *ac = obj; 01254 return ast_hashtab_hash_string(S_OR(ac->label, "")); 01255 }
| static unsigned int hashtab_hash_priority | ( | const void * | obj | ) | [static] |
Definition at line 1245 of file pbx.c.
References ast_hashtab_hash_int(), and ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
01246 { 01247 const struct ast_exten *ac = obj; 01248 return ast_hashtab_hash_int(ac->priority); 01249 }
| static int hint_cmp | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
| static int hint_hash | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 10797 of file pbx.c.
References ast_get_extension_name(), ast_str_case_hash(), ast_strlen_zero(), ast_hint::exten, and ast_hint::exten_name.
Referenced by ast_pbx_init().
10798 { 10799 const struct ast_hint *hint = obj; 10800 const char *exten_name; 10801 int res; 10802 10803 exten_name = ast_get_extension_name(hint->exten); 10804 if (ast_strlen_zero(exten_name)) { 10805 /* 10806 * If the exten or extension name isn't set, return 0 so that 10807 * the ao2_find() search will start in the first bucket. 10808 */ 10809 res = 0; 10810 } else { 10811 res = ast_str_case_hash(exten_name); 10812 } 10813 10814 return res; 10815 }
| static int hint_id_cmp | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 4808 of file pbx.c.
References CMP_MATCH, CMP_STOP, and ast_state_cb::id.
Referenced by ast_add_hint().
04809 { 04810 const struct ast_state_cb *cb = obj; 04811 int *id = arg; 04812 04813 return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0; 04814 }
| static int hintdevice_cmp_multiple | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 999 of file pbx.c.
References CMP_MATCH, ext, and ast_hintdevice::hintdevice.
Referenced by ast_pbx_init(), and handle_statechange().
01000 { 01001 struct ast_hintdevice *ext = obj, *ext2 = arg; 01002 01003 return !strcasecmp(ext->hintdevice, ext2->hintdevice) ? CMP_MATCH : 0; 01004 }
| static void hintdevice_destroy | ( | void * | obj | ) | [static] |
Definition at line 1035 of file pbx.c.
References ao2_ref, and ast_hintdevice::hint.
Referenced by add_hintdevice().
01036 { 01037 struct ast_hintdevice *doomed = obj; 01038 01039 if (doomed->hint) { 01040 ao2_ref(doomed->hint, -1); 01041 doomed->hint = NULL; 01042 } 01043 }
| static int hintdevice_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 988 of file pbx.c.
References ast_str_case_hash(), ext, and ast_hintdevice::hintdevice.
Referenced by ast_pbx_init().
00989 { 00990 const struct ast_hintdevice *ext = obj; 00991 00992 return ast_str_case_hash(ext->hintdevice); 00993 }
| static int hintdevice_remove_cb | ( | void * | deviceobj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1010 of file pbx.c.
References CMP_MATCH, and ast_hintdevice::hint.
Referenced by remove_hintdevice().
01011 { 01012 struct ast_hintdevice *device = deviceobj; 01013 struct ast_hint *hint = arg; 01014 01015 return (device->hint == hint) ? CMP_MATCH : 0; 01016 }
| static int hints_data_provider_get | ( | const struct ast_data_search * | search, | |
| struct ast_data * | data_root | |||
| ) | [static] |
Definition at line 10397 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_data_add_int(), ast_data_add_node(), ast_data_add_str(), ast_data_remove_node(), ast_data_search_match(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, ast_hint::exten, hints, and ast_hint::laststate.
10399 { 10400 struct ast_data *data_hint; 10401 struct ast_hint *hint; 10402 int watchers; 10403 struct ao2_iterator i; 10404 10405 if (ao2_container_count(hints) == 0) { 10406 return 0; 10407 } 10408 10409 i = ao2_iterator_init(hints, 0); 10410 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 10411 watchers = ao2_container_count(hint->callbacks); 10412 data_hint = ast_data_add_node(data_root, "hint"); 10413 if (!data_hint) { 10414 continue; 10415 } 10416 ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten)); 10417 ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten))); 10418 ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten)); 10419 ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate)); 10420 ast_data_add_int(data_hint, "watchers", watchers); 10421 10422 if (!ast_data_search_match(search, data_hint)) { 10423 ast_data_remove_node(data_root, data_hint); 10424 } 10425 } 10426 ao2_iterator_destroy(&i); 10427 10428 return 0; 10429 }
| static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 1595 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
Referenced by pbx_find_extension().
01596 { 01597 if (!i->hastime) 01598 return 1; 01599 01600 return ast_check_timing(&(i->timing)); 01601 }
| 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 5405 of file pbx.c.
References ast_channel_name(), ast_log(), ast_mutex_lock, ast_mutex_unlock, countcalls, getloadavg(), LOG_WARNING, maxcalllock, option_maxcalls, option_maxload, and totalcalls.
Referenced by ast_pbx_run_args(), and ast_pbx_start().
05406 { 05407 int failed = 0; 05408 double curloadavg; 05409 #if defined(HAVE_SYSINFO) 05410 long curfreemem; 05411 struct sysinfo sys_info; 05412 #endif 05413 05414 ast_mutex_lock(&maxcalllock); 05415 if (option_maxcalls) { 05416 if (countcalls >= option_maxcalls) { 05417 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, ast_channel_name(c)); 05418 failed = -1; 05419 } 05420 } 05421 if (option_maxload) { 05422 getloadavg(&curloadavg, 1); 05423 if (curloadavg >= option_maxload) { 05424 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, ast_channel_name(c), curloadavg); 05425 failed = -1; 05426 } 05427 } 05428 #if defined(HAVE_SYSINFO) 05429 if (option_minmemfree) { 05430 if (!sysinfo(&sys_info)) { 05431 /* make sure that the free system memory is above the configured low watermark 05432 * convert the amount of freeram from mem_units to MB */ 05433 curfreemem = sys_info.freeram * sys_info.mem_unit; 05434 curfreemem /= 1024 * 1024; 05435 if (curfreemem < option_minmemfree) { 05436 ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree); 05437 failed = -1; 05438 } 05439 } 05440 } 05441 #endif 05442 05443 if (!failed) { 05444 countcalls++; 05445 totalcalls++; 05446 } 05447 ast_mutex_unlock(&maxcalllock); 05448 05449 return failed; 05450 }
| static void insert_in_next_chars_alt_char_list | ( | struct match_char ** | parent_ptr, | |
| struct match_char * | node | |||
| ) | [static] |
Definition at line 2012 of file pbx.c.
References match_char::alt_char, and match_char::specificity.
Referenced by add_pattern_node().
02013 { 02014 struct match_char *curr, *lcurr; 02015 02016 /* insert node into the tree at "current", so the alt_char list from current is 02017 sorted in increasing value as you go to the leaves */ 02018 if (!(*parent_ptr)) { 02019 *parent_ptr = node; 02020 return; 02021 } 02022 02023 if ((*parent_ptr)->specificity > node->specificity) { 02024 /* insert at head */ 02025 node->alt_char = (*parent_ptr); 02026 *parent_ptr = node; 02027 return; 02028 } 02029 02030 lcurr = *parent_ptr; 02031 for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) { 02032 if (curr->specificity > node->specificity) { 02033 node->alt_char = curr; 02034 lcurr->alt_char = node; 02035 break; 02036 } 02037 lcurr = curr; 02038 } 02039 02040 if (!curr) { 02041 lcurr->alt_char = node; 02042 } 02043 02044 }
| int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 10440 of file pbx.c.
References __ast_custom_function_register(), ARRAY_LEN, ast_cli_register_multiple(), ast_data_register_multiple_core, AST_EVENT_DEVICE_STATE, AST_EVENT_IE_END, ast_event_subscribe(), ast_log(), ast_manager_register_xml, ast_register_application2(), ast_taskprocessor_get(), ast_verb, builtins, device_state_cb(), device_state_sub, EVENT_FLAG_CONFIG, EVENT_FLAG_REPORTING, exception_function, LOG_ERROR, LOG_WARNING, manager_show_dialplan(), pbx_cli, pbx_data_providers, and testtime_function.
Referenced by main().
10441 { 10442 int x; 10443 10444 /* Initialize the PBX */ 10445 ast_verb(1, "Asterisk PBX Core Initializing\n"); 10446 if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) { 10447 ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n"); 10448 } 10449 10450 ast_verb(1, "Registering builtin applications:\n"); 10451 ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli)); 10452 ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers)); 10453 __ast_custom_function_register(&exception_function, NULL); 10454 __ast_custom_function_register(&testtime_function, NULL); 10455 10456 /* Register builtin applications */ 10457 for (x = 0; x < ARRAY_LEN(builtins); x++) { 10458 ast_verb(1, "[%s]\n", builtins[x].name); 10459 if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) { 10460 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 10461 return -1; 10462 } 10463 } 10464 10465 /* Register manager application */ 10466 ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan); 10467 10468 if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL, 10469 AST_EVENT_IE_END))) { 10470 return -1; 10471 } 10472 10473 return 0; 10474 }
| static int lookup_name | ( | const char * | s, | |
| const char *const | names[], | |||
| int | max | |||
| ) | [static] |
Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values.
Definition at line 7740 of file pbx.c.
Referenced by get_range().
07741 { 07742 int i; 07743 07744 if (names && *s > '9') { 07745 for (i = 0; names[i]; i++) { 07746 if (!strcasecmp(s, names[i])) { 07747 return i; 07748 } 07749 } 07750 } 07751 07752 /* Allow months and weekdays to be specified as numbers, as well */ 07753 if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) { 07754 /* What the array offset would have been: "1" would be at offset 0 */ 07755 return i - 1; 07756 } 07757 return -1; /* error return */ 07758 }
| static void manager_dpsendack | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Send ack once.
Definition at line 6853 of file pbx.c.
References astman_send_listack().
Referenced by manager_show_dialplan_helper().
06854 { 06855 astman_send_listack(s, m, "DialPlan list will follow", "start"); 06856 }
| static int manager_show_dialplan | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Manager listing of dial plan.
Definition at line 6999 of file pbx.c.
References ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), dialplan_counters::context_existence, exten, dialplan_counters::extension_existence, manager_show_dialplan_helper(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.
Referenced by load_pbx().
07000 { 07001 const char *exten, *context; 07002 const char *id = astman_get_header(m, "ActionID"); 07003 char idtext[256]; 07004 07005 /* Variables used for different counters */ 07006 struct dialplan_counters counters; 07007 07008 if (!ast_strlen_zero(id)) 07009 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 07010 else 07011 idtext[0] = '\0'; 07012 07013 memset(&counters, 0, sizeof(counters)); 07014 07015 exten = astman_get_header(m, "Extension"); 07016 context = astman_get_header(m, "Context"); 07017 07018 manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL); 07019 07020 if (context && !counters.context_existence) { 07021 char errorbuf[BUFSIZ]; 07022 07023 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context); 07024 astman_send_error(s, m, errorbuf); 07025 return 0; 07026 } 07027 if (exten && !counters.extension_existence) { 07028 char errorbuf[BUFSIZ]; 07029 07030 if (context) 07031 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context); 07032 else 07033 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten); 07034 astman_send_error(s, m, errorbuf); 07035 return 0; 07036 } 07037 07038 astman_append(s, "Event: ShowDialPlanComplete\r\n" 07039 "EventList: Complete\r\n" 07040 "ListItems: %d\r\n" 07041 "ListExtensions: %d\r\n" 07042 "ListPriorities: %d\r\n" 07043 "ListContexts: %d\r\n" 07044 "%s" 07045 "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext); 07046 07047 /* everything ok */ 07048 return 0; 07049 }
| 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 6862 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().
06866 { 06867 struct ast_context *c; 06868 int res = 0, old_total_exten = dpc->total_exten; 06869 06870 if (ast_strlen_zero(exten)) 06871 exten = NULL; 06872 if (ast_strlen_zero(context)) 06873 context = NULL; 06874 06875 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten); 06876 06877 /* try to lock contexts */ 06878 if (ast_rdlock_contexts()) { 06879 astman_send_error(s, m, "Failed to lock contexts"); 06880 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n"); 06881 return -1; 06882 } 06883 06884 c = NULL; /* walk all contexts ... */ 06885 while ( (c = ast_walk_contexts(c)) ) { 06886 struct ast_exten *e; 06887 struct ast_include *i; 06888 struct ast_ignorepat *ip; 06889 06890 if (context && strcmp(ast_get_context_name(c), context) != 0) 06891 continue; /* not the name we want */ 06892 06893 dpc->context_existence = 1; 06894 06895 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c)); 06896 06897 if (ast_rdlock_context(c)) { /* failed to lock */ 06898 ast_debug(3, "manager_show_dialplan: Failed to lock context\n"); 06899 continue; 06900 } 06901 06902 /* XXX note- an empty context is not printed */ 06903 e = NULL; /* walk extensions in context */ 06904 while ( (e = ast_walk_context_extensions(c, e)) ) { 06905 struct ast_exten *p; 06906 06907 /* looking for extension? is this our extension? */ 06908 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) { 06909 /* not the one we are looking for, continue */ 06910 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e)); 06911 continue; 06912 } 06913 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e)); 06914 06915 dpc->extension_existence = 1; 06916 06917 /* may we print context info? */ 06918 dpc->total_context++; 06919 dpc->total_exten++; 06920 06921 p = NULL; /* walk next extension peers */ 06922 while ( (p = ast_walk_extension_priorities(e, p)) ) { 06923 int prio = ast_get_extension_priority(p); 06924 06925 dpc->total_prio++; 06926 if (!dpc->total_items++) 06927 manager_dpsendack(s, m); 06928 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06929 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) ); 06930 06931 /* XXX maybe make this conditional, if p != e ? */ 06932 if (ast_get_extension_label(p)) 06933 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p)); 06934 06935 if (prio == PRIORITY_HINT) { 06936 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p)); 06937 } else { 06938 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)); 06939 } 06940 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e)); 06941 } 06942 } 06943 06944 i = NULL; /* walk included and write info ... */ 06945 while ( (i = ast_walk_context_includes(c, i)) ) { 06946 if (exten) { 06947 /* Check all includes for the requested extension */ 06948 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i); 06949 } else { 06950 if (!dpc->total_items++) 06951 manager_dpsendack(s, m); 06952 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06953 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)); 06954 astman_append(s, "\r\n"); 06955 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i)); 06956 } 06957 } 06958 06959 ip = NULL; /* walk ignore patterns and write info ... */ 06960 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 06961 const char *ipname = ast_get_ignorepat_name(ip); 06962 char ignorepat[AST_MAX_EXTENSION]; 06963 06964 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 06965 if (!exten || ast_extension_match(ignorepat, exten)) { 06966 if (!dpc->total_items++) 06967 manager_dpsendack(s, m); 06968 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06969 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip)); 06970 astman_append(s, "\r\n"); 06971 } 06972 } 06973 if (!rinclude) { 06974 struct ast_sw *sw = NULL; 06975 while ( (sw = ast_walk_context_switches(c, sw)) ) { 06976 if (!dpc->total_items++) 06977 manager_dpsendack(s, m); 06978 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06979 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)); 06980 astman_append(s, "\r\n"); 06981 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw)); 06982 } 06983 } 06984 06985 ast_unlock_context(c); 06986 } 06987 ast_unlock_contexts(); 06988 06989 if (dpc->total_exten == old_total_exten) { 06990 ast_debug(3, "manager_show_dialplan: Found nothing new\n"); 06991 /* Nothing new under the sun */ 06992 return -1; 06993 } else { 06994 return res; 06995 } 06996 }
| static int matchcid | ( | const char * | cidpattern, | |
| const char * | callerid | |||
| ) | [static] |
Definition at line 2807 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
02808 { 02809 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 02810 failing to get a number should count as a match, otherwise not */ 02811 02812 if (ast_strlen_zero(callerid)) { 02813 return ast_strlen_zero(cidpattern) ? 1 : 0; 02814 } 02815 02816 return ast_extension_match(cidpattern, callerid); 02817 }
| 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 1836 of file pbx.c.
References match_char::alt_char, ast_debug, ast_log(), scoreboard::canmatch, match_char::deleted, E_CANMATCH, E_MATCHMORE, ast_exten::exten, scoreboard::exten, match_char::exten, match_char::is_pattern, ast_exten::label, LOG_NOTICE, NEW_MATCHER_CHK_MATCH, NEW_MATCHER_RECURSE, match_char::next_char, match_char::specificity, update_scoreboard(), and match_char::x.
Referenced by pbx_find_extension().
01837 { 01838 struct match_char *p; /* note minimal stack storage requirements */ 01839 struct ast_exten pattern = { .label = label }; 01840 #ifdef DEBUG_THIS 01841 if (tree) 01842 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action)); 01843 else 01844 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action)); 01845 #endif 01846 for (p = tree; p; p = p->alt_char) { 01847 if (p->is_pattern) { 01848 if (p->x[0] == 'N') { 01849 if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) { 01850 #define NEW_MATCHER_CHK_MATCH \ 01851 if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */ \ 01852 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \ 01853 update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \ 01854 if (!p->deleted) { \ 01855 if (action == E_FINDLABEL) { \ 01856 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \ 01857 ast_debug(4, "Found label in preferred extension\n"); \ 01858 return; \ 01859 } \ 01860 } else { \ 01861 ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten); \ 01862 return; /* the first match, by definition, will be the best, because of the sorted tree */ \ 01863 } \ 01864 } \ 01865 } \ 01866 } 01867 01868 #define NEW_MATCHER_RECURSE \ 01869 if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \ 01870 || p->next_char->x[0] == '!')) { \ 01871 if (*(str + 1) || p->next_char->x[0] == '!') { \ 01872 new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01873 if (score->exten) { \ 01874 ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten); \ 01875 return; /* the first match is all we need */ \ 01876 } \ 01877 } else { \ 01878 new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01879 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \ 01880 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \ 01881 "NULL"); \ 01882 return; /* the first match is all we need */ \ 01883 } \ 01884 } \ 01885 } else if ((p->next_char || action == E_CANMATCH) && !*(str + 1)) { \ 01886 score->canmatch = 1; \ 01887 score->canmatch_exten = get_canmatch_exten(p); \ 01888 if (action == E_CANMATCH || action == E_MATCHMORE) { \ 01889 ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \ 01890 return; \ 01891 } \ 01892 } 01893 01894 NEW_MATCHER_CHK_MATCH; 01895 NEW_MATCHER_RECURSE; 01896 } 01897 } else if (p->x[0] == 'Z') { 01898 if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) { 01899 NEW_MATCHER_CHK_MATCH; 01900 NEW_MATCHER_RECURSE; 01901 } 01902 } else if (p->x[0] == 'X') { 01903 if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) { 01904 NEW_MATCHER_CHK_MATCH; 01905 NEW_MATCHER_RECURSE; 01906 } 01907 } else if (p->x[0] == '.' && p->x[1] == 0) { 01908 /* how many chars will the . match against? */ 01909 int i = 0; 01910 const char *str2 = str; 01911 while (*str2 && *str2 != '/') { 01912 str2++; 01913 i++; 01914 } 01915 if (p->exten && *str2 != '/') { 01916 update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p); 01917 if (score->exten) { 01918 ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten); 01919 return; /* the first match is all we need */ 01920 } 01921 } 01922 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01923 new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action); 01924 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01925 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL"); 01926 return; /* the first match is all we need */ 01927 } 01928 } 01929 } else if (p->x[0] == '!' && p->x[1] == 0) { 01930 /* how many chars will the . match against? */ 01931 int i = 1; 01932 const char *str2 = str; 01933 while (*str2 && *str2 != '/') { 01934 str2++; 01935 i++; 01936 } 01937 if (p->exten && *str2 != '/') { 01938 update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p); 01939 if (score->exten) { 01940 ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten); 01941 return; /* the first match is all we need */ 01942 } 01943 } 01944 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01945 new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action); 01946 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01947 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01948 return; /* the first match is all we need */ 01949 } 01950 } 01951 } else if (p->x[0] == '/' && p->x[1] == 0) { 01952 /* the pattern in the tree includes the cid match! */ 01953 if (p->next_char && callerid && *callerid) { 01954 new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action); 01955 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01956 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01957 return; /* the first match is all we need */ 01958 } 01959 } 01960 } else if (strchr(p->x, *str)) { 01961 ast_debug(4, "Nothing strange about this match\n"); 01962 NEW_MATCHER_CHK_MATCH; 01963 NEW_MATCHER_RECURSE; 01964 } 01965 } else if (strchr(p->x, *str)) { 01966 ast_debug(4, "Nothing strange about this match\n"); 01967 NEW_MATCHER_CHK_MATCH; 01968 NEW_MATCHER_RECURSE; 01969 } 01970 } 01971 ast_debug(4, "return at end of func\n"); 01972 }
| static int parse_variable_name | ( | char * | var, | |
| int * | offset, | |||
| int * | length, | |||
| int * | isfunc | |||
| ) | [static] |
extract offset:length from variable name.
Definition at line 3117 of file pbx.c.
Referenced by ast_str_retrieve_variable(), ast_str_substitute_variables_full(), and pbx_substitute_variables_helper_full().
03118 { 03119 int parens = 0; 03120 03121 *offset = 0; 03122 *length = INT_MAX; 03123 *isfunc = 0; 03124 for (; *var; var++) { 03125 if (*var == '(') { 03126 (*isfunc)++; 03127 parens++; 03128 } else if (*var == ')') { 03129 parens--; 03130 } else if (*var == ':' && parens == 0) { 03131 *var++ = '\0'; 03132 sscanf(var, "%30d:%30d", offset, length); 03133 return 1; /* offset:length valid */ 03134 } 03135 } 03136 return 0; 03137 }
| void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 10273 of file pbx.c.
References AST_LIST_REMOVE_HEAD, ast_rwlock_unlock, ast_rwlock_wrlock, ast_var_delete(), ast_var_t::entries, globals, and globalslock.
Referenced by handle_cli_dialplan_reload(), and reload().
10274 { 10275 struct ast_var_t *vardata; 10276 10277 ast_rwlock_wrlock(&globalslock); 10278 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 10279 ast_var_delete(vardata); 10280 ast_rwlock_unlock(&globalslock); 10281 }
| const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
| const char * | name | |||
| ) |
Return a pointer to the value of the corresponding channel variable.
This function will return a pointer to the buffer inside the channel variable. This value should only be accessed with the channel locked. If the value needs to be kept around, it should be done by using the following thread-safe code:
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 10035 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_rwlock_rdlock, ast_rwlock_unlock, ast_var_name(), ast_var_value(), globals, globalslock, and ast_channel::varshead.
Referenced by __ast_pbx_run(), _macro_exec(), _while_exec(), agentmonitoroutgoing_exec(), analog_call(), append_channel_vars(), array(), ast_bridge_call(), ast_bridge_timelimit(), ast_call_forward(), ast_channel_connected_line_macro(), ast_channel_redirecting_macro(), ast_eivr_getvariable(), ast_hangup(), ast_monitor_stop(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_run(), create_dynamic_parkinglot(), crement_function_read(), dahdi_hangup(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_check(), feature_interpret(), find_by_mark(), find_conf_realtime(), findparkinglotname(), func_channel_read(), generic_fax_exec(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), manager_mixmonitor(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), park_space_reserve(), pbx_builtin_background(), pbx_builtin_gotoiftime(), queue_exec(), real_ctx(), receivefax_exec(), retrydial_exec(), ring_entry(), run_agi(), sendfax_exec(), set_config_flags(), set_local_info(), setsubstate(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridge_vars(), and wait_for_answer().
10036 { 10037 struct ast_var_t *variables; 10038 const char *ret = NULL; 10039 int i; 10040 struct varshead *places[2] = { NULL, &globals }; 10041 10042 if (!name) 10043 return NULL; 10044 10045 if (chan) { 10046 ast_channel_lock(chan); 10047 places[0] = &chan->varshead; 10048 } 10049 10050 for (i = 0; i < 2; i++) { 10051 if (!places[i]) 10052 continue; 10053 if (places[i] == &globals) 10054 ast_rwlock_rdlock(&globalslock); 10055 AST_LIST_TRAVERSE(places[i], variables, entries) { 10056 if (!strcmp(name, ast_var_name(variables))) { 10057 ret = ast_var_value(variables); 10058 break; 10059 } 10060 } 10061 if (places[i] == &globals) 10062 ast_rwlock_unlock(&globalslock); 10063 if (ret) 10064 break; 10065 } 10066 10067 if (chan) 10068 ast_channel_unlock(chan); 10069 10070 return ret; 10071 }
| static int pbx_builtin_gotoif | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 10295 of file pbx.c.
References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), pbx_checkcondition(), and strsep().
10296 { 10297 char *condition, *branch1, *branch2, *branch; 10298 char *stringp; 10299 10300 if (ast_strlen_zero(data)) { 10301 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 10302 return 0; 10303 } 10304 10305 stringp = ast_strdupa(data); 10306 condition = strsep(&stringp,"?"); 10307 branch1 = strsep(&stringp,":"); 10308 branch2 = strsep(&stringp,""); 10309 branch = pbx_checkcondition(condition) ? branch1 : branch2; 10310 10311 if (ast_strlen_zero(branch)) { 10312 ast_debug(1, "Not taking any branch\n"); 10313 return 0; 10314 } 10315 10316 return pbx_builtin_goto(chan, branch); 10317 }
| int pbx_builtin_importvar | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 10231 of file pbx.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), strsep(), value, and VAR_BUF_SIZE.
10232 { 10233 char *name; 10234 char *value; 10235 char *channel; 10236 char tmp[VAR_BUF_SIZE]; 10237 static int deprecation_warning = 0; 10238 10239 if (ast_strlen_zero(data)) { 10240 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 10241 return 0; 10242 } 10243 tmp[0] = 0; 10244 if (!deprecation_warning) { 10245 ast_log(LOG_WARNING, "ImportVar is deprecated. Please use Set(varname=${IMPORT(channel,variable)}) instead.\n"); 10246 deprecation_warning = 1; 10247 } 10248 10249 value = ast_strdupa(data); 10250 name = strsep(&value,"="); 10251 channel = strsep(&value,","); 10252 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 10253 struct ast_channel *chan2 = ast_channel_get_by_name(channel); 10254 if (chan2) { 10255 char *s = alloca(strlen(value) + 4); 10256 if (s) { 10257 sprintf(s, "${%s}", value); 10258 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 10259 } 10260 chan2 = ast_channel_unref(chan2); 10261 } 10262 pbx_builtin_setvar_helper(chan, name, tmp); 10263 } 10264 10265 return(0); 10266 }
| static int pbx_builtin_incomplete | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 9561 of file pbx.c.
References __ast_answer(), ast_channel::_state, ast_check_hangup(), AST_CONTROL_INCOMPLETE, ast_indicate(), AST_PBX_INCOMPLETE, AST_STATE_UP, and ast_strlen_zero().
09562 { 09563 const char *options = data; 09564 int answer = 1; 09565 09566 /* Some channels can receive DTMF in unanswered state; some cannot */ 09567 if (!ast_strlen_zero(options) && strchr(options, 'n')) { 09568 answer = 0; 09569 } 09570 09571 /* If the channel is hungup, stop waiting */ 09572 if (ast_check_hangup(chan)) { 09573 return -1; 09574 } else if (chan->_state != AST_STATE_UP && answer) { 09575 __ast_answer(chan, 0, 1); 09576 } 09577 09578 ast_indicate(chan, AST_CONTROL_INCOMPLETE); 09579 09580 return AST_PBX_INCOMPLETE; 09581 }
| static int pbx_builtin_noop | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
| void pbx_builtin_pushvar_helper | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| const char * | value | |||
| ) |
Add a variable to the channel variable stack, without removing any previously set value.
Definition at line 10073 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, ast_log(), ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_verb, globals, globalslock, LOG_WARNING, and ast_channel::varshead.
Referenced by acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), and frame_set_var().
10074 { 10075 struct ast_var_t *newvariable; 10076 struct varshead *headp; 10077 10078 if (name[strlen(name)-1] == ')') { 10079 char *function = ast_strdupa(name); 10080 10081 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 10082 ast_func_write(chan, function, value); 10083 return; 10084 } 10085 10086 if (chan) { 10087 ast_channel_lock(chan); 10088 headp = &chan->varshead; 10089 } else { 10090 ast_rwlock_wrlock(&globalslock); 10091 headp = &globals; 10092 } 10093 10094 if (value) { 10095 if (headp == &globals) 10096 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10097 newvariable = ast_var_assign(name, value); 10098 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10099 } 10100 10101 if (chan) 10102 ast_channel_unlock(chan); 10103 else 10104 ast_rwlock_unlock(&globalslock); 10105 }
| int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
| const char * | reason | |||
| ) |
Definition at line 3446 of file pbx.c.
References raise_exception().
03447 { 03448 /* Priority will become 1, next time through the AUTOLOOP */ 03449 return raise_exception(chan, reason, 0); 03450 }
| static int pbx_builtin_saycharacters | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 10356 of file pbx.c.
References ast_channel_language(), and ast_say_character_str().
10357 { 10358 int res = 0; 10359 10360 if (data) 10361 res = ast_say_character_str(chan, data, "", ast_channel_language(chan)); 10362 return res; 10363 }
| static int pbx_builtin_saydigits | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 10347 of file pbx.c.
References ast_channel_language(), and ast_say_digit_str().
10348 { 10349 int res = 0; 10350 10351 if (data) 10352 res = ast_say_digit_str(chan, data, "", ast_channel_language(chan)); 10353 return res; 10354 }
| static int pbx_builtin_saynumber | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 10319 of file pbx.c.
References ast_channel_language(), ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), LOG_WARNING, and strsep().
10320 { 10321 char tmp[256]; 10322 char *number = tmp; 10323 char *options; 10324 10325 if (ast_strlen_zero(data)) { 10326 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 10327 return -1; 10328 } 10329 ast_copy_string(tmp, data, sizeof(tmp)); 10330 strsep(&number, ","); 10331 options = strsep(&number, ","); 10332 if (options) { 10333 if ( strcasecmp(options, "f") && strcasecmp(options, "m") && 10334 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 10335 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 10336 return -1; 10337 } 10338 } 10339 10340 if (ast_say_number(chan, atoi(tmp), "", ast_channel_language(chan), options)) { 10341 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 10342 } 10343 10344 return 0; 10345 }
| static int pbx_builtin_sayphonetic | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 10365 of file pbx.c.
References ast_channel_language(), and ast_say_phonetic_str().
10366 { 10367 int res = 0; 10368 10369 if (data) 10370 res = ast_say_phonetic_str(chan, data, "", ast_channel_language(chan)); 10371 return res; 10372 }
| int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
| struct ast_str ** | buf | |||
| ) |
Create a human-readable string, specifying all variables and their corresponding values.
| chan | Channel from which to read variables | |
| buf | Dynamic string in which to place the result (should be allocated with ast_str_create). |
Definition at line 10004 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_reset(), ast_var_name(), ast_var_value(), ast_var_t::entries, LOG_ERROR, total, var, and ast_channel::varshead.
Referenced by ast_var_channels_table(), dumpchan_exec(), handle_show_chanvar(), handle_showchan(), and vars2manager().
10005 { 10006 struct ast_var_t *variables; 10007 const char *var, *val; 10008 int total = 0; 10009 10010 if (!chan) 10011 return 0; 10012 10013 ast_str_reset(*buf); 10014 10015 ast_channel_lock(chan); 10016 10017 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 10018 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 10019 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 10020 ) { 10021 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 10022 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 10023 break; 10024 } else 10025 total++; 10026 } else 10027 break; 10028 } 10029 10030 ast_channel_unlock(chan); 10031 10032 return total; 10033 }
| int pbx_builtin_setvar | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) |
Parse and set a single channel variable, where the name and value are separated with an '=' character.
Definition at line 10165 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(), strsep(), and value.
Referenced by ast_compile_ael2(), and rpt_exec().
10166 { 10167 char *name, *value, *mydata; 10168 10169 if (ast_compat_app_set) { 10170 return pbx_builtin_setvar_multiple(chan, data); 10171 } 10172 10173 if (ast_strlen_zero(data)) { 10174 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 10175 return 0; 10176 } 10177 10178 mydata = ast_strdupa(data); 10179 name = strsep(&mydata, "="); 10180 value = mydata; 10181 if (!value) { 10182 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 10183 return 0; 10184 } 10185 10186 if (strchr(name, ' ')) { 10187 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 10188 } 10189 10190 pbx_builtin_setvar_helper(chan, name, value); 10191 10192 return 0; 10193 }
| int pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| const char * | value | |||
| ) |
Add a variable to the channel variable stack, removing the most recently set value for the same name.
Definition at line 10107 of file pbx.c.
References ast_channel_lock, ast_channel_name(), ast_channel_uniqueid(), ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, and ast_channel::varshead.
Referenced by __analog_ss_thread(), __ast_pbx_run(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_helper(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), analog_ss_thread(), aqm_exec(), array(), ast_bridge_call(), ast_cc_agent_set_interfaces_chanvar(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_pickup_call(), ast_rtp_instance_set_stats_vars(), ast_set_cc_interfaces_chanvar(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), calendar_write_exec(), cb_events(), cccancel_exec(), ccreq_exec(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmf(), dahdi_new(), dial_exec_full(), disa_exec(), do_notify(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), fax_detect_framehook(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), launch_monitor_thread(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parked_call(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), msg_send_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), parked_call_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), receivefax_exec(), record_exec(), reload_module(), return_exec(), rollback_exec(), rotate_file(), rpt_exec(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), setsubstate(), shift_pop(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), start_monitor_exec(), system_exec_helper(), testtime_write(), transfer_exec(), transmit(), tryexec_exec(), unshift_push(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().
10108 { 10109 struct ast_var_t *newvariable; 10110 struct varshead *headp; 10111 const char *nametail = name; 10112 10113 if (name[strlen(name) - 1] == ')') { 10114 char *function = ast_strdupa(name); 10115 10116 return ast_func_write(chan, function, value); 10117 } 10118 10119 if (chan) { 10120 ast_channel_lock(chan); 10121 headp = &chan->varshead; 10122 } else { 10123 ast_rwlock_wrlock(&globalslock); 10124 headp = &globals; 10125 } 10126 10127 /* For comparison purposes, we have to strip leading underscores */ 10128 if (*nametail == '_') { 10129 nametail++; 10130 if (*nametail == '_') 10131 nametail++; 10132 } 10133 10134 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 10135 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 10136 /* there is already such a variable, delete it */ 10137 AST_LIST_REMOVE_CURRENT(entries); 10138 ast_var_delete(newvariable); 10139 break; 10140 } 10141 } 10142 AST_LIST_TRAVERSE_SAFE_END; 10143 10144 if (value) { 10145 if (headp == &globals) 10146 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10147 newvariable = ast_var_assign(name, value); 10148 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10149 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 10150 "Channel: %s\r\n" 10151 "Variable: %s\r\n" 10152 "Value: %s\r\n" 10153 "Uniqueid: %s\r\n", 10154 chan ? ast_channel_name(chan) : "none", name, value, 10155 chan ? ast_channel_uniqueid(chan) : "none"); 10156 } 10157 10158 if (chan) 10159 ast_channel_unlock(chan); 10160 else 10161 ast_rwlock_unlock(&globalslock); 10162 return 0; 10163 }
| int pbx_builtin_setvar_multiple | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) |
Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
Definition at line 10195 of file pbx.c.
References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_channel::context, ast_channel::exten, LOG_WARNING, pbx_builtin_setvar_helper(), ast_channel::priority, and value.
Referenced by pbx_builtin_setvar(), queue_function_var(), set_queue_variables(), and try_calling().
10196 { 10197 char *data; 10198 int x; 10199 AST_DECLARE_APP_ARGS(args, 10200 AST_APP_ARG(pair)[24]; 10201 ); 10202 AST_DECLARE_APP_ARGS(pair, 10203 AST_APP_ARG(name); 10204 AST_APP_ARG(value); 10205 ); 10206 10207 if (ast_strlen_zero(vdata)) { 10208 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 10209 return 0; 10210 } 10211 10212 data = ast_strdupa(vdata); 10213 AST_STANDARD_APP_ARGS(args, data); 10214 10215 for (x = 0; x < args.argc; x++) { 10216 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 10217 if (pair.argc == 2) { 10218 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 10219 if (strchr(pair.name, ' ')) 10220 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); 10221 } else if (!chan) { 10222 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 10223 } else { 10224 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 10225 } 10226 } 10227 10228 return 0; 10229 }
| 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 10283 of file pbx.c.
References ast_strlen_zero().
Referenced by _macro_exec(), _while_exec(), acf_if(), execif_exec(), gosubif_exec(), macroif_exec(), pbx_builtin_gotoif(), and testtime_write().
10284 { 10285 int res; 10286 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 10287 return 0; 10288 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 10289 return res; 10290 } else { /* Strings are true */ 10291 return 1; 10292 } 10293 }
| static void pbx_destroy | ( | struct ast_pbx * | p | ) | [static] |
Definition at line 1603 of file pbx.c.
References ast_free.
Referenced by __ast_pbx_run().
01604 { 01605 ast_free(p); 01606 }
| int pbx_exec | ( | struct ast_channel * | c, | |
| struct ast_app * | app, | |||
| const char * | data | |||
| ) |
Execute an application.
| c | channel to execute on | |
| app | which app to execute | |
| data | the data passed into the app |
| 0 | success | |
| -1 | failure |
| c | Channel |
| app | Application |
| data | Data for execution |
Definition at line 1523 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_channel::appl, ast_cdr_setapp(), AST_CEL_APP_END, AST_CEL_APP_START, ast_cel_report_event(), ast_check_hangup(), ast_log(), ast_opt_dont_warn, ast_strlen_zero(), ast_channel::cdr, ast_channel::data, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, and S_OR.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), record_thread(), try_calling(), and tryexec_exec().
01526 { 01527 int res; 01528 struct ast_module_user *u = NULL; 01529 const char *saved_c_appl; 01530 const char *saved_c_data; 01531 01532 if (c->cdr && !ast_check_hangup(c)) 01533 ast_cdr_setapp(c->cdr, app->name, data); 01534 01535 /* save channel values */ 01536 saved_c_appl= c->appl; 01537 saved_c_data= c->data; 01538 01539 c->appl = app->name; 01540 c->data = data; 01541 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01542 01543 if (app->module) 01544 u = __ast_module_user_add(app->module, c); 01545 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01546 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01547 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01548 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01549 app->name, (char *) data); 01550 } 01551 res = app->execute(c, S_OR(data, "")); 01552 if (app->module && u) 01553 __ast_module_user_remove(app->module, u); 01554 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01555 /* restore channel values */ 01556 c->appl = saved_c_appl; 01557 c->data = saved_c_data; 01558 return res; 01559 }
| 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 4326 of file pbx.c.
References ast_exten::app, app, ast_channel_name(), ast_channel_uniqueid(), ast_copy_string(), ast_debug, ast_log(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_verb, ast_exten::cached_app, COLOR_BRCYAN, COLOR_BRMAGENTA, ast_channel::context, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCH, E_MATCHMORE, EVENT_FLAG_DIALPLAN, ast_switch::exec, EXT_DATA_SIZE, ast_channel::exten, pbx_find_info::foundcontext, LOG_NOTICE, LOG_WARNING, manager_event, ast_switch::name, ast_app::name, pbx_exec(), pbx_find_extension(), pbx_findapp(), pbx_substitute_variables(), ast_channel::priority, ast_exten::priority, S_OR, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, pbx_find_info::swo, term_color(), and VERBOSITY_ATLEAST.
Referenced by ast_canmatch_extension(), ast_exists_extension(), ast_findlabel_extension(), ast_findlabel_extension2(), ast_matchmore_extension(), and ast_spawn_extension().
04329 { 04330 struct ast_exten *e; 04331 struct ast_app *app; 04332 int res; 04333 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 04334 char passdata[EXT_DATA_SIZE]; 04335 04336 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 04337 04338 ast_rdlock_contexts(); 04339 if (found) 04340 *found = 0; 04341 04342 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 04343 if (e) { 04344 if (found) 04345 *found = 1; 04346 if (matching_action) { 04347 ast_unlock_contexts(); 04348 return -1; /* success, we found it */ 04349 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 04350 res = e->priority; 04351 ast_unlock_contexts(); 04352 return res; /* the priority we were looking for */ 04353 } else { /* spawn */ 04354 if (!e->cached_app) 04355 e->cached_app = pbx_findapp(e->app); 04356 app = e->cached_app; 04357 ast_unlock_contexts(); 04358 if (!app) { 04359 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 04360 return -1; 04361 } 04362 if (c->context != context) 04363 ast_copy_string(c->context, context, sizeof(c->context)); 04364 if (c->exten != exten) 04365 ast_copy_string(c->exten, exten, sizeof(c->exten)); 04366 c->priority = priority; 04367 pbx_substitute_variables(passdata, sizeof(passdata), c, e); 04368 #ifdef CHANNEL_TRACE 04369 ast_channel_trace_update(c); 04370 #endif 04371 ast_debug(1, "Launching '%s'\n", app->name); 04372 if (VERBOSITY_ATLEAST(3)) { 04373 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 04374 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 04375 exten, context, priority, 04376 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 04377 term_color(tmp2, ast_channel_name(c), COLOR_BRMAGENTA, 0, sizeof(tmp2)), 04378 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 04379 "in new stack"); 04380 } 04381 manager_event(EVENT_FLAG_DIALPLAN, "Newexten", 04382 "Channel: %s\r\n" 04383 "Context: %s\r\n" 04384 "Extension: %s\r\n" 04385 "Priority: %d\r\n" 04386 "Application: %s\r\n" 04387 "AppData: %s\r\n" 04388 "Uniqueid: %s\r\n", 04389 ast_channel_name(c), c->context, c->exten, c->priority, app->name, passdata, ast_channel_uniqueid(c)); 04390 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 04391 } 04392 } else if (q.swo) { /* not found here, but in another switch */ 04393 if (found) 04394 *found = 1; 04395 ast_unlock_contexts(); 04396 if (matching_action) { 04397 return -1; 04398 } else { 04399 if (!q.swo->exec) { 04400 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 04401 res = -1; 04402 } 04403 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 04404 } 04405 } else { /* not found anywhere, see what happened */ 04406 ast_unlock_contexts(); 04407 /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */ 04408 switch (q.status) { 04409 case STATUS_NO_CONTEXT: 04410 if (!matching_action && !combined_find_spawn) 04411 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, "")); 04412 break; 04413 case STATUS_NO_EXTENSION: 04414 if (!matching_action && !combined_find_spawn) 04415 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, "")); 04416 break; 04417 case STATUS_NO_PRIORITY: 04418 if (!matching_action && !combined_find_spawn) 04419 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, "")); 04420 break; 04421 case STATUS_NO_LABEL: 04422 if (context && !combined_find_spawn) 04423 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, "")); 04424 break; 04425 default: 04426 ast_debug(1, "Shouldn't happen!\n"); 04427 } 04428 04429 return (matching_action) ? 0 : -1; 04430 } 04431 }
| 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 2819 of file pbx.c.
References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_debug, ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_buffer(), ast_str_size(), ast_str_thread_get(), ast_strdupa, ast_strlen_zero(), ast_walk_context_extensions(), ast_switch::canmatch, scoreboard::canmatch_exten, create_match_char_tree(), ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, scoreboard::exten, extenpatternmatchnew, extension_match_core(), find_context(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_context::name, ast_sw::name, new_find_extension(), ast_include::next, scoreboard::node, overrideswitch, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, strsep(), switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().
Referenced by ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), check_goto(), check_pval_item(), get_parking_exten(), pbx_extension_helper(), pbx_find_extension(), register_peer_exten(), and remove_exten_if_exist().
02823 { 02824 int x, res; 02825 struct ast_context *tmp = NULL; 02826 struct ast_exten *e = NULL, *eroot = NULL; 02827 struct ast_include *i = NULL; 02828 struct ast_sw *sw = NULL; 02829 struct ast_exten pattern = {NULL, }; 02830 struct scoreboard score = {0, }; 02831 struct ast_str *tmpdata = NULL; 02832 02833 pattern.label = label; 02834 pattern.priority = priority; 02835 #ifdef NEED_DEBUG_HERE 02836 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02837 #endif 02838 02839 /* Initialize status if appropriate */ 02840 if (q->stacklen == 0) { 02841 q->status = STATUS_NO_CONTEXT; 02842 q->swo = NULL; 02843 q->data = NULL; 02844 q->foundcontext = NULL; 02845 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02846 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02847 return NULL; 02848 } 02849 02850 /* Check first to see if we've already been checked */ 02851 for (x = 0; x < q->stacklen; x++) { 02852 if (!strcasecmp(q->incstack[x], context)) 02853 return NULL; 02854 } 02855 02856 if (bypass) { /* bypass means we only look there */ 02857 tmp = bypass; 02858 } else { /* look in contexts */ 02859 tmp = find_context(context); 02860 if (!tmp) { 02861 return NULL; 02862 } 02863 } 02864 02865 if (q->status < STATUS_NO_EXTENSION) 02866 q->status = STATUS_NO_EXTENSION; 02867 02868 /* Do a search for matching extension */ 02869 02870 eroot = NULL; 02871 score.total_specificity = 0; 02872 score.exten = 0; 02873 score.total_length = 0; 02874 if (!tmp->pattern_tree && tmp->root_table) { 02875 create_match_char_tree(tmp); 02876 #ifdef NEED_DEBUG 02877 ast_debug(1, "Tree Created in context %s:\n", context); 02878 log_match_char_tree(tmp->pattern_tree," "); 02879 #endif 02880 } 02881 #ifdef NEED_DEBUG 02882 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 02883 log_match_char_tree(tmp->pattern_tree, ":: "); 02884 #endif 02885 02886 do { 02887 if (!ast_strlen_zero(overrideswitch)) { 02888 char *osw = ast_strdupa(overrideswitch), *name; 02889 struct ast_switch *asw; 02890 ast_switch_f *aswf = NULL; 02891 char *datap; 02892 int eval = 0; 02893 02894 name = strsep(&osw, "/"); 02895 asw = pbx_findswitch(name); 02896 02897 if (!asw) { 02898 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 02899 break; 02900 } 02901 02902 if (osw && strchr(osw, '$')) { 02903 eval = 1; 02904 } 02905 02906 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02907 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!"); 02908 break; 02909 } else if (eval) { 02910 /* Substitute variables now */ 02911 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02912 datap = ast_str_buffer(tmpdata); 02913 } else { 02914 datap = osw; 02915 } 02916 02917 /* equivalent of extension_match_core() at the switch level */ 02918 if (action == E_CANMATCH) 02919 aswf = asw->canmatch; 02920 else if (action == E_MATCHMORE) 02921 aswf = asw->matchmore; 02922 else /* action == E_MATCH */ 02923 aswf = asw->exists; 02924 if (!aswf) { 02925 res = 0; 02926 } else { 02927 if (chan) { 02928 ast_autoservice_start(chan); 02929 } 02930 res = aswf(chan, context, exten, priority, callerid, datap); 02931 if (chan) { 02932 ast_autoservice_stop(chan); 02933 } 02934 } 02935 if (res) { /* Got a match */ 02936 q->swo = asw; 02937 q->data = datap; 02938 q->foundcontext = context; 02939 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02940 return NULL; 02941 } 02942 } 02943 } while (0); 02944 02945 if (extenpatternmatchnew) { 02946 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02947 eroot = score.exten; 02948 02949 if (score.last_char == '!' && action == E_MATCHMORE) { 02950 /* We match an extension ending in '!'. 02951 * The decision in this case is final and is NULL (no match). 02952 */ 02953 #ifdef NEED_DEBUG_HERE 02954 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02955 #endif 02956 return NULL; 02957 } 02958 02959 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02960 q->status = STATUS_SUCCESS; 02961 #ifdef NEED_DEBUG_HERE 02962 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02963 #endif 02964 return score.canmatch_exten; 02965 } 02966 02967 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02968 if (score.node) { 02969 struct ast_exten *z = trie_find_next_match(score.node); 02970 if (z) { 02971 #ifdef NEED_DEBUG_HERE 02972 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02973 #endif 02974 } else { 02975 if (score.canmatch_exten) { 02976 #ifdef NEED_DEBUG_HERE 02977 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02978 #endif 02979 return score.canmatch_exten; 02980 } else { 02981 #ifdef NEED_DEBUG_HERE 02982 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02983 #endif 02984 } 02985 } 02986 return z; 02987 } 02988 #ifdef NEED_DEBUG_HERE 02989 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02990 #endif 02991 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02992 } 02993 02994 if (eroot) { 02995 /* found entry, now look for the right priority */ 02996 if (q->status < STATUS_NO_PRIORITY) 02997 q->status = STATUS_NO_PRIORITY; 02998 e = NULL; 02999 if (action == E_FINDLABEL && label ) { 03000 if (q->status < STATUS_NO_LABEL) 03001 q->status = STATUS_NO_LABEL; 03002 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03003 } else { 03004 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03005 } 03006 if (e) { /* found a valid match */ 03007 q->status = STATUS_SUCCESS; 03008 q->foundcontext = context; 03009 #ifdef NEED_DEBUG_HERE 03010 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 03011 #endif 03012 return e; 03013 } 03014 } 03015 } else { /* the old/current default exten pattern match algorithm */ 03016 03017 /* scan the list trying to match extension and CID */ 03018 eroot = NULL; 03019 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 03020 int match = extension_match_core(eroot->exten, exten, action); 03021 /* 0 on fail, 1 on match, 2 on earlymatch */ 03022 03023 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 03024 continue; /* keep trying */ 03025 if (match == 2 && action == E_MATCHMORE) { 03026 /* We match an extension ending in '!'. 03027 * The decision in this case is final and is NULL (no match). 03028 */ 03029 return NULL; 03030 } 03031 /* found entry, now look for the right priority */ 03032 if (q->status < STATUS_NO_PRIORITY) 03033 q->status = STATUS_NO_PRIORITY; 03034 e = NULL; 03035 if (action == E_FINDLABEL && label ) { 03036 if (q->status < STATUS_NO_LABEL) 03037 q->status = STATUS_NO_LABEL; 03038 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03039 } else { 03040 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03041 } 03042 if (e) { /* found a valid match */ 03043 q->status = STATUS_SUCCESS; 03044 q->foundcontext = context; 03045 return e; 03046 } 03047 } 03048 } 03049 03050 /* Check alternative switches */ 03051 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 03052 struct ast_switch *asw = pbx_findswitch(sw->name); 03053 ast_switch_f *aswf = NULL; 03054 char *datap; 03055 03056 if (!asw) { 03057 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 03058 continue; 03059 } 03060 03061 /* Substitute variables now */ 03062 if (sw->eval) { 03063 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03064 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 03065 continue; 03066 } 03067 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03068 } 03069 03070 /* equivalent of extension_match_core() at the switch level */ 03071 if (action == E_CANMATCH) 03072 aswf = asw->canmatch; 03073 else if (action == E_MATCHMORE) 03074 aswf = asw->matchmore; 03075 else /* action == E_MATCH */ 03076 aswf = asw->exists; 03077 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 03078 if (!aswf) 03079 res = 0; 03080 else { 03081 if (chan) 03082 ast_autoservice_start(chan); 03083 res = aswf(chan, context, exten, priority, callerid, datap); 03084 if (chan) 03085 ast_autoservice_stop(chan); 03086 } 03087 if (res) { /* Got a match */ 03088 q->swo = asw; 03089 q->data = datap; 03090 q->foundcontext = context; 03091 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03092 return NULL; 03093 } 03094 } 03095 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 03096 /* Now try any includes we have in this context */ 03097 for (i = tmp->includes; i; i = i->next) { 03098 if (include_valid(i)) { 03099 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 03100 #ifdef NEED_DEBUG_HERE 03101 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 03102 #endif 03103 return e; 03104 } 03105 if (q->swo) 03106 return NULL; 03107 } 03108 } 03109 return NULL; 03110 }
| struct ast_app* pbx_findapp | ( | const char * | app | ) | [read] |
Find application handle in linked list.
Look up an application.
Definition at line 1567 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_app::name.
Referenced by aelsub_exec(), answer_exec_run(), ast_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), conf_start_record(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), realtime_exec(), record_thread(), try_calling(), and tryexec_exec().
01568 { 01569 struct ast_app *tmp; 01570 01571 AST_RWLIST_RDLOCK(&apps); 01572 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01573 if (!strcasecmp(tmp->name, app)) 01574 break; 01575 } 01576 AST_RWLIST_UNLOCK(&apps); 01577 01578 return tmp; 01579 }
| static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static, read] |
Definition at line 1581 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_switch::name.
Referenced by pbx_find_extension().
01582 { 01583 struct ast_switch *asw; 01584 01585 AST_RWLIST_RDLOCK(&switches); 01586 AST_RWLIST_TRAVERSE(&switches, asw, list) { 01587 if (!strcasecmp(asw->name, sw)) 01588 break; 01589 } 01590 AST_RWLIST_UNLOCK(&switches); 01591 01592 return asw; 01593 }
| static int pbx_parseable_goto | ( | struct ast_channel * | chan, | |
| const char * | goto_string, | |||
| int | async | |||
| ) | [static] |
Definition at line 10713 of file pbx.c.
References ast_async_goto(), ast_explicit_goto(), ast_findlabel_extension(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_channel::caller, ast_channel::context, ast_channel::exten, ast_party_caller::id, LOG_WARNING, ast_party_id::number, ast_channel::priority, S_COR, ast_party_number::str, strsep(), and ast_party_number::valid.
Referenced by ast_async_parseable_goto(), and ast_parseable_goto().
10714 { 10715 char *exten, *pri, *context; 10716 char *stringp; 10717 int ipri; 10718 int mode = 0; 10719 10720 if (ast_strlen_zero(goto_string)) { 10721 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n"); 10722 return -1; 10723 } 10724 stringp = ast_strdupa(goto_string); 10725 context = strsep(&stringp, ","); /* guaranteed non-null */ 10726 exten = strsep(&stringp, ","); 10727 pri = strsep(&stringp, ","); 10728 if (!exten) { /* Only a priority in this one */ 10729 pri = context; 10730 exten = NULL; 10731 context = NULL; 10732 } else if (!pri) { /* Only an extension and priority in this one */ 10733 pri = exten; 10734 exten = context; 10735 context = NULL; 10736 } 10737 if (*pri == '+') { 10738 mode = 1; 10739 pri++; 10740 } else if (*pri == '-') { 10741 mode = -1; 10742 pri++; 10743 } 10744 if (sscanf(pri, "%30d", &ipri) != 1) { 10745 ipri = ast_findlabel_extension(chan, context ? context : chan->context, 10746 exten ? exten : chan->exten, pri, 10747 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)); 10748 if (ipri < 1) { 10749 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 10750 return -1; 10751 } else 10752 mode = 0; 10753 } 10754 /* At this point we have a priority and maybe an extension and a context */ 10755 10756 if (mode) 10757 ipri = chan->priority + (ipri * mode); 10758 10759 if (async) 10760 ast_async_goto(chan, context, exten, ipri); 10761 else 10762 ast_explicit_goto(chan, context, exten, ipri); 10763 10764 return 0; 10765 10766 }
| void pbx_retrieve_variable | ( | struct ast_channel * | c, | |
| const char * | var, | |||
| char ** | ret, | |||
| char * | workspace, | |||
| int | workspacelen, | |||
| struct varshead * | headp | |||
| ) |
Support for Asterisk built-in variables in the dialplan.
Retrieve the value of a builtin variable or variable from the channel variable stack.
Definition at line 3240 of file pbx.c.
References ast_copy_string(), ast_free, ast_str_buffer(), ast_str_create(), ast_str_retrieve_variable(), and str.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
03241 { 03242 struct ast_str *str = ast_str_create(16); 03243 const char *cret; 03244 03245 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 03246 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 03247 *ret = cret ? workspace : NULL; 03248 ast_free(str); 03249 }
| int pbx_set_autofallthrough | ( | int | newval | ) |
Set "autofallthrough" flag, if newval is <0, does not actually set. If set to 1, sets to auto fall through. If newval set to 0, sets to no auto fall through (reads extension instead). Returns previous value.
Definition at line 5556 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05557 { 05558 int oldval = autofallthrough; 05559 autofallthrough = newval; 05560 return oldval; 05561 }
| int pbx_set_extenpatternmatchnew | ( | int | newval | ) |
Set "extenpatternmatchnew" flag, if newval is <0, does not actually set. If set to 1, sets to use the new Trie-based pattern matcher. If newval set to 0, sets to use the old linear-search algorithm. Returns previous value.
Definition at line 5563 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05564 { 05565 int oldval = extenpatternmatchnew; 05566 extenpatternmatchnew = newval; 05567 return oldval; 05568 }
| 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 5570 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05571 { 05572 if (overrideswitch) { 05573 ast_free(overrideswitch); 05574 } 05575 if (!ast_strlen_zero(newval)) { 05576 overrideswitch = ast_strdup(newval); 05577 } else { 05578 overrideswitch = NULL; 05579 } 05580 }
| static void pbx_substitute_variables | ( | char * | passdata, | |
| int | datalen, | |||
| struct ast_channel * | c, | |||
| struct ast_exten * | e | |||
| ) | [static] |
Definition at line 4289 of file pbx.c.
References ast_copy_string(), ast_exten::data, and pbx_substitute_variables_helper().
Referenced by pbx_extension_helper().
04290 { 04291 const char *tmp; 04292 04293 /* Nothing more to do */ 04294 if (!e->data) { 04295 *passdata = '\0'; 04296 return; 04297 } 04298 04299 /* No variables or expressions in e->data, so why scan it? */ 04300 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) { 04301 ast_copy_string(passdata, e->data, datalen); 04302 return; 04303 } 04304 04305 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1); 04306 }
| void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) |
Definition at line 4277 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by add_extensions(), ast_add_extension2_lockopt(), function_eval(), get_manager_event_info(), get_mapping_weight(), import_helper(), launch_monitor_thread(), manager_log(), pbx_builtin_importvar(), pbx_find_extension(), pbx_load_config(), pbx_substitute_variables(), realtime_exec(), rotate_file(), rpt_do_lstats(), rpt_exec(), substituted(), try_calling(), and write_cdr().
04278 { 04279 size_t used; 04280 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 04281 }
| void pbx_substitute_variables_helper_full | ( | struct ast_channel * | c, | |
| struct varshead * | headp, | |||
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count, | |||
| size_t * | used | |||
| ) |
Definition at line 4081 of file pbx.c.
References ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full(), substring(), var, VAR_BUF_SIZE, and ast_channel::varshead.
Referenced by pbx_substitute_variables_helper(), pbx_substitute_variables_helper_full(), and pbx_substitute_variables_varshead().
04082 { 04083 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 04084 char *cp4 = NULL; 04085 const char *whereweare, *orig_cp2 = cp2; 04086 int length, offset, offset2, isfunction; 04087 char *workspace = NULL; 04088 char *ltmp = NULL, *var = NULL; 04089 char *nextvar, *nextexp, *nextthing; 04090 char *vars, *vare; 04091 int pos, brackets, needsub, len; 04092 04093 *cp2 = 0; /* just in case nothing ends up there */ 04094 whereweare = cp1; 04095 while (!ast_strlen_zero(whereweare) && count) { 04096 /* Assume we're copying the whole remaining string */ 04097 pos = strlen(whereweare); 04098 nextvar = NULL; 04099 nextexp = NULL; 04100 nextthing = strchr(whereweare, '$'); 04101 if (nextthing) { 04102 switch (nextthing[1]) { 04103 case '{': 04104 nextvar = nextthing; 04105 pos = nextvar - whereweare; 04106 break; 04107 case '[': 04108 nextexp = nextthing; 04109 pos = nextexp - whereweare; 04110 break; 04111 default: 04112 pos = 1; 04113 } 04114 } 04115 04116 if (pos) { 04117 /* Can't copy more than 'count' bytes */ 04118 if (pos > count) 04119 pos = count; 04120 04121 /* Copy that many bytes */ 04122 memcpy(cp2, whereweare, pos); 04123 04124 count -= pos; 04125 cp2 += pos; 04126 whereweare += pos; 04127 *cp2 = 0; 04128 } 04129 04130 if (nextvar) { 04131 /* We have a variable. Find the start and end, and determine 04132 if we are going to have to recursively call ourselves on the 04133 contents */ 04134 vars = vare = nextvar + 2; 04135 brackets = 1; 04136 needsub = 0; 04137 04138 /* Find the end of it */ 04139 while (brackets && *vare) { 04140 if ((vare[0] == '$') && (vare[1] == '{')) { 04141 needsub++; 04142 } else if (vare[0] == '{') { 04143 brackets++; 04144 } else if (vare[0] == '}') { 04145 brackets--; 04146 } else if ((vare[0] == '$') && (vare[1] == '[')) 04147 needsub++; 04148 vare++; 04149 } 04150 if (brackets) 04151 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04152 len = vare - vars - 1; 04153 04154 /* Skip totally over variable string */ 04155 whereweare += (len + 3); 04156 04157 if (!var) 04158 var = alloca(VAR_BUF_SIZE); 04159 04160 /* Store variable name (and truncate) */ 04161 ast_copy_string(var, vars, len + 1); 04162 04163 /* Substitute if necessary */ 04164 if (needsub) { 04165 size_t used; 04166 if (!ltmp) 04167 ltmp = alloca(VAR_BUF_SIZE); 04168 04169 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04170 vars = ltmp; 04171 } else { 04172 vars = var; 04173 } 04174 04175 if (!workspace) 04176 workspace = alloca(VAR_BUF_SIZE); 04177 04178 workspace[0] = '\0'; 04179 04180 parse_variable_name(vars, &offset, &offset2, &isfunction); 04181 if (isfunction) { 04182 /* Evaluate function */ 04183 if (c || !headp) 04184 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04185 else { 04186 struct varshead old; 04187 struct ast_channel *c = ast_dummy_channel_alloc(); 04188 if (c) { 04189 memcpy(&old, &c->varshead, sizeof(old)); 04190 memcpy(&c->varshead, headp, sizeof(c->varshead)); 04191 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04192 /* Don't deallocate the varshead that was passed in */ 04193 memcpy(&c->varshead, &old, sizeof(c->varshead)); 04194 c = ast_channel_unref(c); 04195 } else { 04196 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04197 } 04198 } 04199 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 04200 } else { 04201 /* Retrieve variable value */ 04202 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 04203 } 04204 if (cp4) { 04205 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 04206 04207 length = strlen(cp4); 04208 if (length > count) 04209 length = count; 04210 memcpy(cp2, cp4, length); 04211 count -= length; 04212 cp2 += length; 04213 *cp2 = 0; 04214 } 04215 } else if (nextexp) { 04216 /* We have an expression. Find the start and end, and determine 04217 if we are going to have to recursively call ourselves on the 04218 contents */ 04219 vars = vare = nextexp + 2; 04220 brackets = 1; 04221 needsub = 0; 04222 04223 /* Find the end of it */ 04224 while (brackets && *vare) { 04225 if ((vare[0] == '$') && (vare[1] == '[')) { 04226 needsub++; 04227 brackets++; 04228 vare++; 04229 } else if (vare[0] == '[') { 04230 brackets++; 04231 } else if (vare[0] == ']') { 04232 brackets--; 04233 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04234 needsub++; 04235 vare++; 04236 } 04237 vare++; 04238 } 04239 if (brackets) 04240 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04241 len = vare - vars - 1; 04242 04243 /* Skip totally over expression */ 04244 whereweare += (len + 3); 04245 04246 if (!var) 04247 var = alloca(VAR_BUF_SIZE); 04248 04249 /* Store variable name (and truncate) */ 04250 ast_copy_string(var, vars, len + 1); 04251 04252 /* Substitute if necessary */ 04253 if (needsub) { 04254 size_t used; 04255 if (!ltmp) 04256 ltmp = alloca(VAR_BUF_SIZE); 04257 04258 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04259 vars = ltmp; 04260 } else { 04261 vars = var; 04262 } 04263 04264 length = ast_expr(vars, cp2, count, c); 04265 04266 if (length) { 04267 ast_debug(1, "Expression result is '%s'\n", cp2); 04268 count -= length; 04269 cp2 += length; 04270 *cp2 = 0; 04271 } 04272 } 04273 } 04274 *used = cp2 - orig_cp2; 04275 }
| void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
| const char * | cp1, | |||
| char * | cp2, | |||
| int | count | |||
| ) |
Definition at line 4283 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by do_say(), dundi_lookup_local(), get_mapping_weight(), and loopback_subst().
04284 { 04285 size_t used; 04286 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 04287 }
| static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 5474 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
05475 { 05476 /* Oh joyeous kernel, we're a new thread, with nothing to do but 05477 answer this channel and get it going. 05478 */ 05479 /* NOTE: 05480 The launcher of this function _MUST_ increment 'countcalls' 05481 before invoking the function; it will be decremented when the 05482 PBX has finished running on the channel 05483 */ 05484 struct ast_channel *c = data; 05485 05486 __ast_pbx_run(c, NULL); 05487 decrease_call_count(); 05488 05489 pthread_exit(NULL); 05490 05491 return NULL; 05492 }
| static void print_app_docs | ( | struct ast_app * | aa, | |
| int | fd | |||
| ) | [static] |
Definition at line 6086 of file pbx.c.
References ast_app::arguments, ast_cli(), ast_free, ast_malloc, AST_MAX_APP, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, COLOR_CYAN, COLOR_MAGENTA, ast_app::description, ast_switch::description, ast_app::name, S_OR, ast_app::seealso, ast_app::synopsis, synopsis, ast_app::syntax, and term_color().
Referenced by handle_show_application().
06087 { 06088 /* Maximum number of characters added by terminal coloring is 22 */ 06089 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40]; 06090 char seealsotitle[40]; 06091 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL; 06092 char *seealso = NULL; 06093 int syntax_size, synopsis_size, description_size, arguments_size, seealso_size; 06094 06095 snprintf(info, sizeof(info), "\n -= Info about application '%s' =- \n\n", aa->name); 06096 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 06097 06098 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 06099 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 06100 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 06101 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 06102 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 06103 06104 #ifdef AST_XML_DOCS 06105 if (aa->docsrc == AST_XML_DOC) { 06106 description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1); 06107 arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1); 06108 synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1); 06109 seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1); 06110 06111 if (!synopsis || !description || !arguments || !seealso) { 06112 goto return_cleanup; 06113 } 06114 } else 06115 #endif 06116 { 06117 synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06118 synopsis = ast_malloc(synopsis_size); 06119 06120 description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06121 description = ast_malloc(description_size); 06122 06123 arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06124 arguments = ast_malloc(arguments_size); 06125 06126 seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06127 seealso = ast_malloc(seealso_size); 06128 06129 if (!synopsis || !description || !arguments || !seealso) { 06130 goto return_cleanup; 06131 } 06132 06133 term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 06134 term_color(description, S_OR(aa->description, "Not available"), COLOR_CYAN, 0, description_size); 06135 term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 06136 term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 06137 } 06138 06139 /* Handle the syntax the same for both XML and raw docs */ 06140 syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 06141 if (!(syntax = ast_malloc(syntax_size))) { 06142 goto return_cleanup; 06143 } 06144 term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 06145 06146 ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 06147 infotitle, syntitle, synopsis, destitle, description, 06148 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 06149 06150 return_cleanup: 06151 ast_free(description); 06152 ast_free(arguments); 06153 ast_free(synopsis); 06154 ast_free(seealso); 06155 ast_free(syntax); 06156 }
| static void print_ext | ( | struct ast_exten * | e, | |
| char * | buf, | |||
| int | buflen | |||
| ) | [static] |
helper function to print an extension
Definition at line 6512 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().
06513 { 06514 int prio = ast_get_extension_priority(e); 06515 if (prio == PRIORITY_HINT) { 06516 snprintf(buf, buflen, "hint: %s", 06517 ast_get_extension_app(e)); 06518 } else { 06519 snprintf(buf, buflen, "%d. %s(%s)", 06520 prio, ast_get_extension_app(e), 06521 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 06522 } 06523 }
| static int raise_exception | ( | struct ast_channel * | chan, | |
| const char * | reason, | |||
| int | priority | |||
| ) | [static] |
Definition at line 3420 of file pbx.c.
References ast_calloc_with_stringfields, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), ast_string_field_set, ast_channel::context, ast_datastore::data, exception_store_info, ast_channel::exten, exten, ast_channel::priority, pbx_exception::priority, and set_ext_pri().
Referenced by __ast_pbx_run(), pbx_builtin_raise_exception(), and pbx_builtin_waitexten().
03421 { 03422 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03423 struct pbx_exception *exception = NULL; 03424 03425 if (!ds) { 03426 ds = ast_datastore_alloc(&exception_store_info, NULL); 03427 if (!ds) 03428 return -1; 03429 if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) { 03430 ast_datastore_free(ds); 03431 return -1; 03432 } 03433 ds->data = exception; 03434 ast_channel_datastore_add(chan, ds); 03435 } else 03436 exception = ds->data; 03437 03438 ast_string_field_set(exception, reason, reason); 03439 ast_string_field_set(exception, context, chan->context); 03440 ast_string_field_set(exception, exten, chan->exten); 03441 exception->priority = chan->priority; 03442 set_ext_pri(chan, "e", priority); 03443 return 0; 03444 }
| static int remove_hintdevice | ( | struct ast_hint * | hint | ) | [static] |
Definition at line 1018 of file pbx.c.
References ao2_t_callback, hintdevice_remove_cb(), OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.
Referenced by ast_change_hint(), and ast_remove_hint().
01019 { 01020 /* iterate through all devices and remove the devices which are linked to this hint */ 01021 ao2_t_callback(hintdevices, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, 01022 hintdevice_remove_cb, hint, 01023 "callback to remove all devices which are linked to a hint"); 01024 return 0; 01025 }
| 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 5057 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_channel::exten, and ast_channel::priority.
Referenced by __ast_pbx_run(), ast_pbx_outgoing_exten(), pbx_builtin_waitexten(), and raise_exception().
05058 { 05059 ast_channel_lock(c); 05060 ast_copy_string(c->exten, exten, sizeof(c->exten)); 05061 c->priority = pri; 05062 ast_channel_unlock(c); 05063 }
| 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 6677 of file pbx.c.
References ast_cli(), ast_exists_extension(), ast_get_context_name(), ast_get_context_registrar(), ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_contexts(), cli_match_char_tree(), dialplan_counters::context_existence, ast_context::name, ast_context::pattern_tree, dialplan_counters::total_context, and dialplan_counters::total_exten.
Referenced by handle_debug_dialplan().
06678 { 06679 struct ast_context *c = NULL; 06680 int res = 0, old_total_exten = dpc->total_exten; 06681 06682 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n"); 06683 06684 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n"); 06685 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n"); 06686 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n"); 06687 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n"); 06688 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n"); 06689 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n"); 06690 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n"); 06691 ast_rdlock_contexts(); 06692 06693 /* walk all contexts ... */ 06694 while ( (c = ast_walk_contexts(c)) ) { 06695 int context_info_printed = 0; 06696 06697 if (context && strcmp(ast_get_context_name(c), context)) 06698 continue; /* skip this one, name doesn't match */ 06699 06700 dpc->context_existence = 1; 06701 06702 if (!c->pattern_tree) 06703 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */ 06704 06705 ast_rdlock_context(c); 06706 06707 dpc->total_context++; 06708 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06709 ast_get_context_name(c), ast_get_context_registrar(c)); 06710 context_info_printed = 1; 06711 06712 if (c->pattern_tree) 06713 { 06714 cli_match_char_tree(c->pattern_tree, " ", fd); 06715 } else { 06716 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n"); 06717 } 06718 06719 ast_unlock_context(c); 06720 06721 /* if we print something in context, make an empty line */ 06722 if (context_info_printed) 06723 ast_cli(fd, "\n"); 06724 } 06725 ast_unlock_contexts(); 06726 06727 return (dpc->total_exten == old_total_exten) ? -1 : res; 06728 }
| 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 6526 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(), buf2, 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().
06527 { 06528 struct ast_context *c = NULL; 06529 int res = 0, old_total_exten = dpc->total_exten; 06530 06531 ast_rdlock_contexts(); 06532 06533 /* walk all contexts ... */ 06534 while ( (c = ast_walk_contexts(c)) ) { 06535 struct ast_exten *e; 06536 struct ast_include *i; 06537 struct ast_ignorepat *ip; 06538 char buf[256], buf2[256]; 06539 int context_info_printed = 0; 06540 06541 if (context && strcmp(ast_get_context_name(c), context)) 06542 continue; /* skip this one, name doesn't match */ 06543 06544 dpc->context_existence = 1; 06545 06546 ast_rdlock_context(c); 06547 06548 /* are we looking for exten too? if yes, we print context 06549 * only if we find our extension. 06550 * Otherwise print context even if empty ? 06551 * XXX i am not sure how the rinclude is handled. 06552 * I think it ought to go inside. 06553 */ 06554 if (!exten) { 06555 dpc->total_context++; 06556 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06557 ast_get_context_name(c), ast_get_context_registrar(c)); 06558 context_info_printed = 1; 06559 } 06560 06561 /* walk extensions ... */ 06562 e = NULL; 06563 while ( (e = ast_walk_context_extensions(c, e)) ) { 06564 struct ast_exten *p; 06565 06566 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 06567 continue; /* skip, extension match failed */ 06568 06569 dpc->extension_existence = 1; 06570 06571 /* may we print context info? */ 06572 if (!context_info_printed) { 06573 dpc->total_context++; 06574 if (rinclude) { /* TODO Print more info about rinclude */ 06575 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 06576 ast_get_context_name(c), ast_get_context_registrar(c)); 06577 } else { 06578 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06579 ast_get_context_name(c), ast_get_context_registrar(c)); 06580 } 06581 context_info_printed = 1; 06582 } 06583 dpc->total_prio++; 06584 06585 /* write extension name and first peer */ 06586 if (e->matchcid) 06587 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch); 06588 else 06589 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 06590 06591 print_ext(e, buf2, sizeof(buf2)); 06592 06593 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 06594 ast_get_extension_registrar(e)); 06595 06596 dpc->total_exten++; 06597 /* walk next extension peers */ 06598 p = e; /* skip the first one, we already got it */ 06599 while ( (p = ast_walk_extension_priorities(e, p)) ) { 06600 const char *el = ast_get_extension_label(p); 06601 dpc->total_prio++; 06602 if (el) 06603 snprintf(buf, sizeof(buf), " [%s]", el); 06604 else 06605 buf[0] = '\0'; 06606 print_ext(p, buf2, sizeof(buf2)); 06607 06608 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 06609 ast_get_extension_registrar(p)); 06610 } 06611 } 06612 06613 /* walk included and write info ... */ 06614 i = NULL; 06615 while ( (i = ast_walk_context_includes(c, i)) ) { 06616 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 06617 if (exten) { 06618 /* Check all includes for the requested extension */ 06619 if (includecount >= AST_PBX_MAX_STACK) { 06620 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n"); 06621 } else { 06622 int dupe = 0; 06623 int x; 06624 for (x = 0; x < includecount; x++) { 06625 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 06626 dupe++; 06627 break; 06628 } 06629 } 06630 if (!dupe) { 06631 includes[includecount] = ast_get_include_name(i); 06632 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 06633 } else { 06634 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 06635 } 06636 } 06637 } else { 06638 ast_cli(fd, " Include => %-45s [%s]\n", 06639 buf, ast_get_include_registrar(i)); 06640 } 06641 } 06642 06643 /* walk ignore patterns and write info ... */ 06644 ip = NULL; 06645 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 06646 const char *ipname = ast_get_ignorepat_name(ip); 06647 char ignorepat[AST_MAX_EXTENSION]; 06648 snprintf(buf, sizeof(buf), "'%s'", ipname); 06649 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 06650 if (!exten || ast_extension_match(ignorepat, exten)) { 06651 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 06652 buf, ast_get_ignorepat_registrar(ip)); 06653 } 06654 } 06655 if (!rinclude) { 06656 struct ast_sw *sw = NULL; 06657 while ( (sw = ast_walk_context_switches(c, sw)) ) { 06658 snprintf(buf, sizeof(buf), "'%s/%s'", 06659 ast_get_switch_name(sw), 06660 ast_get_switch_data(sw)); 06661 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 06662 buf, ast_get_switch_registrar(sw)); 06663 } 06664 } 06665 06666 ast_unlock_context(c); 06667 06668 /* if we print something in context, make an empty line */ 06669 if (context_info_printed) 06670 ast_cli(fd, "\n"); 06671 } 06672 ast_unlock_contexts(); 06673 06674 return (dpc->total_exten == old_total_exten) ? -1 : res; 06675 }
| static int statecbs_cmp | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 10825 of file pbx.c.
References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.
Referenced by ast_pbx_init().
10826 { 10827 const struct ast_state_cb *state_cb = obj; 10828 ast_state_cb_type change_cb = arg; 10829 10830 return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0; 10831 }
| 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 3150 of file pbx.c.
References ast_copy_string().
Referenced by pbx_substitute_variables_helper_full().
03151 { 03152 char *ret = workspace; 03153 int lr; /* length of the input string after the copy */ 03154 03155 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 03156 03157 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 03158 03159 /* Quick check if no need to do anything */ 03160 if (offset == 0 && length >= lr) /* take the whole string */ 03161 return ret; 03162 03163 if (offset < 0) { /* translate negative offset into positive ones */ 03164 offset = lr + offset; 03165 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 03166 offset = 0; 03167 } 03168 03169 /* too large offset result in empty string so we know what to return */ 03170 if (offset >= lr) 03171 return ret + lr; /* the final '\0' */ 03172 03173 ret += offset; /* move to the start position */ 03174 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 03175 ret[length] = '\0'; 03176 else if (length < 0) { 03177 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 03178 ret[lr + length - offset] = '\0'; 03179 else 03180 ret[0] = '\0'; 03181 } 03182 03183 return ret; 03184 }
| static struct ast_exten* trie_find_next_match | ( | struct match_char * | node | ) | [static, read] |
Definition at line 1777 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().
01778 { 01779 struct match_char *m3; 01780 struct match_char *m4; 01781 struct ast_exten *e3; 01782 01783 if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */ 01784 return node->exten; 01785 } 01786 01787 if (node && node->x[0] == '!' && !node->x[1]) { 01788 return node->exten; 01789 } 01790 01791 if (!node || !node->next_char) { 01792 return NULL; 01793 } 01794 01795 m3 = node->next_char; 01796 01797 if (m3->exten) { 01798 return m3->exten; 01799 } 01800 for (m4 = m3->alt_char; m4; m4 = m4->alt_char) { 01801 if (m4->exten) { 01802 return m4->exten; 01803 } 01804 } 01805 for (m4 = m3; m4; m4 = m4->alt_char) { 01806 e3 = trie_find_next_match(m3); 01807 if (e3) { 01808 return e3; 01809 } 01810 } 01811 01812 return NULL; 01813 }
| static void unreference_cached_app | ( | struct ast_app * | app | ) | [static] |
Definition at line 7284 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().
07285 { 07286 struct ast_context *context = NULL; 07287 struct ast_exten *eroot = NULL, *e = NULL; 07288 07289 ast_rdlock_contexts(); 07290 while ((context = ast_walk_contexts(context))) { 07291 while ((eroot = ast_walk_context_extensions(context, eroot))) { 07292 while ((e = ast_walk_extension_priorities(eroot, e))) { 07293 if (e->cached_app == app) 07294 e->cached_app = NULL; 07295 } 07296 } 07297 } 07298 ast_unlock_contexts(); 07299 07300 return; 07301 }
| 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 1682 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().
01683 { 01684 /* if this extension is marked as deleted, then skip this -- if it never shows 01685 on the scoreboard, it will never be found, nor will halt the traversal. */ 01686 if (deleted) 01687 return; 01688 board->total_specificity = spec; 01689 board->total_length = length; 01690 board->exten = exten; 01691 board->last_char = last; 01692 board->node = node; 01693 #ifdef NEED_DEBUG_HERE 01694 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec); 01695 #endif 01696 }
| static void wait_for_hangup | ( | struct ast_channel * | chan, | |
| const void * | data | |||
| ) | [static] |
Definition at line 9445 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().
09446 { 09447 int res; 09448 struct ast_frame *f; 09449 double waitsec; 09450 int waittime; 09451 09452 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0)) 09453 waitsec = -1; 09454 if (waitsec > -1) { 09455 waittime = waitsec * 1000.0; 09456 ast_safe_sleep(chan, waittime); 09457 } else do { 09458 res = ast_waitfor(chan, -1); 09459 if (res < 0) 09460 return; 09461 f = ast_read(chan); 09462 if (f) 09463 ast_frfree(f); 09464 } while(f); 09465 }
int autofallthrough = 1 [static] |
Definition at line 1261 of file pbx.c.
Referenced by __ast_pbx_run(), and pbx_set_autofallthrough().
struct ast_app_option background_opts[128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },} [static] |
struct pbx_builtin builtins[] [static] |
ast_mutex_t conlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static] |
Lock for the ast_context list.
Definition at line 1320 of file pbx.c.
Referenced by ast_rdlock_contexts(), ast_unlock_contexts(), and ast_wrlock_contexts().
ast_mutex_t context_merge_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static] |
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
Definition at line 1325 of file pbx.c.
Referenced by ast_merge_contexts_and_delete(), and handle_statechange().
struct ast_context* contexts [static] |
Definition at line 1311 of file pbx.c.
Referenced by __ast_context_destroy(), ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and ast_walk_contexts().
struct ast_hashtab* contexts_table = NULL [static] |
Definition at line 1312 of file pbx.c.
Referenced by ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), find_context(), and find_context_locked().
int countcalls [static] |
Definition at line 1269 of file pbx.c.
Referenced by ast_active_calls(), decrease_call_count(), and increase_call_count().
const char* const days[] [static] |
struct ast_event_sub* device_state_sub [static] |
struct ast_taskprocessor* device_state_tps [static] |
struct ast_custom_function exception_function [static] |
Initial value:
{
.name = "EXCEPTION",
.read = acf_exception_read,
}
Definition at line 3472 of file pbx.c.
Referenced by load_pbx().
struct ast_datastore_info exception_store_info [static] |
Initial value:
{
.type = "EXCEPTION",
.destroy = exception_store_free,
}
Definition at line 3404 of file pbx.c.
Referenced by acf_exception_read(), and raise_exception().
int extenpatternmatchnew = 0 [static] |
Definition at line 1262 of file pbx.c.
Referenced by pbx_find_extension(), and pbx_set_extenpatternmatchnew().
struct cfextension_states extension_states[] [static] |
Referenced by ast_extension_state2str().
struct ast_threadstorage extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , } [static] |
ast_rwlock_t globalslock = { {0} , NULL, 1 } [static] |
Definition at line 1258 of file pbx.c.
Referenced by ast_str_retrieve_variable(), handle_show_globals(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
struct ast_threadstorage hintdevice_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_hintdevice_data , .custom_init = NULL , } [static] |
struct ao2_container* hintdevices [static] |
struct ao2_container* hints [static] |
Definition at line 1340 of file pbx.c.
Referenced by ast_add_hint(), ast_change_hint(), ast_extension_state_add_destroy(), ast_extension_state_del(), ast_merge_contexts_and_delete(), ast_pbx_init(), ast_remove_hint(), complete_core_show_hint(), handle_show_hint(), handle_show_hints(), hints_data_provider_get(), and lua_register_hints().
struct ast_data_handler hints_data_provider [static] |
Initial value:
{
.version = AST_DATA_HANDLER_VERSION,
.get = hints_data_provider_get
}
ast_mutex_t maxcalllock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static] |
Definition at line 1268 of file pbx.c.
Referenced by decrease_call_count(), and increase_call_count().
const char* const months[] [static] |
char* overrideswitch = NULL [static] |
Definition at line 1263 of file pbx.c.
Referenced by handle_cli_dialplan_save(), pbx_find_extension(), and pbx_set_overrideswitch().
struct ast_cli_entry pbx_cli[] [static] |
struct ast_data_entry pbx_data_providers[] [static] |
Initial value:
{
AST_DATA_ENTRY("asterisk/core/hints", &hints_data_provider),
}
Definition at line 10436 of file pbx.c.
Referenced by load_pbx().
struct ast_app_option resetcdr_opts[128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },} [static] |
struct ao2_container* statecbs [static] |
Definition at line 1342 of file pbx.c.
Referenced by ast_extension_state_add_destroy(), ast_extension_state_del(), ast_pbx_init(), and handle_statechange().
int stateid = 1 [static] |
struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , } [static] |
struct ast_custom_function testtime_function [static] |
Initial value:
{
.name = "TESTTIME",
.write = testtime_write,
}
Definition at line 9679 of file pbx.c.
Referenced by load_pbx().
int totalcalls [static] |
Definition at line 1270 of file pbx.c.
Referenced by ast_processed_calls(), increase_call_count(), and timing_read().
struct ast_app_option waitexten_opts[128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },} [static] |
1.5.6