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