#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. | |
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) |
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 968 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 93 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 2032 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_EXTENSION 2 |
Definition at line 2033 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_LABEL 4 |
Definition at line 2035 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_PRIORITY 3 |
Definition at line 2034 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 98 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 7659 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().
07660 { 07661 struct ast_context *tmp, *tmpl=NULL; 07662 struct ast_exten *exten_item, *prio_item; 07663 07664 for (tmp = list; tmp; ) { 07665 struct ast_context *next = NULL; /* next starting point */ 07666 /* The following code used to skip forward to the next 07667 context with matching registrar, but this didn't 07668 make sense; individual priorities registrar'd to 07669 the matching registrar could occur in any context! */ 07670 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar); 07671 if (con) { 07672 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */ 07673 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar); 07674 if ( !strcasecmp(tmp->name, con->name) ) { 07675 break; /* found it */ 07676 } 07677 } 07678 } 07679 07680 if (!tmp) /* not found, we are done */ 07681 break; 07682 ast_wrlock_context(tmp); 07683 07684 if (registrar) { 07685 /* then search thru and remove any extens that match registrar. */ 07686 struct ast_hashtab_iter *exten_iter; 07687 struct ast_hashtab_iter *prio_iter; 07688 struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL; 07689 struct ast_include *i, *pi = NULL, *ni = NULL; 07690 struct ast_sw *sw = NULL; 07691 07692 /* remove any ignorepats whose registrar matches */ 07693 for (ip = tmp->ignorepats; ip; ip = ipn) { 07694 ipn = ip->next; 07695 if (!strcmp(ip->registrar, registrar)) { 07696 if (ipl) { 07697 ipl->next = ip->next; 07698 ast_free(ip); 07699 continue; /* don't change ipl */ 07700 } else { 07701 tmp->ignorepats = ip->next; 07702 ast_free(ip); 07703 continue; /* don't change ipl */ 07704 } 07705 } 07706 ipl = ip; 07707 } 07708 /* remove any includes whose registrar matches */ 07709 for (i = tmp->includes; i; i = ni) { 07710 ni = i->next; 07711 if (strcmp(i->registrar, registrar) == 0) { 07712 /* remove from list */ 07713 if (pi) { 07714 pi->next = i->next; 07715 /* free include */ 07716 ast_free(i); 07717 continue; /* don't change pi */ 07718 } else { 07719 tmp->includes = i->next; 07720 /* free include */ 07721 ast_free(i); 07722 continue; /* don't change pi */ 07723 } 07724 } 07725 pi = i; 07726 } 07727 /* remove any switches whose registrar matches */ 07728 AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) { 07729 if (strcmp(sw->registrar,registrar) == 0) { 07730 AST_LIST_REMOVE_CURRENT(list); 07731 ast_free(sw); 07732 } 07733 } 07734 AST_LIST_TRAVERSE_SAFE_END; 07735 07736 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */ 07737 exten_iter = ast_hashtab_start_traversal(tmp->root_table); 07738 while ((exten_item=ast_hashtab_next(exten_iter))) { 07739 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 07740 while ((prio_item=ast_hashtab_next(prio_iter))) { 07741 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) { 07742 continue; 07743 } 07744 ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n", 07745 tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL); 07746 /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */ 07747 ast_context_remove_extension_callerid2(tmp, prio_item->exten, prio_item->priority, prio_item->cidmatch, 1, NULL, 1); 07748 } 07749 ast_hashtab_end_traversal(prio_iter); 07750 } 07751 ast_hashtab_end_traversal(exten_iter); 07752 } 07753 07754 /* delete the context if it's registrar matches, is empty, has refcount of 1, */ 07755 /* it's not empty, if it has includes, ignorepats, or switches that are registered from 07756 another registrar. It's not empty if there are any extensions */ 07757 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) { 07758 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 07759 ast_hashtab_remove_this_object(contexttab, tmp); 07760 07761 next = tmp->next; 07762 if (tmpl) 07763 tmpl->next = next; 07764 else 07765 contexts = next; 07766 /* Okay, now we're safe to let it go -- in a sense, we were 07767 ready to let it go as soon as we locked it. */ 07768 ast_unlock_context(tmp); 07769 __ast_internal_context_destroy(tmp); 07770 } else { 07771 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar, 07772 tmp->refcount, tmp->root); 07773 ast_unlock_context(tmp); 07774 next = tmp->next; 07775 tmpl = tmp; 07776 } 07777 } else if (con) { 07778 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar); 07779 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 07780 ast_hashtab_remove_this_object(contexttab, tmp); 07781 07782 next = tmp->next; 07783 if (tmpl) 07784 tmpl->next = next; 07785 else 07786 contexts = next; 07787 /* Okay, now we're safe to let it go -- in a sense, we were 07788 ready to let it go as soon as we locked it. */ 07789 ast_unlock_context(tmp); 07790 __ast_internal_context_destroy(tmp); 07791 } 07792 07793 /* if we have a specific match, we are done, otherwise continue */ 07794 tmp = con ? NULL : next; 07795 } 07796 }
int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
struct ast_module * | mod | |||
) |
Register a custom function.
Definition at line 2792 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().
02793 { 02794 struct ast_custom_function *cur; 02795 char tmps[80]; 02796 02797 if (!acf) 02798 return -1; 02799 02800 acf->mod = mod; 02801 02802 AST_RWLIST_WRLOCK(&acf_root); 02803 02804 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 02805 if (!strcmp(acf->name, cur->name)) { 02806 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 02807 AST_RWLIST_UNLOCK(&acf_root); 02808 return -1; 02809 } 02810 } 02811 02812 /* Store in alphabetical order */ 02813 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 02814 if (strcasecmp(acf->name, cur->name) < 0) { 02815 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 02816 break; 02817 } 02818 } 02819 AST_RWLIST_TRAVERSE_SAFE_END; 02820 if (!cur) 02821 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 02822 02823 AST_RWLIST_UNLOCK(&acf_root); 02824 02825 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 02826 02827 return 0; 02828 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 8879 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().
08880 { 08881 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 08882 08883 if (!chan) 08884 return -2; 08885 08886 if (context == NULL) 08887 context = chan->context; 08888 if (exten == NULL) 08889 exten = chan->exten; 08890 08891 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 08892 if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num)) 08893 return goto_func(chan, context, exten, priority); 08894 else 08895 return -3; 08896 }
static void __ast_internal_context_destroy | ( | struct ast_context * | con | ) | [static] |
Definition at line 7612 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().
07613 { 07614 struct ast_include *tmpi; 07615 struct ast_sw *sw; 07616 struct ast_exten *e, *el, *en; 07617 struct ast_ignorepat *ipi; 07618 struct ast_context *tmp = con; 07619 07620 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 07621 struct ast_include *tmpil = tmpi; 07622 tmpi = tmpi->next; 07623 ast_free(tmpil); 07624 } 07625 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 07626 struct ast_ignorepat *ipl = ipi; 07627 ipi = ipi->next; 07628 ast_free(ipl); 07629 } 07630 if (tmp->registrar) 07631 ast_free(tmp->registrar); 07632 07633 /* destroy the hash tabs */ 07634 if (tmp->root_table) { 07635 ast_hashtab_destroy(tmp->root_table, 0); 07636 } 07637 /* and destroy the pattern tree */ 07638 if (tmp->pattern_tree) 07639 destroy_pattern_tree(tmp->pattern_tree); 07640 07641 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 07642 ast_free(sw); 07643 for (e = tmp->root; e;) { 07644 for (en = e->peer; en;) { 07645 el = en; 07646 en = en->peer; 07647 destroy_exten(el); 07648 } 07649 el = e; 07650 e = e->next; 07651 destroy_exten(el); 07652 } 07653 tmp->root = NULL; 07654 ast_rwlock_destroy(&tmp->lock); 07655 ast_free(tmp); 07656 }
static enum ast_pbx_result __ast_pbx_run | ( | struct ast_channel * | c, | |
struct ast_pbx_args * | args | |||
) | [static] |
Definition at line 3691 of file pbx.c.
References ast_channel::_softhangup, ast_calloc, 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::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().
03693 { 03694 int found = 0; /* set if we find at least one match */ 03695 int res = 0; 03696 int autoloopflag; 03697 int error = 0; /* set an error conditions */ 03698 03699 /* A little initial setup here */ 03700 if (c->pbx) { 03701 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 03702 /* XXX and now what ? */ 03703 ast_free(c->pbx); 03704 } 03705 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 03706 return -1; 03707 /* Set reasonable defaults */ 03708 c->pbx->rtimeoutms = 10000; 03709 c->pbx->dtimeoutms = 5000; 03710 03711 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 03712 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 03713 03714 /* Start by trying whatever the channel is set to */ 03715 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 03716 /* If not successful fall back to 's' */ 03717 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); 03718 /* XXX the original code used the existing priority in the call to 03719 * ast_exists_extension(), and reset it to 1 afterwards. 03720 * I believe the correct thing is to set it to 1 immediately. 03721 */ 03722 set_ext_pri(c, "s", 1); 03723 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 03724 /* JK02: And finally back to default if everything else failed */ 03725 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); 03726 ast_copy_string(c->context, "default", sizeof(c->context)); 03727 } 03728 } 03729 for (;;) { 03730 char dst_exten[256]; /* buffer to accumulate digits */ 03731 int pos = 0; /* XXX should check bounds */ 03732 int digit = 0; 03733 int invalid = 0; 03734 int timeout = 0; 03735 03736 /* loop on priorities in this context/exten */ 03737 while ( !(res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found,1))) { 03738 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) { 03739 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */ 03740 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 03741 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 03742 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 03743 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03744 pbx_builtin_raise_exception(c, "ABSOLUTETIMEOUT"); 03745 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 03746 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 03747 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 03748 } else if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 03749 c->_softhangup = 0; 03750 continue; 03751 } else if (ast_check_hangup(c)) { 03752 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n", 03753 c->exten, c->priority); 03754 error = 1; 03755 break; 03756 } 03757 c->priority++; 03758 } /* end while - from here on we can use 'break' to go out */ 03759 if (found && res) { 03760 /* Something bad happened, or a hangup has been requested. */ 03761 if (strchr("0123456789ABCDEF*#", res)) { 03762 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res); 03763 pos = 0; 03764 dst_exten[pos++] = digit = res; 03765 dst_exten[pos] = '\0'; 03766 } else if (res == AST_PBX_INCOMPLETE) { 03767 ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 03768 ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 03769 03770 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */ 03771 if (!ast_matchmore_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 03772 invalid = 1; 03773 } else { 03774 ast_copy_string(dst_exten, c->exten, sizeof(dst_exten)); 03775 digit = 1; 03776 pos = strlen(dst_exten); 03777 } 03778 } else { 03779 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 03780 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 03781 03782 if ((res == AST_PBX_ERROR) && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03783 /* if we are already on the 'e' exten, don't jump to it again */ 03784 if (!strcmp(c->exten, "e")) { 03785 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); 03786 error = 1; 03787 } else { 03788 pbx_builtin_raise_exception(c, "ERROR"); 03789 continue; 03790 } 03791 } 03792 03793 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 03794 c->_softhangup = 0; 03795 continue; 03796 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) { 03797 set_ext_pri(c, "T", 1); 03798 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 03799 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 03800 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 03801 continue; 03802 } else { 03803 if (c->cdr) 03804 ast_cdr_update(c); 03805 error = 1; 03806 break; 03807 } 03808 } 03809 } 03810 if (error) 03811 break; 03812 03813 /*!\note 03814 * We get here on a failure of some kind: non-existing extension or 03815 * hangup. We have options, here. We can either catch the failure 03816 * and continue, or we can drop out entirely. */ 03817 03818 if (invalid || !ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) { 03819 /*!\note 03820 * If there is no match at priority 1, it is not a valid extension anymore. 03821 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if 03822 * neither exist. 03823 */ 03824 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 03825 ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 03826 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 03827 set_ext_pri(c, "i", 1); 03828 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03829 pbx_builtin_raise_exception(c, "INVALID"); 03830 } else { 03831 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 03832 c->name, c->exten, c->context); 03833 error = 1; /* we know what to do with it */ 03834 break; 03835 } 03836 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 03837 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 03838 c->_softhangup = 0; 03839 } else { /* keypress received, get more digits for a full extension */ 03840 int waittime = 0; 03841 if (digit) 03842 waittime = c->pbx->dtimeoutms; 03843 else if (!autofallthrough) 03844 waittime = c->pbx->rtimeoutms; 03845 if (!waittime) { 03846 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 03847 if (!status) 03848 status = "UNKNOWN"; 03849 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 03850 if (!strcasecmp(status, "CONGESTION")) 03851 res = pbx_builtin_congestion(c, "10"); 03852 else if (!strcasecmp(status, "CHANUNAVAIL")) 03853 res = pbx_builtin_congestion(c, "10"); 03854 else if (!strcasecmp(status, "BUSY")) 03855 res = pbx_builtin_busy(c, "10"); 03856 error = 1; /* XXX disable message */ 03857 break; /* exit from the 'for' loop */ 03858 } 03859 03860 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 03861 break; 03862 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos])) 03863 timeout = 1; 03864 if (!timeout && ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */ 03865 set_ext_pri(c, dst_exten, 1); 03866 else { 03867 /* No such extension */ 03868 if (!timeout && !ast_strlen_zero(dst_exten)) { 03869 /* An invalid extension */ 03870 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 03871 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 03872 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 03873 set_ext_pri(c, "i", 1); 03874 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03875 pbx_builtin_raise_exception(c, "INVALID"); 03876 } else { 03877 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context); 03878 found = 1; /* XXX disable message */ 03879 break; 03880 } 03881 } else { 03882 /* A simple timeout */ 03883 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) { 03884 ast_verb(3, "Timeout on %s\n", c->name); 03885 set_ext_pri(c, "t", 1); 03886 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03887 pbx_builtin_raise_exception(c, "RESPONSETIMEOUT"); 03888 } else { 03889 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); 03890 found = 1; /* XXX disable message */ 03891 break; 03892 } 03893 } 03894 } 03895 if (c->cdr) { 03896 ast_verb(2, "CDR updated on %s\n",c->name); 03897 ast_cdr_update(c); 03898 } 03899 } 03900 } 03901 03902 if (!found && !error) { 03903 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 03904 } 03905 03906 if (!args || !args->no_hangup_chan) { 03907 ast_softhangup(c, c->hangupcause ? c->hangupcause : AST_CAUSE_NORMAL_CLEARING); 03908 } 03909 03910 if ((!args || !args->no_hangup_chan) && 03911 !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) && 03912 ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) { 03913 set_ext_pri(c, "h", 1); 03914 if (c->cdr && ast_opt_end_cdr_before_h_exten) { 03915 ast_cdr_end(c->cdr); 03916 } 03917 while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found, 1)) == 0) { 03918 c->priority++; 03919 } 03920 if (found && res) { 03921 /* Something bad happened, or a hangup has been requested. */ 03922 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 03923 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 03924 } 03925 } 03926 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 03927 ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */ 03928 pbx_destroy(c->pbx); 03929 c->pbx = NULL; 03930 03931 if (!args || !args->no_hangup_chan) { 03932 ast_hangup(c); 03933 } 03934 03935 return 0; 03936 }
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 1808 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, LOG_NOTICE, and LOG_WARNING.
Referenced by extension_match_core().
01809 { 01810 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 01811 01812 #ifdef NEED_DEBUG_HERE 01813 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode); 01814 #endif 01815 01816 if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */ 01817 #ifdef NEED_DEBUG_HERE 01818 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n"); 01819 #endif 01820 return 1; 01821 } 01822 01823 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 01824 int ld = strlen(data), lp = strlen(pattern); 01825 01826 if (lp < ld) { /* pattern too short, cannot match */ 01827 #ifdef NEED_DEBUG_HERE 01828 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n"); 01829 #endif 01830 return 0; 01831 } 01832 /* depending on the mode, accept full or partial match or both */ 01833 if (mode == E_MATCH) { 01834 #ifdef NEED_DEBUG_HERE 01835 ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data); 01836 #endif 01837 return !strcmp(pattern, data); /* 1 on match, 0 on fail */ 01838 } 01839 if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */ 01840 #ifdef NEED_DEBUG_HERE 01841 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld); 01842 #endif 01843 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 01844 } else { 01845 #ifdef NEED_DEBUG_HERE 01846 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data); 01847 #endif 01848 return 0; 01849 } 01850 } 01851 pattern++; /* skip leading _ */ 01852 /* 01853 * XXX below we stop at '/' which is a separator for the CID info. However we should 01854 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 01855 */ 01856 while (*data && *pattern && *pattern != '/') { 01857 const char *end; 01858 01859 if (*data == '-') { /* skip '-' in data (just a separator) */ 01860 data++; 01861 continue; 01862 } 01863 switch (toupper(*pattern)) { 01864 case '[': /* a range */ 01865 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */ 01866 if (end == NULL) { 01867 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 01868 return 0; /* unconditional failure */ 01869 } 01870 for (pattern++; pattern != end; pattern++) { 01871 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 01872 if (*data >= pattern[0] && *data <= pattern[2]) 01873 break; /* match found */ 01874 else { 01875 pattern += 2; /* skip a total of 3 chars */ 01876 continue; 01877 } 01878 } else if (*data == pattern[0]) 01879 break; /* match found */ 01880 } 01881 if (pattern == end) { 01882 #ifdef NEED_DEBUG_HERE 01883 ast_log(LOG_NOTICE,"return (0) when pattern==end\n"); 01884 #endif 01885 return 0; 01886 } 01887 pattern = end; /* skip and continue */ 01888 break; 01889 case 'N': 01890 if (*data < '2' || *data > '9') { 01891 #ifdef NEED_DEBUG_HERE 01892 ast_log(LOG_NOTICE,"return (0) N is matched\n"); 01893 #endif 01894 return 0; 01895 } 01896 break; 01897 case 'X': 01898 if (*data < '0' || *data > '9') { 01899 #ifdef NEED_DEBUG_HERE 01900 ast_log(LOG_NOTICE,"return (0) X is matched\n"); 01901 #endif 01902 return 0; 01903 } 01904 break; 01905 case 'Z': 01906 if (*data < '1' || *data > '9') { 01907 #ifdef NEED_DEBUG_HERE 01908 ast_log(LOG_NOTICE,"return (0) Z is matched\n"); 01909 #endif 01910 return 0; 01911 } 01912 break; 01913 case '.': /* Must match, even with more digits */ 01914 #ifdef NEED_DEBUG_HERE 01915 ast_log(LOG_NOTICE,"return (1) when '.' is matched\n"); 01916 #endif 01917 return 1; 01918 case '!': /* Early match */ 01919 #ifdef NEED_DEBUG_HERE 01920 ast_log(LOG_NOTICE,"return (2) when '!' is matched\n"); 01921 #endif 01922 return 2; 01923 case ' ': 01924 case '-': /* Ignore these in patterns */ 01925 data--; /* compensate the final data++ */ 01926 break; 01927 default: 01928 if (*data != *pattern) { 01929 #ifdef NEED_DEBUG_HERE 01930 ast_log(LOG_NOTICE,"return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern); 01931 #endif 01932 return 0; 01933 } 01934 01935 } 01936 data++; 01937 pattern++; 01938 } 01939 if (*data) /* data longer than pattern, no match */ { 01940 #ifdef NEED_DEBUG_HERE 01941 ast_log(LOG_NOTICE,"return (0) when data longer than pattern\n"); 01942 #endif 01943 return 0; 01944 } 01945 01946 /* 01947 * match so far, but ran off the end of the data. 01948 * Depending on what is next, determine match or not. 01949 */ 01950 if (*pattern == '\0' || *pattern == '/') { /* exact match */ 01951 #ifdef NEED_DEBUG_HERE 01952 ast_log(LOG_NOTICE,"at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1); 01953 #endif 01954 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 01955 } else if (*pattern == '!') { /* early match */ 01956 #ifdef NEED_DEBUG_HERE 01957 ast_log(LOG_NOTICE,"at end, return (2) when '!' is matched\n"); 01958 #endif 01959 return 2; 01960 } else { /* partial match */ 01961 #ifdef NEED_DEBUG_HERE 01962 ast_log(LOG_NOTICE,"at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1); 01963 #endif 01964 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 01965 } 01966 }
static int acf_exception_read | ( | struct ast_channel * | chan, | |
const char * | name, | |||
char * | data, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 2609 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.
02610 { 02611 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 02612 struct pbx_exception *exception = NULL; 02613 if (!ds || !ds->data) 02614 return -1; 02615 exception = ds->data; 02616 if (!strcasecmp(data, "REASON")) 02617 ast_copy_string(buf, exception->reason, buflen); 02618 else if (!strcasecmp(data, "CONTEXT")) 02619 ast_copy_string(buf, exception->context, buflen); 02620 else if (!strncasecmp(data, "EXTEN", 5)) 02621 ast_copy_string(buf, exception->exten, buflen); 02622 else if (!strcasecmp(data, "PRIORITY")) 02623 snprintf(buf, buflen, "%d", exception->priority); 02624 else 02625 return -1; 02626 return 0; 02627 }
static struct match_char * add_exten_to_pattern_tree | ( | struct ast_context * | con, | |
struct ast_exten * | e1, | |||
int | findonly | |||
) | [static] |
Definition at line 1475 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().
01476 { 01477 struct match_char *m1 = NULL, *m2 = NULL, **m0; 01478 int specif; 01479 int already; 01480 int pattern = 0; 01481 char buf[256]; 01482 char extenbuf[512]; 01483 char *s1 = extenbuf; 01484 int l1 = strlen(e1->exten) + strlen(e1->cidmatch) + 2; 01485 01486 01487 ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf)); 01488 01489 if (e1->matchcid && l1 <= sizeof(extenbuf)) { 01490 strcat(extenbuf,"/"); 01491 strcat(extenbuf,e1->cidmatch); 01492 } else if (l1 > sizeof(extenbuf)) { 01493 ast_log(LOG_ERROR,"The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", e1->exten, e1->cidmatch); 01494 return 0; 01495 } 01496 #ifdef NEED_DEBUG 01497 ast_log(LOG_DEBUG,"Adding exten %s%c%s to tree\n", s1, e1->matchcid? '/':' ', e1->matchcid? e1->cidmatch : ""); 01498 #endif 01499 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */ 01500 m0 = &con->pattern_tree; 01501 already = 1; 01502 01503 if ( *s1 == '_') { 01504 pattern = 1; 01505 s1++; 01506 } 01507 while( *s1 ) { 01508 if (pattern && *s1 == '[' && *(s1-1) != '\\') { 01509 char *s2 = buf; 01510 buf[0] = 0; 01511 s1++; /* get past the '[' */ 01512 while (*s1 != ']' && *(s1-1) != '\\' ) { 01513 if (*s1 == '\\') { 01514 if (*(s1+1) == ']') { 01515 *s2++ = ']'; 01516 s1++;s1++; 01517 } else 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 } 01527 } else if (*s1 == '-') { /* remember to add some error checking to all this! */ 01528 char s3 = *(s1-1); 01529 char s4 = *(s1+1); 01530 for (s3++; s3 <= s4; s3++) { 01531 *s2++ = s3; 01532 } 01533 s1++; s1++; 01534 } else if (*s1 == '\0') { 01535 ast_log(LOG_WARNING, "A matching ']' was not found for '[' in pattern string '%s'\n", extenbuf); 01536 break; 01537 } else { 01538 *s2++ = *s1++; 01539 } 01540 } 01541 *s2 = 0; /* null terminate the exploded range */ 01542 /* sort the characters */ 01543 01544 specif = strlen(buf); 01545 qsort(buf, specif, 1, compare_char); 01546 specif <<= 8; 01547 specif += buf[0]; 01548 } else { 01549 01550 if (*s1 == '\\') { 01551 s1++; 01552 buf[0] = *s1; 01553 } else { 01554 if (pattern) { 01555 if (*s1 == 'n') /* make sure n,x,z patterns are canonicalized to N,X,Z */ 01556 *s1 = 'N'; 01557 else if (*s1 == 'x') 01558 *s1 = 'X'; 01559 else if (*s1 == 'z') 01560 *s1 = 'Z'; 01561 } 01562 buf[0] = *s1; 01563 } 01564 buf[1] = 0; 01565 specif = 1; 01566 } 01567 m2 = 0; 01568 if (already && (m2=already_in_tree(m1,buf)) && m2->next_char) { 01569 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... 01570 a shorter pattern might win if the longer one doesn't match */ 01571 m2->exten = e1; 01572 m2->deleted = 0; 01573 } 01574 m1 = m2->next_char; /* m1 points to the node to compare against */ 01575 m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */ 01576 } else { /* not already OR not m2 OR nor m2->next_char */ 01577 if (m2) { 01578 if (findonly) 01579 return m2; 01580 m1 = m2; /* while m0 stays the same */ 01581 } else { 01582 if (findonly) 01583 return m1; 01584 m1 = add_pattern_node(con, m1, buf, pattern, already,specif, m0); /* m1 is the node just added */ 01585 m0 = &m1->next_char; 01586 } 01587 01588 if (!(*(s1+1))) { 01589 m1->deleted = 0; 01590 m1->exten = e1; 01591 } 01592 01593 already = 0; 01594 } 01595 s1++; /* advance to next char */ 01596 } 01597 return m1; 01598 }
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 1434 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().
01435 { 01436 struct match_char *m; 01437 01438 if (!(m = ast_calloc(1, sizeof(*m)))) 01439 return NULL; 01440 01441 if (!(m->x = ast_strdup(pattern))) { 01442 ast_free(m); 01443 return NULL; 01444 } 01445 01446 /* the specificity scores are the same as used in the old 01447 pattern matcher. */ 01448 m->is_pattern = is_pattern; 01449 if (specificity == 1 && is_pattern && pattern[0] == 'N') 01450 m->specificity = 0x0802; 01451 else if (specificity == 1 && is_pattern && pattern[0] == 'Z') 01452 m->specificity = 0x0901; 01453 else if (specificity == 1 && is_pattern && pattern[0] == 'X') 01454 m->specificity = 0x0a00; 01455 else if (specificity == 1 && is_pattern && pattern[0] == '.') 01456 m->specificity = 0x10000; 01457 else if (specificity == 1 && is_pattern && pattern[0] == '!') 01458 m->specificity = 0x20000; 01459 else 01460 m->specificity = specificity; 01461 01462 if (!con->pattern_tree) { 01463 insert_in_next_chars_alt_char_list(&con->pattern_tree, m); 01464 } else { 01465 if (already) { /* switch to the new regime (traversing vs appending)*/ 01466 insert_in_next_chars_alt_char_list(nextcharptr, m); 01467 } else { 01468 insert_in_next_chars_alt_char_list(¤t->next_char, m); 01469 } 01470 } 01471 01472 return m; 01473 }
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 6825 of file pbx.c.
References add_pri_lockopt(), and el.
Referenced by ast_add_extension2_lockopt().
06827 { 06828 return add_pri_lockopt(con, tmp, el, e, replace, 1); 06829 }
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 6836 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().
06838 { 06839 struct ast_exten *ep; 06840 struct ast_exten *eh=e; 06841 06842 for (ep = NULL; e ; ep = e, e = e->peer) { 06843 if (e->priority >= tmp->priority) 06844 break; 06845 } 06846 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 06847 ast_hashtab_insert_safe(eh->peer_table, tmp); 06848 06849 if (tmp->label) { 06850 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 06851 } 06852 ep->peer = tmp; 06853 return 0; /* success */ 06854 } 06855 if (e->priority == tmp->priority) { 06856 /* Can't have something exactly the same. Is this a 06857 replacement? If so, replace, otherwise, bonk. */ 06858 if (!replace) { 06859 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 06860 if (tmp->datad) { 06861 tmp->datad(tmp->data); 06862 /* if you free this, null it out */ 06863 tmp->data = NULL; 06864 } 06865 06866 ast_free(tmp); 06867 return -1; 06868 } 06869 /* we are replacing e, so copy the link fields and then update 06870 * whoever pointed to e to point to us 06871 */ 06872 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 06873 tmp->peer = e->peer; /* always meaningful */ 06874 if (ep) { /* We're in the peer list, just insert ourselves */ 06875 ast_hashtab_remove_object_via_lookup(eh->peer_table,e); 06876 06877 if (e->label) { 06878 ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e); 06879 } 06880 06881 ast_hashtab_insert_safe(eh->peer_table,tmp); 06882 if (tmp->label) { 06883 ast_hashtab_insert_safe(eh->peer_label_table,tmp); 06884 } 06885 06886 ep->peer = tmp; 06887 } else if (el) { /* We're the first extension. Take over e's functions */ 06888 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 06889 tmp->peer_table = e->peer_table; 06890 tmp->peer_label_table = e->peer_label_table; 06891 ast_hashtab_remove_object_via_lookup(tmp->peer_table,e); 06892 ast_hashtab_insert_safe(tmp->peer_table,tmp); 06893 if (e->label) { 06894 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 06895 } 06896 if (tmp->label) { 06897 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 06898 } 06899 06900 ast_hashtab_remove_object_via_lookup(con->root_table, e); 06901 ast_hashtab_insert_safe(con->root_table, tmp); 06902 el->next = tmp; 06903 /* The pattern trie points to this exten; replace the pointer, 06904 and all will be well */ 06905 if (x) { /* if the trie isn't formed yet, don't sweat this */ 06906 if (x->exten) { /* this test for safety purposes */ 06907 x->exten = tmp; /* replace what would become a bad pointer */ 06908 } else { 06909 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 06910 } 06911 } 06912 } else { /* We're the very first extension. */ 06913 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 06914 ast_hashtab_remove_object_via_lookup(con->root_table, e); 06915 ast_hashtab_insert_safe(con->root_table, tmp); 06916 tmp->peer_table = e->peer_table; 06917 tmp->peer_label_table = e->peer_label_table; 06918 ast_hashtab_remove_object_via_lookup(tmp->peer_table, e); 06919 ast_hashtab_insert_safe(tmp->peer_table, tmp); 06920 if (e->label) { 06921 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 06922 } 06923 if (tmp->label) { 06924 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 06925 } 06926 06927 ast_hashtab_remove_object_via_lookup(con->root_table, e); 06928 ast_hashtab_insert_safe(con->root_table, tmp); 06929 con->root = tmp; 06930 /* The pattern trie points to this exten; replace the pointer, 06931 and all will be well */ 06932 if (x) { /* if the trie isn't formed yet; no problem */ 06933 if (x->exten) { /* this test for safety purposes */ 06934 x->exten = tmp; /* replace what would become a bad pointer */ 06935 } else { 06936 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 06937 } 06938 } 06939 } 06940 if (tmp->priority == PRIORITY_HINT) 06941 ast_change_hint(e,tmp); 06942 /* Destroy the old one */ 06943 if (e->datad) 06944 e->datad(e->data); 06945 ast_free(e); 06946 } else { /* Slip ourselves in just before e */ 06947 tmp->peer = e; 06948 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 06949 if (ep) { /* Easy enough, we're just in the peer list */ 06950 if (tmp->label) { 06951 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 06952 } 06953 ast_hashtab_insert_safe(eh->peer_table, tmp); 06954 ep->peer = tmp; 06955 } else { /* we are the first in some peer list, so link in the ext list */ 06956 tmp->peer_table = e->peer_table; 06957 tmp->peer_label_table = e->peer_label_table; 06958 e->peer_table = 0; 06959 e->peer_label_table = 0; 06960 ast_hashtab_insert_safe(tmp->peer_table, tmp); 06961 if (tmp->label) { 06962 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 06963 } 06964 ast_hashtab_remove_object_via_lookup(con->root_table, e); 06965 ast_hashtab_insert_safe(con->root_table, tmp); 06966 if (el) 06967 el->next = tmp; /* in the middle... */ 06968 else 06969 con->root = tmp; /* ... or at the head */ 06970 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 06971 } 06972 /* And immediately return success. */ 06973 if (tmp->priority == PRIORITY_HINT) { 06974 if (lockhints) { 06975 ast_add_hint(tmp); 06976 } else { 06977 ast_add_hint_nolock(tmp); 06978 } 06979 } 06980 } 06981 return 0; 06982 }
static struct match_char * already_in_tree | ( | struct match_char * | current, | |
char * | pat | |||
) | [static] |
Definition at line 1382 of file pbx.c.
References match_char::alt_char, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01383 { 01384 struct match_char *t; 01385 01386 if (!current) 01387 return 0; 01388 01389 for (t = current; t; t = t->alt_char) { 01390 if (!strcmp(pat, t->x)) /* uh, we may want to sort exploded [] contents to make matching easy */ 01391 return t; 01392 } 01393 01394 return 0; 01395 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 4074 of file pbx.c.
References countcalls.
Referenced by handle_chanlist(), handle_showcalls(), and sysinfo_helper().
04075 { 04076 return countcalls; 04077 }
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 6691 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().
06694 { 06695 int ret = -1; 06696 struct ast_context *c = find_context_locked(context); 06697 06698 if (c) { 06699 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 06700 application, data, datad, registrar); 06701 ast_unlock_contexts(); 06702 } 06703 06704 return ret; 06705 }
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 7009 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().
07013 { 07014 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1); 07015 }
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 7022 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().
07026 { 07027 /* 07028 * Sort extensions (or patterns) according to the rules indicated above. 07029 * These are implemented by the function ext_cmp()). 07030 * All priorities for the same ext/pattern/cid are kept in a list, 07031 * using the 'peer' field as a link field.. 07032 */ 07033 struct ast_exten *tmp, *tmp2, *e, *el = NULL; 07034 int res; 07035 int length; 07036 char *p; 07037 char expand_buf[VAR_BUF_SIZE]; 07038 struct ast_exten dummy_exten = {0}; 07039 char dummy_name[1024]; 07040 07041 if (ast_strlen_zero(extension)) { 07042 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", 07043 con->name); 07044 return -1; 07045 } 07046 07047 /* If we are adding a hint evalulate in variables and global variables */ 07048 if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) { 07049 struct ast_channel c = {0, }; 07050 07051 ast_copy_string(c.exten, extension, sizeof(c.exten)); 07052 ast_copy_string(c.context, con->name, sizeof(c.context)); 07053 pbx_substitute_variables_helper(&c, application, expand_buf, sizeof(expand_buf)); 07054 application = expand_buf; 07055 } 07056 07057 length = sizeof(struct ast_exten); 07058 length += strlen(extension) + 1; 07059 length += strlen(application) + 1; 07060 if (label) 07061 length += strlen(label) + 1; 07062 if (callerid) 07063 length += strlen(callerid) + 1; 07064 else 07065 length ++; /* just the '\0' */ 07066 07067 /* Be optimistic: Build the extension structure first */ 07068 if (!(tmp = ast_calloc(1, length))) 07069 return -1; 07070 07071 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */ 07072 label = 0; 07073 07074 /* use p as dst in assignments, as the fields are const char * */ 07075 p = tmp->stuff; 07076 if (label) { 07077 tmp->label = p; 07078 strcpy(p, label); 07079 p += strlen(label) + 1; 07080 } 07081 tmp->exten = p; 07082 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 07083 tmp->priority = priority; 07084 tmp->cidmatch = p; /* but use p for assignments below */ 07085 if (!ast_strlen_zero(callerid)) { 07086 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 07087 tmp->matchcid = 1; 07088 } else { 07089 *p++ = '\0'; 07090 tmp->matchcid = 0; 07091 } 07092 tmp->app = p; 07093 strcpy(p, application); 07094 tmp->parent = con; 07095 tmp->data = data; 07096 tmp->datad = datad; 07097 tmp->registrar = registrar; 07098 07099 if (lockconts) { 07100 ast_wrlock_context(con); 07101 } 07102 07103 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding 07104 an extension, and the trie exists, then we need to incrementally add this pattern to it. */ 07105 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 07106 dummy_exten.exten = dummy_name; 07107 dummy_exten.matchcid = 0; 07108 dummy_exten.cidmatch = 0; 07109 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten); 07110 if (!tmp2) { 07111 /* hmmm, not in the trie; */ 07112 add_exten_to_pattern_tree(con, tmp, 0); 07113 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */ 07114 } 07115 } 07116 res = 0; /* some compilers will think it is uninitialized otherwise */ 07117 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 07118 res = ext_cmp(e->exten, tmp->exten); 07119 if (res == 0) { /* extension match, now look at cidmatch */ 07120 if (!e->matchcid && !tmp->matchcid) 07121 res = 0; 07122 else if (tmp->matchcid && !e->matchcid) 07123 res = 1; 07124 else if (e->matchcid && !tmp->matchcid) 07125 res = -1; 07126 else 07127 res = strcasecmp(e->cidmatch, tmp->cidmatch); 07128 } 07129 if (res >= 0) 07130 break; 07131 } 07132 if (e && res == 0) { /* exact match, insert in the pri chain */ 07133 res = add_pri(con, tmp, el, e, replace); 07134 if (lockconts) { 07135 ast_unlock_context(con); 07136 } 07137 if (res < 0) { 07138 errno = EEXIST; /* XXX do we care ? */ 07139 return 0; /* XXX should we return -1 maybe ? */ 07140 } 07141 } else { 07142 /* 07143 * not an exact match, this is the first entry with this pattern, 07144 * so insert in the main list right before 'e' (if any) 07145 */ 07146 tmp->next = e; 07147 if (el) { /* there is another exten already in this context */ 07148 el->next = tmp; 07149 tmp->peer_table = ast_hashtab_create(13, 07150 hashtab_compare_exten_numbers, 07151 ast_hashtab_resize_java, 07152 ast_hashtab_newsize_java, 07153 hashtab_hash_priority, 07154 0); 07155 tmp->peer_label_table = ast_hashtab_create(7, 07156 hashtab_compare_exten_labels, 07157 ast_hashtab_resize_java, 07158 ast_hashtab_newsize_java, 07159 hashtab_hash_labels, 07160 0); 07161 if (label) { 07162 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 07163 } 07164 ast_hashtab_insert_safe(tmp->peer_table, tmp); 07165 } else { /* this is the first exten in this context */ 07166 if (!con->root_table) 07167 con->root_table = ast_hashtab_create(27, 07168 hashtab_compare_extens, 07169 ast_hashtab_resize_java, 07170 ast_hashtab_newsize_java, 07171 hashtab_hash_extens, 07172 0); 07173 con->root = tmp; 07174 con->root->peer_table = ast_hashtab_create(13, 07175 hashtab_compare_exten_numbers, 07176 ast_hashtab_resize_java, 07177 ast_hashtab_newsize_java, 07178 hashtab_hash_priority, 07179 0); 07180 con->root->peer_label_table = ast_hashtab_create(7, 07181 hashtab_compare_exten_labels, 07182 ast_hashtab_resize_java, 07183 ast_hashtab_newsize_java, 07184 hashtab_hash_labels, 07185 0); 07186 if (label) { 07187 ast_hashtab_insert_safe(con->root->peer_label_table, tmp); 07188 } 07189 ast_hashtab_insert_safe(con->root->peer_table, tmp); 07190 07191 } 07192 ast_hashtab_insert_safe(con->root_table, tmp); 07193 if (lockconts) { 07194 ast_unlock_context(con); 07195 } 07196 if (tmp->priority == PRIORITY_HINT) { 07197 if (lockhints) { 07198 ast_add_hint(tmp); 07199 } else { 07200 ast_add_hint_nolock(tmp); 07201 } 07202 } 07203 } 07204 if (option_debug) { 07205 if (tmp->matchcid) { 07206 ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 07207 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 07208 } else { 07209 ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n", 07210 tmp->exten, tmp->priority, con->name, con); 07211 } 07212 } 07213 07214 if (tmp->matchcid) { 07215 ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 07216 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 07217 } else { 07218 ast_verb(3, "Added extension '%s' priority %d to %s (%p)\n", 07219 tmp->exten, tmp->priority, con->name, con); 07220 } 07221 07222 return 0; 07223 }
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 6672 of file pbx.c.
References ast_add_extension2_lockopt(), and find_context().
Referenced by ast_merge_contexts_and_delete().
06675 { 06676 int ret = -1; 06677 struct ast_context *c = find_context(context); 06678 06679 if (c) { 06680 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid, 06681 application, data, datad, registrar, 0, 0); 06682 } 06683 06684 return ret; 06685 }
static int ast_add_hint | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state.
Definition at line 3538 of file pbx.c.
References ast_add_hint_nolock(), AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by ast_add_extension2_lockopt().
03539 { 03540 int ret; 03541 03542 AST_RWLIST_WRLOCK(&hints); 03543 ret = ast_add_hint_nolock(e); 03544 AST_RWLIST_UNLOCK(&hints); 03545 03546 return ret; 03547 }
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 3509 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().
03510 { 03511 struct ast_hint *hint; 03512 03513 if (!e) 03514 return -1; 03515 03516 /* Search if hint exists, do nothing */ 03517 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03518 if (hint->exten == e) { 03519 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 03520 return -1; 03521 } 03522 } 03523 03524 ast_debug(2, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 03525 03526 if (!(hint = ast_calloc(1, sizeof(*hint)))) { 03527 return -1; 03528 } 03529 /* Initialize and insert new item at the top */ 03530 hint->exten = e; 03531 hint->laststate = ast_extension_state2(e); 03532 AST_RWLIST_INSERT_HEAD(&hints, hint, list); 03533 03534 return 0; 03535 }
int ast_async_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6730 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(), and socket_process().
06731 { 06732 int res = 0; 06733 06734 ast_channel_lock(chan); 06735 06736 if (chan->pbx) { /* This channel is currently in the PBX */ 06737 ast_explicit_goto(chan, context, exten, priority + 1); 06738 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 06739 } else { 06740 /* In order to do it when the channel doesn't really exist within 06741 the PBX, we have to make a new channel, masquerade, and start the PBX 06742 at the new location */ 06743 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name); 06744 if (!tmpchan) { 06745 res = -1; 06746 } else { 06747 if (chan->cdr) { 06748 ast_cdr_discard(tmpchan->cdr); 06749 tmpchan->cdr = ast_cdr_dup(chan->cdr); /* share the love */ 06750 } 06751 /* Make formats okay */ 06752 tmpchan->readformat = chan->readformat; 06753 tmpchan->writeformat = chan->writeformat; 06754 /* Setup proper location */ 06755 ast_explicit_goto(tmpchan, 06756 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 06757 06758 /* Masquerade into temp channel */ 06759 if (ast_channel_masquerade(tmpchan, chan)) { 06760 /* Failed to set up the masquerade. It's probably chan_local 06761 * in the middle of optimizing itself out. Sad. :( */ 06762 ast_hangup(tmpchan); 06763 tmpchan = NULL; 06764 res = -1; 06765 } else { 06766 /* Grab the locks and get going */ 06767 ast_channel_lock(tmpchan); 06768 ast_do_masquerade(tmpchan); 06769 ast_channel_unlock(tmpchan); 06770 /* Start the PBX going on our stolen channel */ 06771 if (ast_pbx_start(tmpchan)) { 06772 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 06773 ast_hangup(tmpchan); 06774 res = -1; 06775 } 06776 } 06777 } 06778 } 06779 ast_channel_unlock(chan); 06780 return res; 06781 }
int ast_async_goto_by_name | ( | const char * | channame, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6783 of file pbx.c.
References ast_async_goto(), ast_channel_unlock, ast_get_channel_by_name_locked(), and chan.
06784 { 06785 struct ast_channel *chan; 06786 int res = -1; 06787 06788 chan = ast_get_channel_by_name_locked(channame); 06789 if (chan) { 06790 res = ast_async_goto(chan, context, exten, priority); 06791 ast_channel_unlock(chan); 06792 } 06793 return res; 06794 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8903 of file pbx.c.
References __ast_goto_if_exists(), and chan.
08904 { 08905 return __ast_goto_if_exists(chan, context, exten, priority, 1); 08906 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 8966 of file pbx.c.
References chan, and pbx_parseable_goto().
Referenced by asyncgoto_exec().
08967 { 08968 return pbx_parseable_goto(chan, goto_string, 1); 08969 }
int ast_build_timing | ( | struct ast_timing * | i, | |
const char * | info_in | |||
) |
Definition at line 6351 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().
06352 { 06353 char info_save[256]; 06354 char *info; 06355 06356 /* Check for empty just in case */ 06357 if (ast_strlen_zero(info_in)) 06358 return 0; 06359 /* make a copy just in case we were passed a static string */ 06360 ast_copy_string(info_save, info_in, sizeof(info_save)); 06361 info = info_save; 06362 /* Assume everything except time */ 06363 i->monthmask = 0xfff; /* 12 bits */ 06364 i->daymask = 0x7fffffffU; /* 31 bits */ 06365 i->dowmask = 0x7f; /* 7 bits */ 06366 /* on each call, use strsep() to move info to the next argument */ 06367 get_timerange(i, strsep(&info, "|,")); 06368 if (info) 06369 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 06370 if (info) 06371 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 06372 if (info) 06373 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 06374 return 1; 06375 }
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 3636 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by background_detect_exec(), cb_events(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), handle_link_data(), handle_link_phone_dtmf(), leave_voicemail(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), phone_check_exception(), skinny_ss(), ss_thread(), and valid_exit().
03637 { 03638 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 03639 }
Change hint for an extension.
Definition at line 3550 of file pbx.c.
References AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_hint::exten, and ast_hint::list.
03551 { 03552 struct ast_hint *hint; 03553 int res = -1; 03554 03555 AST_RWLIST_WRLOCK(&hints); 03556 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03557 if (hint->exten == oe) { 03558 hint->exten = ne; 03559 res = 0; 03560 break; 03561 } 03562 } 03563 AST_RWLIST_UNLOCK(&hints); 03564 03565 return res; 03566 }
int ast_check_timing | ( | const struct ast_timing * | i | ) |
Definition at line 6377 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().
06378 { 06379 struct ast_tm tm; 06380 struct timeval now = ast_tvnow(); 06381 06382 ast_localtime(&now, &tm, NULL); 06383 06384 /* If it's not the right month, return */ 06385 if (!(i->monthmask & (1 << tm.tm_mon))) 06386 return 0; 06387 06388 /* If it's not that time of the month.... */ 06389 /* Warning, tm_mday has range 1..31! */ 06390 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 06391 return 0; 06392 06393 /* If it's not the right day of the week */ 06394 if (!(i->dowmask & (1 << tm.tm_wday))) 06395 return 0; 06396 06397 /* Sanity check the hour just to be safe */ 06398 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 06399 ast_log(LOG_WARNING, "Insane time...\n"); 06400 return 0; 06401 } 06402 06403 /* Now the tough part, we calculate if it fits 06404 in the right time based on min/hour */ 06405 if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2)))) 06406 return 0; 06407 06408 /* If we got this far, then we're good */ 06409 return 1; 06410 }
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 6603 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
06604 { 06605 int ret = -1; 06606 struct ast_context *c = find_context_locked(context); 06607 06608 if (c) { 06609 ret = ast_context_add_ignorepat2(c, value, registrar); 06610 ast_unlock_contexts(); 06611 } 06612 return ret; 06613 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 6615 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().
06616 { 06617 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 06618 int length; 06619 char *pattern; 06620 length = sizeof(struct ast_ignorepat); 06621 length += strlen(value) + 1; 06622 if (!(ignorepat = ast_calloc(1, length))) 06623 return -1; 06624 /* The cast to char * is because we need to write the initial value. 06625 * The field is not supposed to be modified otherwise. Also, gcc 4.2 06626 * sees the cast as dereferencing a type-punned pointer and warns about 06627 * it. This is the workaround (we're telling gcc, yes, that's really 06628 * what we wanted to do). 06629 */ 06630 pattern = (char *) ignorepat->pattern; 06631 strcpy(pattern, value); 06632 ignorepat->next = NULL; 06633 ignorepat->registrar = registrar; 06634 ast_wrlock_context(con); 06635 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 06636 ignorepatl = ignorepatc; 06637 if (!strcasecmp(ignorepatc->pattern, value)) { 06638 /* Already there */ 06639 ast_unlock_context(con); 06640 errno = EEXIST; 06641 return -1; 06642 } 06643 } 06644 if (ignorepatl) 06645 ignorepatl->next = ignorepat; 06646 else 06647 con->ignorepats = ignorepat; 06648 ast_unlock_context(con); 06649 return 0; 06650 06651 }
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 6157 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
06158 { 06159 int ret = -1; 06160 struct ast_context *c = find_context_locked(context); 06161 06162 if (c) { 06163 ret = ast_context_add_include2(c, include, registrar); 06164 ast_unlock_contexts(); 06165 } 06166 return ret; 06167 }
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 6419 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().
06421 { 06422 struct ast_include *new_include; 06423 char *c; 06424 struct ast_include *i, *il = NULL; /* include, include_last */ 06425 int length; 06426 char *p; 06427 06428 length = sizeof(struct ast_include); 06429 length += 2 * (strlen(value) + 1); 06430 06431 /* allocate new include structure ... */ 06432 if (!(new_include = ast_calloc(1, length))) 06433 return -1; 06434 /* Fill in this structure. Use 'p' for assignments, as the fields 06435 * in the structure are 'const char *' 06436 */ 06437 p = new_include->stuff; 06438 new_include->name = p; 06439 strcpy(p, value); 06440 p += strlen(value) + 1; 06441 new_include->rname = p; 06442 strcpy(p, value); 06443 /* Strip off timing info, and process if it is there */ 06444 if ( (c = strchr(p, ',')) ) { 06445 *c++ = '\0'; 06446 new_include->hastime = ast_build_timing(&(new_include->timing), c); 06447 } 06448 new_include->next = NULL; 06449 new_include->registrar = registrar; 06450 06451 ast_wrlock_context(con); 06452 06453 /* ... go to last include and check if context is already included too... */ 06454 for (i = con->includes; i; i = i->next) { 06455 if (!strcasecmp(i->name, new_include->name)) { 06456 ast_free(new_include); 06457 ast_unlock_context(con); 06458 errno = EEXIST; 06459 return -1; 06460 } 06461 il = i; 06462 } 06463 06464 /* ... include new context into context list, unlock, return */ 06465 if (il) 06466 il->next = new_include; 06467 else 06468 con->includes = new_include; 06469 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 06470 06471 ast_unlock_context(con); 06472 06473 return 0; 06474 }
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 6481 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
06482 { 06483 int ret = -1; 06484 struct ast_context *c = find_context_locked(context); 06485 06486 if (c) { /* found, add switch to this context */ 06487 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 06488 ast_unlock_contexts(); 06489 } 06490 return ret; 06491 }
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 6500 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().
06502 { 06503 struct ast_sw *new_sw; 06504 struct ast_sw *i; 06505 int length; 06506 char *p; 06507 06508 length = sizeof(struct ast_sw); 06509 length += strlen(value) + 1; 06510 if (data) 06511 length += strlen(data); 06512 length++; 06513 06514 /* allocate new sw structure ... */ 06515 if (!(new_sw = ast_calloc(1, length))) 06516 return -1; 06517 /* ... fill in this structure ... */ 06518 p = new_sw->stuff; 06519 new_sw->name = p; 06520 strcpy(new_sw->name, value); 06521 p += strlen(value) + 1; 06522 new_sw->data = p; 06523 if (data) { 06524 strcpy(new_sw->data, data); 06525 p += strlen(data) + 1; 06526 } else { 06527 strcpy(new_sw->data, ""); 06528 p++; 06529 } 06530 new_sw->eval = eval; 06531 new_sw->registrar = registrar; 06532 06533 /* ... try to lock this context ... */ 06534 ast_wrlock_context(con); 06535 06536 /* ... go to last sw and check if context is already swd too... */ 06537 AST_LIST_TRAVERSE(&con->alts, i, list) { 06538 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 06539 ast_free(new_sw); 06540 ast_unlock_context(con); 06541 errno = EEXIST; 06542 return -1; 06543 } 06544 } 06545 06546 /* ... sw new context into context list, unlock, return */ 06547 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 06548 06549 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 06550 06551 ast_unlock_context(con); 06552 06553 return 0; 06554 }
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 7798 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().
07799 { 07800 ast_wrlock_contexts(); 07801 __ast_context_destroy(contexts, contexts_table, con,registrar); 07802 ast_unlock_contexts(); 07803 }
struct ast_context* ast_context_find | ( | const char * | name | ) |
Find a context.
name | name of the context to find |
Definition at line 2012 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().
02013 { 02014 struct ast_context *tmp = NULL; 02015 struct fake_context item; 02016 02017 ast_copy_string(item.name, name, sizeof(item.name)); 02018 02019 ast_rdlock_contexts(); 02020 if( contexts_table ) { 02021 tmp = ast_hashtab_lookup(contexts_table,&item); 02022 } else { 02023 while ( (tmp = ast_walk_contexts(tmp)) ) { 02024 if (!name || !strcasecmp(name, tmp->name)) 02025 break; 02026 } 02027 } 02028 ast_unlock_contexts(); 02029 return tmp; 02030 }
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 5814 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().
05815 { 05816 struct ast_context *tmp, **local_contexts; 05817 struct fake_context search; 05818 int length = sizeof(struct ast_context) + strlen(name) + 1; 05819 05820 if (!contexts_table) { 05821 contexts_table = ast_hashtab_create(17, 05822 ast_hashtab_compare_contexts, 05823 ast_hashtab_resize_java, 05824 ast_hashtab_newsize_java, 05825 ast_hashtab_hash_contexts, 05826 0); 05827 } 05828 05829 ast_copy_string(search.name, name, sizeof(search.name)); 05830 if (!extcontexts) { 05831 ast_rdlock_contexts(); 05832 local_contexts = &contexts; 05833 tmp = ast_hashtab_lookup(contexts_table, &search); 05834 ast_unlock_contexts(); 05835 if (tmp) { 05836 tmp->refcount++; 05837 return tmp; 05838 } 05839 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 05840 local_contexts = extcontexts; 05841 tmp = ast_hashtab_lookup(exttable, &search); 05842 if (tmp) { 05843 tmp->refcount++; 05844 return tmp; 05845 } 05846 } 05847 05848 if ((tmp = ast_calloc(1, length))) { 05849 ast_rwlock_init(&tmp->lock); 05850 ast_mutex_init(&tmp->macrolock); 05851 strcpy(tmp->name, name); 05852 tmp->root = NULL; 05853 tmp->root_table = NULL; 05854 tmp->registrar = ast_strdup(registrar); 05855 tmp->includes = NULL; 05856 tmp->ignorepats = NULL; 05857 tmp->refcount = 1; 05858 } else { 05859 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 05860 return NULL; 05861 } 05862 05863 if (!extcontexts) { 05864 ast_wrlock_contexts(); 05865 tmp->next = *local_contexts; 05866 *local_contexts = tmp; 05867 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 05868 ast_unlock_contexts(); 05869 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 05870 ast_verb(3, "Registered extension context '%s' (%p) in table %p; registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 05871 } else { 05872 tmp->next = *local_contexts; 05873 if (exttable) 05874 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 05875 05876 *local_contexts = tmp; 05877 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 05878 ast_verb(3, "Registered extension context '%s' (%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 05879 } 05880 return tmp; 05881 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 4461 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().
04462 { 04463 struct ast_context *c = NULL; 04464 int ret = -1; 04465 struct fake_context item; 04466 04467 ast_rdlock_contexts(); 04468 04469 ast_copy_string(item.name, context, sizeof(item.name)); 04470 04471 c = ast_hashtab_lookup(contexts_table,&item); 04472 if (c) 04473 ret = 0; 04474 04475 04476 #ifdef NOTNOW 04477 04478 while ((c = ast_walk_contexts(c))) { 04479 if (!strcmp(ast_get_context_name(c), context)) { 04480 ret = 0; 04481 break; 04482 } 04483 } 04484 04485 #endif 04486 ast_unlock_contexts(); 04487 04488 /* if we found context, lock macrolock */ 04489 if (ret == 0) 04490 ret = ast_mutex_lock(&c->macrolock); 04491 04492 return ret; 04493 }
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 4268 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), unregister_exten(), and UnregisterExtension().
04269 { 04270 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 04271 }
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 4295 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by manage_parkinglot(), park_exec_full(), and unload_module().
04296 { 04297 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 04298 }
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 4273 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().
04274 { 04275 int ret = -1; /* default error return */ 04276 struct ast_context *c = find_context_locked(context); 04277 04278 if (c) { /* ... remove extension ... */ 04279 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1); 04280 ast_unlock_contexts(); 04281 } 04282 return ret; 04283 }
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 4300 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().
04301 { 04302 struct ast_exten *exten, *prev_exten = NULL; 04303 struct ast_exten *peer; 04304 struct ast_exten ex, *exten2, *exten3; 04305 char dummy_name[1024]; 04306 struct ast_exten *previous_peer = NULL; 04307 struct ast_exten *next_peer = NULL; 04308 int found = 0; 04309 04310 if (!already_locked) 04311 ast_wrlock_context(con); 04312 04313 /* Handle this is in the new world */ 04314 04315 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 04316 * peers, not just those matching the callerid. */ 04317 #ifdef NEED_DEBUG 04318 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 04319 #endif 04320 #ifdef CONTEXT_DEBUG 04321 check_contexts(__FILE__, __LINE__); 04322 #endif 04323 /* find this particular extension */ 04324 ex.exten = dummy_name; 04325 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 04326 ex.cidmatch = callerid; 04327 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 04328 exten = ast_hashtab_lookup(con->root_table, &ex); 04329 if (exten) { 04330 if (priority == 0) { 04331 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 04332 if (!exten2) 04333 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); 04334 if (con->pattern_tree) { 04335 04336 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 04337 04338 if (x->exten) { /* this test for safety purposes */ 04339 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 04340 x->exten = 0; /* get rid of what will become a bad pointer */ 04341 } else { 04342 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 04343 } 04344 } 04345 } else { 04346 ex.priority = priority; 04347 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 04348 if (exten2) { 04349 04350 if (exten2->label) { /* if this exten has a label, remove that, too */ 04351 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 04352 if (!exten3) 04353 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); 04354 } 04355 04356 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 04357 if (!exten3) 04358 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); 04359 if (exten2 == exten && exten2->peer) { 04360 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 04361 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 04362 } 04363 if (ast_hashtab_size(exten->peer_table) == 0) { 04364 /* well, if the last priority of an exten is to be removed, 04365 then, the extension is removed, too! */ 04366 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 04367 if (!exten3) 04368 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 04369 if (con->pattern_tree) { 04370 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 04371 if (x->exten) { /* this test for safety purposes */ 04372 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 04373 x->exten = 0; /* get rid of what will become a bad pointer */ 04374 } 04375 } 04376 } 04377 } else { 04378 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 04379 priority, exten->exten, con->name); 04380 } 04381 } 04382 } else { 04383 /* hmmm? this exten is not in this pattern tree? */ 04384 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 04385 extension, con->name); 04386 } 04387 #ifdef NEED_DEBUG 04388 if (con->pattern_tree) { 04389 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 04390 log_match_char_tree(con->pattern_tree, " "); 04391 } 04392 #endif 04393 04394 /* scan the extension list to find first matching extension-registrar */ 04395 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 04396 if (!strcmp(exten->exten, extension) && 04397 (!registrar || !strcmp(exten->registrar, registrar)) && 04398 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 04399 break; 04400 } 04401 if (!exten) { 04402 /* we can't find right extension */ 04403 if (!already_locked) 04404 ast_unlock_context(con); 04405 return -1; 04406 } 04407 04408 /* scan the priority list to remove extension with exten->priority == priority */ 04409 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 04410 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))); 04411 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 04412 if ((priority == 0 || peer->priority == priority) && 04413 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 04414 (!registrar || !strcmp(peer->registrar, registrar) )) { 04415 found = 1; 04416 04417 /* we are first priority extension? */ 04418 if (!previous_peer) { 04419 /* 04420 * We are first in the priority chain, so must update the extension chain. 04421 * The next node is either the next priority or the next extension 04422 */ 04423 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 04424 if (peer->peer) { 04425 /* move the peer_table and peer_label_table down to the next peer, if 04426 it is there */ 04427 peer->peer->peer_table = peer->peer_table; 04428 peer->peer->peer_label_table = peer->peer_label_table; 04429 peer->peer_table = NULL; 04430 peer->peer_label_table = NULL; 04431 } 04432 if (!prev_exten) { /* change the root... */ 04433 con->root = next_node; 04434 } else { 04435 prev_exten->next = next_node; /* unlink */ 04436 } 04437 if (peer->peer) { /* update the new head of the pri list */ 04438 peer->peer->next = peer->next; 04439 } 04440 } else { /* easy, we are not first priority in extension */ 04441 previous_peer->peer = peer->peer; 04442 } 04443 04444 /* now, free whole priority extension */ 04445 destroy_exten(peer); 04446 } else { 04447 previous_peer = peer; 04448 } 04449 } 04450 if (!already_locked) 04451 ast_unlock_context(con); 04452 return found ? 0 : -1; 04453 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 6560 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
06561 { 06562 int ret = -1; 06563 struct ast_context *c = find_context_locked(context); 06564 06565 if (c) { 06566 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 06567 ast_unlock_contexts(); 06568 } 06569 return ret; 06570 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 6572 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().
06573 { 06574 struct ast_ignorepat *ip, *ipl = NULL; 06575 06576 ast_wrlock_context(con); 06577 06578 for (ip = con->ignorepats; ip; ip = ip->next) { 06579 if (!strcmp(ip->pattern, ignorepat) && 06580 (!registrar || (registrar == ip->registrar))) { 06581 if (ipl) { 06582 ipl->next = ip->next; 06583 ast_free(ip); 06584 } else { 06585 con->ignorepats = ip->next; 06586 ast_free(ip); 06587 } 06588 ast_unlock_context(con); 06589 return 0; 06590 } 06591 ipl = ip; 06592 } 06593 06594 ast_unlock_context(con); 06595 errno = EINVAL; 06596 return -1; 06597 }
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 4160 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
04161 { 04162 int ret = -1; 04163 struct ast_context *c = find_context_locked(context); 04164 04165 if (c) { 04166 /* found, remove include from this context ... */ 04167 ret = ast_context_remove_include2(c, include, registrar); 04168 ast_unlock_contexts(); 04169 } 04170 return ret; 04171 }
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 4182 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().
04183 { 04184 struct ast_include *i, *pi = NULL; 04185 int ret = -1; 04186 04187 ast_wrlock_context(con); 04188 04189 /* find our include */ 04190 for (i = con->includes; i; pi = i, i = i->next) { 04191 if (!strcmp(i->name, include) && 04192 (!registrar || !strcmp(i->registrar, registrar))) { 04193 /* remove from list */ 04194 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 04195 if (pi) 04196 pi->next = i->next; 04197 else 04198 con->includes = i->next; 04199 /* free include and return */ 04200 ast_free(i); 04201 ret = 0; 04202 break; 04203 } 04204 } 04205 04206 ast_unlock_context(con); 04207 04208 return ret; 04209 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 4216 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
04217 { 04218 int ret = -1; /* default error return */ 04219 struct ast_context *c = find_context_locked(context); 04220 04221 if (c) { 04222 /* remove switch from this context ... */ 04223 ret = ast_context_remove_switch2(c, sw, data, registrar); 04224 ast_unlock_contexts(); 04225 } 04226 return ret; 04227 }
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 4237 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().
04238 { 04239 struct ast_sw *i; 04240 int ret = -1; 04241 04242 ast_wrlock_context(con); 04243 04244 /* walk switches */ 04245 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 04246 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 04247 (!registrar || !strcmp(i->registrar, registrar))) { 04248 /* found, remove from list */ 04249 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 04250 AST_LIST_REMOVE_CURRENT(list); 04251 ast_free(i); /* free switch and return */ 04252 ret = 0; 04253 break; 04254 } 04255 } 04256 AST_LIST_TRAVERSE_SAFE_END; 04257 04258 ast_unlock_context(con); 04259 04260 return ret; 04261 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 4500 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().
04501 { 04502 struct ast_context *c = NULL; 04503 int ret = -1; 04504 struct fake_context item; 04505 04506 ast_rdlock_contexts(); 04507 04508 ast_copy_string(item.name, context, sizeof(item.name)); 04509 04510 c = ast_hashtab_lookup(contexts_table,&item); 04511 if (c) 04512 ret = 0; 04513 #ifdef NOTNOW 04514 04515 while ((c = ast_walk_contexts(c))) { 04516 if (!strcmp(ast_get_context_name(c), context)) { 04517 ret = 0; 04518 break; 04519 } 04520 } 04521 04522 #endif 04523 ast_unlock_contexts(); 04524 04525 /* if we found context, unlock macrolock */ 04526 if (ret == 0) 04527 ret = ast_mutex_unlock(&c->macrolock); 04528 04529 return ret; 04530 }
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 8860 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().
08861 { 08862 struct ast_include *inc = NULL; 08863 int res = 0; 08864 08865 while ( (inc = ast_walk_context_includes(con, inc)) ) { 08866 if (ast_context_find(inc->rname)) 08867 continue; 08868 08869 res = -1; 08870 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 08871 ast_get_context_name(con), inc->rname); 08872 break; 08873 } 08874 08875 return res; 08876 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) |
Definition at line 2763 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().
02764 { 02765 struct ast_custom_function *acf = NULL; 02766 02767 AST_RWLIST_RDLOCK(&acf_root); 02768 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 02769 if (!strcmp(name, acf->name)) 02770 break; 02771 } 02772 AST_RWLIST_UNLOCK(&acf_root); 02773 02774 return acf; 02775 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 2777 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().
02778 { 02779 struct ast_custom_function *cur; 02780 02781 if (!acf) 02782 return -1; 02783 02784 AST_RWLIST_WRLOCK(&acf_root); 02785 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) 02786 ast_verb(2, "Unregistered custom function %s\n", cur->name); 02787 AST_RWLIST_UNLOCK(&acf_root); 02788 02789 return cur ? 0 : -1; 02790 }
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 3621 of file pbx.c.
References E_MATCH, and pbx_extension_helper().
Referenced by __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), answer_call(), ast_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), builtin_atxfer(), builtin_blindtransfer(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmfup(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), park_space_reserve(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), pri_dchannel(), privacy_exec(), process_ast_dsp(), readexten_exec(), register_peer_exten(), rpt_exec(), show_debug_helper(), skinny_ss(), socket_process(), ss_thread(), and waitstream_core().
03622 { 03623 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 03624 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6707 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().
06708 { 06709 if (!chan) 06710 return -1; 06711 06712 ast_channel_lock(chan); 06713 06714 if (!ast_strlen_zero(context)) 06715 ast_copy_string(chan->context, context, sizeof(chan->context)); 06716 if (!ast_strlen_zero(exten)) 06717 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06718 if (priority > -1) { 06719 chan->priority = priority; 06720 /* see flag description in channel.h for explanation */ 06721 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 06722 chan->priority--; 06723 } 06724 06725 ast_channel_unlock(chan); 06726 06727 return 0; 06728 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 1989 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().
01990 { 01991 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 01992 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 01993 return extension_match_core(pattern, data, needmore); 01994 }
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 1791 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
01792 { 01793 return ext_cmp(a, b); 01794 }
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 1984 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().
01985 { 01986 return extension_match_core(pattern, data, E_MATCH); 01987 }
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 3313 of file pbx.c.
References ast_extension_state2(), and ast_hint_extension().
Referenced by action_extensionstate(), extstate_read(), and handle_request_subscribe().
03314 { 03315 struct ast_exten *e; 03316 03317 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */ 03318 if (!e) 03319 return -1; /* No hint, return -1 */ 03320 03321 return ast_extension_state2(e); /* Check all devices in the hint */ 03322 }
static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
Check state of extension by using hints.
Definition at line 3257 of file pbx.c.
References ast_copy_string(), AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, ast_device_state(), AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, AST_EXTENSION_UNAVAILABLE, ast_get_extension_app(), AST_MAX_EXTENSION, and strsep().
Referenced by ast_add_hint_nolock(), ast_extension_state(), and handle_statechange().
03258 { 03259 char hint[AST_MAX_EXTENSION] = ""; 03260 char *cur, *rest; 03261 struct ast_devstate_aggregate agg; 03262 enum ast_device_state state; 03263 03264 if (!e) 03265 return -1; 03266 03267 ast_devstate_aggregate_init(&agg); 03268 03269 ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint)); 03270 03271 rest = hint; /* One or more devices separated with a & character */ 03272 03273 while ( (cur = strsep(&rest, "&")) ) 03274 ast_devstate_aggregate_add(&agg, ast_device_state(cur)); 03275 03276 state = ast_devstate_aggregate_result(&agg); 03277 03278 switch (state) { 03279 case AST_DEVICE_ONHOLD: 03280 return AST_EXTENSION_ONHOLD; 03281 case AST_DEVICE_BUSY: 03282 return AST_EXTENSION_BUSY; 03283 case AST_DEVICE_UNAVAILABLE: 03284 return AST_EXTENSION_UNAVAILABLE; 03285 case AST_DEVICE_RINGINUSE: 03286 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 03287 case AST_DEVICE_RINGING: 03288 return AST_EXTENSION_RINGING; 03289 case AST_DEVICE_INUSE: 03290 return AST_EXTENSION_INUSE; 03291 case AST_DEVICE_UNKNOWN: 03292 case AST_DEVICE_INVALID: 03293 case AST_DEVICE_NOT_INUSE: 03294 return AST_EXTENSION_NOT_INUSE; 03295 } 03296 03297 return AST_EXTENSION_NOT_INUSE; 03298 }
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 3301 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().
03302 { 03303 int i; 03304 03305 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 03306 if (extension_states[i].extension_state == extension_state) 03307 return extension_states[i].text; 03308 } 03309 return "Unknown"; 03310 }
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 3374 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_context::name, ast_exten::parent, ast_exten::priority, ast_exten::registrar, and stateid.
Referenced by __init_manager(), handle_request_subscribe(), and skinny_register().
03376 { 03377 struct ast_hint *hint; 03378 struct ast_state_cb *cblist; 03379 struct ast_exten *e; 03380 03381 /* If there's no context and extension: add callback to statecbs list */ 03382 if (!context && !exten) { 03383 AST_RWLIST_WRLOCK(&hints); 03384 03385 AST_LIST_TRAVERSE(&statecbs, cblist, entry) { 03386 if (cblist->callback == callback) { 03387 cblist->data = data; 03388 AST_RWLIST_UNLOCK(&hints); 03389 return 0; 03390 } 03391 } 03392 03393 /* Now insert the callback */ 03394 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 03395 AST_RWLIST_UNLOCK(&hints); 03396 return -1; 03397 } 03398 cblist->id = 0; 03399 cblist->callback = callback; 03400 cblist->data = data; 03401 03402 AST_LIST_INSERT_HEAD(&statecbs, cblist, entry); 03403 03404 AST_RWLIST_UNLOCK(&hints); 03405 03406 return 0; 03407 } 03408 03409 if (!context || !exten) 03410 return -1; 03411 03412 /* This callback type is for only one hint, so get the hint */ 03413 e = ast_hint_extension(NULL, context, exten); 03414 if (!e) { 03415 return -1; 03416 } 03417 03418 /* If this is a pattern, dynamically create a new extension for this 03419 * particular match. Note that this will only happen once for each 03420 * individual extension, because the pattern will no longer match first. 03421 */ 03422 if (e->exten[0] == '_') { 03423 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 03424 e->cidmatch, e->app, ast_strdup(e->data), ast_free_ptr, 03425 e->registrar); 03426 e = ast_hint_extension(NULL, context, exten); 03427 if (!e || e->exten[0] == '_') { 03428 return -1; 03429 } 03430 } 03431 03432 /* Find the hint in the list of hints */ 03433 AST_RWLIST_WRLOCK(&hints); 03434 03435 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03436 if (hint->exten == e) 03437 break; 03438 } 03439 03440 if (!hint) { 03441 /* We have no hint, sorry */ 03442 AST_RWLIST_UNLOCK(&hints); 03443 return -1; 03444 } 03445 03446 /* Now insert the callback in the callback list */ 03447 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 03448 AST_RWLIST_UNLOCK(&hints); 03449 return -1; 03450 } 03451 03452 cblist->id = stateid++; /* Unique ID for this callback */ 03453 cblist->callback = callback; /* Pointer to callback routine */ 03454 cblist->data = data; /* Data for the callback */ 03455 03456 AST_LIST_INSERT_HEAD(&hint->callbacks, cblist, entry); 03457 03458 AST_RWLIST_UNLOCK(&hints); 03459 03460 return cblist->id; 03461 }
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 3464 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().
03465 { 03466 struct ast_state_cb *p_cur = NULL; 03467 int ret = -1; 03468 03469 if (!id && !callback) 03470 return -1; 03471 03472 AST_RWLIST_WRLOCK(&hints); 03473 03474 if (!id) { /* id == 0 is a callback without extension */ 03475 AST_LIST_TRAVERSE_SAFE_BEGIN(&statecbs, p_cur, entry) { 03476 if (p_cur->callback == callback) { 03477 AST_LIST_REMOVE_CURRENT(entry); 03478 break; 03479 } 03480 } 03481 AST_LIST_TRAVERSE_SAFE_END; 03482 } else { /* callback with extension, find the callback based on ID */ 03483 struct ast_hint *hint; 03484 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03485 AST_LIST_TRAVERSE_SAFE_BEGIN(&hint->callbacks, p_cur, entry) { 03486 if (p_cur->id == id) { 03487 AST_LIST_REMOVE_CURRENT(entry); 03488 break; 03489 } 03490 } 03491 AST_LIST_TRAVERSE_SAFE_END; 03492 03493 if (p_cur) 03494 break; 03495 } 03496 } 03497 03498 if (p_cur) { 03499 ast_free(p_cur); 03500 } 03501 03502 AST_RWLIST_UNLOCK(&hints); 03503 03504 return ret; 03505 }
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 3626 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().
03627 { 03628 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 03629 }
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 3631 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
03632 { 03633 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 03634 }
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 2850 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().
02851 { 02852 char *copy = ast_strdupa(function); 02853 char *args = func_args(copy); 02854 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 02855 02856 if (acfptr == NULL) 02857 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 02858 else if (!acfptr->read) 02859 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 02860 else { 02861 int res; 02862 struct ast_module_user *u = NULL; 02863 if (acfptr->mod) 02864 u = __ast_module_user_add(acfptr->mod, chan); 02865 res = acfptr->read(chan, copy, args, workspace, len); 02866 if (acfptr->mod && u) 02867 __ast_module_user_remove(acfptr->mod, u); 02868 return res; 02869 } 02870 return -1; 02871 }
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 2873 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 pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
02874 { 02875 char *copy = ast_strdupa(function); 02876 char *args = func_args(copy); 02877 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 02878 02879 if (acfptr == NULL) 02880 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 02881 else if (!acfptr->write) 02882 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 02883 else { 02884 int res; 02885 struct ast_module_user *u = NULL; 02886 if (acfptr->mod) 02887 u = __ast_module_user_add(acfptr->mod, chan); 02888 res = acfptr->write(chan, copy, args, value); 02889 if (acfptr->mod && u) 02890 __ast_module_user_remove(acfptr->mod, u); 02891 return res; 02892 } 02893 02894 return -1; 02895 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 8712 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().
08713 { 08714 return con ? con->name : NULL; 08715 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 8750 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
08751 { 08752 return c ? c->registrar : NULL; 08753 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 8780 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().
08781 { 08782 return e ? e->app : NULL; 08783 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 8785 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().
08786 { 08787 return e ? e->data : NULL; 08788 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 8775 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
08776 { 08777 return e ? e->cidmatch : NULL; 08778 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) |
Definition at line 8717 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 8727 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 8770 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
08771 { 08772 return e ? e->matchcid : 0; 08773 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 8722 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 8742 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 8755 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
08756 { 08757 return e ? e->registrar : NULL; 08758 }
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 3604 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().
03605 { 03606 struct ast_exten *e = ast_hint_extension(c, context, exten); 03607 03608 if (e) { 03609 if (hint) 03610 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 03611 if (name) { 03612 const char *tmp = ast_get_extension_app_data(e); 03613 if (tmp) 03614 ast_copy_string(name, tmp, namesize); 03615 } 03616 return -1; 03617 } 03618 return 0; 03619 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 8737 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().
08738 { 08739 return ip ? ip->pattern : NULL; 08740 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 8765 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().
08766 { 08767 return ip ? ip->registrar : NULL; 08768 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 8732 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().
08733 { 08734 return inc ? inc->name : NULL; 08735 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 8760 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().
08761 { 08762 return i ? i->registrar : NULL; 08763 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 8795 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().
08796 { 08797 return sw ? sw->data : NULL; 08798 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 8800 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
08801 { 08802 return sw->eval; 08803 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 8790 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().
08791 { 08792 return sw ? sw->name : NULL; 08793 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 8805 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().
08806 { 08807 return sw ? sw->registrar : NULL; 08808 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8898 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().
08899 { 08900 return __ast_goto_if_exists(chan, context, exten, priority, 0); 08901 }
int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
const void * | ah_b | |||
) |
Definition at line 352 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
00353 { 00354 const struct ast_context *ac = ah_a; 00355 const struct ast_context *bc = ah_b; 00356 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 00357 return 1; 00358 /* assume context names are registered in a string table! */ 00359 return strcmp(ac->name, bc->name); 00360 }
unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 395 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().
00396 { 00397 const struct ast_context *ac = obj; 00398 return ast_hashtab_hash_string(ac->name); 00399 }
static struct ast_exten* ast_hint_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) | [static] |
Definition at line 3247 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().
03248 { 03249 struct ast_exten *e; 03250 ast_rdlock_contexts(); 03251 e = ast_hint_extension_nolock(c, context, exten); 03252 ast_unlock_contexts(); 03253 return e; 03254 }
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 3241 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().
03242 { 03243 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 03244 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 03245 }
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 6653 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().
06654 { 06655 struct ast_context *con = ast_context_find(context); 06656 if (con) { 06657 struct ast_ignorepat *pat; 06658 for (pat = con->ignorepats; pat; pat = pat->next) { 06659 if (ast_extension_match(pat->pattern, pattern)) 06660 return 1; 06661 } 06662 } 06663 06664 return 0; 06665 }
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 3641 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(), readexten_exec(), skinny_ss(), and ss_thread().
03642 { 03643 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 03644 }
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 6013 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, store_hint::exten, ast_hint::exten, ast_exten::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, ast_context::registrar, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
06014 { 06015 double ft; 06016 struct ast_context *tmp, *oldcontextslist; 06017 struct ast_hashtab *oldtable; 06018 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 06019 struct store_hint *this; 06020 struct ast_hint *hint; 06021 struct ast_exten *exten; 06022 int length; 06023 struct ast_state_cb *thiscb; 06024 struct ast_hashtab_iter *iter; 06025 06026 /* it is very important that this function hold the hint list lock _and_ the conlock 06027 during its operation; not only do we need to ensure that the list of contexts 06028 and extensions does not change, but also that no hint callbacks (watchers) are 06029 added or removed during the merge/delete process 06030 06031 in addition, the locks _must_ be taken in this order, because there are already 06032 other code paths that use this order 06033 */ 06034 06035 struct timeval begintime, writelocktime, endlocktime, enddeltime; 06036 int wrlock_ver; 06037 06038 begintime = ast_tvnow(); 06039 ast_rdlock_contexts(); 06040 iter = ast_hashtab_start_traversal(contexts_table); 06041 while ((tmp = ast_hashtab_next(iter))) { 06042 context_merge(extcontexts, exttable, tmp, registrar); 06043 } 06044 ast_hashtab_end_traversal(iter); 06045 wrlock_ver = ast_wrlock_contexts_version(); 06046 06047 ast_unlock_contexts(); /* this feels real retarded, but you must do 06048 what you must do If this isn't done, the following 06049 wrlock is a guraranteed deadlock */ 06050 ast_wrlock_contexts(); 06051 if (ast_wrlock_contexts_version() > wrlock_ver+1) { 06052 ast_log(LOG_WARNING,"==================!!!!!!!!!!!!!!!Something changed the contexts in the middle of merging contexts!\n"); 06053 } 06054 06055 AST_RWLIST_WRLOCK(&hints); 06056 writelocktime = ast_tvnow(); 06057 06058 /* preserve all watchers for hints associated with this registrar */ 06059 AST_RWLIST_TRAVERSE(&hints, hint, list) { 06060 if (!AST_LIST_EMPTY(&hint->callbacks) && !strcmp(registrar, hint->exten->parent->registrar)) { 06061 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 06062 if (!(this = ast_calloc(1, length))) 06063 continue; 06064 AST_LIST_APPEND_LIST(&this->callbacks, &hint->callbacks, entry); 06065 this->laststate = hint->laststate; 06066 this->context = this->data; 06067 strcpy(this->data, hint->exten->parent->name); 06068 this->exten = this->data + strlen(this->context) + 1; 06069 strcpy(this->exten, hint->exten->exten); 06070 AST_LIST_INSERT_HEAD(&store, this, list); 06071 } 06072 } 06073 06074 /* save the old table and list */ 06075 oldtable = contexts_table; 06076 oldcontextslist = contexts; 06077 06078 /* move in the new table and list */ 06079 contexts_table = exttable; 06080 contexts = *extcontexts; 06081 06082 /* restore the watchers for hints that can be found; notify those that 06083 cannot be restored 06084 */ 06085 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 06086 struct pbx_find_info q = { .stacklen = 0 }; 06087 exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH); 06088 /* If this is a pattern, dynamically create a new extension for this 06089 * particular match. Note that this will only happen once for each 06090 * individual extension, because the pattern will no longer match first. 06091 */ 06092 if (exten && exten->exten[0] == '_') { 06093 ast_add_extension_nolock(exten->parent->name, 0, this->exten, PRIORITY_HINT, NULL, 06094 0, exten->app, ast_strdup(exten->data), ast_free_ptr, registrar); 06095 /* rwlocks are not recursive locks */ 06096 exten = ast_hint_extension_nolock(NULL, this->context, this->exten); 06097 } 06098 06099 /* Find the hint in the list of hints */ 06100 AST_RWLIST_TRAVERSE(&hints, hint, list) { 06101 if (hint->exten == exten) 06102 break; 06103 } 06104 if (!exten || !hint) { 06105 /* this hint has been removed, notify the watchers */ 06106 while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) { 06107 thiscb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, thiscb->data); 06108 ast_free(thiscb); 06109 } 06110 } else { 06111 AST_LIST_APPEND_LIST(&hint->callbacks, &this->callbacks, entry); 06112 hint->laststate = this->laststate; 06113 } 06114 ast_free(this); 06115 } 06116 06117 AST_RWLIST_UNLOCK(&hints); 06118 ast_unlock_contexts(); 06119 endlocktime = ast_tvnow(); 06120 06121 /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk 06122 is now freely using the new stuff instead */ 06123 06124 ast_hashtab_destroy(oldtable, NULL); 06125 06126 for (tmp = oldcontextslist; tmp; ) { 06127 struct ast_context *next; /* next starting point */ 06128 next = tmp->next; 06129 __ast_internal_context_destroy(tmp); 06130 tmp = next; 06131 } 06132 enddeltime = ast_tvnow(); 06133 06134 ft = ast_tvdiff_us(writelocktime, begintime); 06135 ft /= 1000000.0; 06136 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 06137 06138 ft = ast_tvdiff_us(endlocktime, writelocktime); 06139 ft /= 1000000.0; 06140 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 06141 06142 ft = ast_tvdiff_us(enddeltime, endlocktime); 06143 ft /= 1000000.0; 06144 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 06145 06146 ft = ast_tvdiff_us(enddeltime, begintime); 06147 ft /= 1000000.0; 06148 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 06149 return; 06150 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
This function will handle locking the channel as needed.
Definition at line 8961 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().
08962 { 08963 return pbx_parseable_goto(chan, goto_string, 0); 08964 }
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 7489 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().
07490 { 07491 struct ast_channel *chan; 07492 struct app_tmp *tmp; 07493 int res = -1, cdr_res = -1; 07494 struct outgoing_helper oh; 07495 07496 memset(&oh, 0, sizeof(oh)); 07497 oh.vars = vars; 07498 oh.account = account; 07499 07500 if (locked_channel) 07501 *locked_channel = NULL; 07502 if (ast_strlen_zero(app)) { 07503 res = -1; 07504 goto outgoing_app_cleanup; 07505 } 07506 if (synchronous) { 07507 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07508 if (chan) { 07509 ast_set_variables(chan, vars); 07510 if (account) 07511 ast_cdr_setaccount(chan, account); 07512 if (chan->_state == AST_STATE_UP) { 07513 res = 0; 07514 ast_verb(4, "Channel %s was answered.\n", chan->name); 07515 tmp = ast_calloc(1, sizeof(*tmp)); 07516 if (!tmp) 07517 res = -1; 07518 else { 07519 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 07520 if (appdata) 07521 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 07522 tmp->chan = chan; 07523 if (synchronous > 1) { 07524 if (locked_channel) 07525 ast_channel_unlock(chan); 07526 ast_pbx_run_app(tmp); 07527 } else { 07528 if (locked_channel) 07529 ast_channel_lock(chan); 07530 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 07531 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 07532 ast_free(tmp); 07533 if (locked_channel) 07534 ast_channel_unlock(chan); 07535 ast_hangup(chan); 07536 res = -1; 07537 } else { 07538 if (locked_channel) 07539 *locked_channel = chan; 07540 } 07541 } 07542 } 07543 } else { 07544 ast_verb(4, "Channel %s was never answered.\n", chan->name); 07545 if (chan->cdr) { /* update the cdr */ 07546 /* here we update the status of the call, which sould be busy. 07547 * if that fails then we set the status to failed */ 07548 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 07549 ast_cdr_failed(chan->cdr); 07550 } 07551 ast_hangup(chan); 07552 } 07553 } 07554 07555 if (res < 0) { /* the call failed for some reason */ 07556 if (*reason == 0) { /* if the call failed (not busy or no answer) 07557 * update the cdr with the failed message */ 07558 cdr_res = ast_pbx_outgoing_cdr_failed(); 07559 if (cdr_res != 0) { 07560 res = cdr_res; 07561 goto outgoing_app_cleanup; 07562 } 07563 } 07564 } 07565 07566 } else { 07567 struct async_stat *as; 07568 if (!(as = ast_calloc(1, sizeof(*as)))) { 07569 res = -1; 07570 goto outgoing_app_cleanup; 07571 } 07572 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07573 if (!chan) { 07574 ast_free(as); 07575 res = -1; 07576 goto outgoing_app_cleanup; 07577 } 07578 as->chan = chan; 07579 ast_copy_string(as->app, app, sizeof(as->app)); 07580 if (appdata) 07581 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 07582 as->timeout = timeout; 07583 ast_set_variables(chan, vars); 07584 if (account) 07585 ast_cdr_setaccount(chan, account); 07586 /* Start a new thread, and get something handling this channel. */ 07587 if (locked_channel) 07588 ast_channel_lock(chan); 07589 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 07590 ast_log(LOG_WARNING, "Failed to start async wait\n"); 07591 ast_free(as); 07592 if (locked_channel) 07593 ast_channel_unlock(chan); 07594 ast_hangup(chan); 07595 res = -1; 07596 goto outgoing_app_cleanup; 07597 } else { 07598 if (locked_channel) 07599 *locked_channel = chan; 07600 } 07601 res = 0; 07602 } 07603 outgoing_app_cleanup: 07604 ast_variables_destroy(vars); 07605 return res; 07606 }
static int ast_pbx_outgoing_cdr_failed | ( | void | ) | [static] |
Function to post an empty cdr after a spool call fails.
Definition at line 7297 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().
07298 { 07299 /* allocate a channel */ 07300 struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", ""); 07301 07302 if (!chan) 07303 return -1; /* failure */ 07304 07305 if (!chan->cdr) { 07306 /* allocation of the cdr failed */ 07307 ast_channel_free(chan); /* free the channel */ 07308 return -1; /* return failure */ 07309 } 07310 07311 /* allocation of the cdr was successful */ 07312 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 07313 ast_cdr_start(chan->cdr); /* record the start and stop time */ 07314 ast_cdr_end(chan->cdr); 07315 ast_cdr_failed(chan->cdr); /* set the status to failed */ 07316 ast_cdr_detach(chan->cdr); /* post and free the record */ 07317 chan->cdr = NULL; 07318 ast_channel_free(chan); /* free the channel */ 07319 07320 return 0; /* success */ 07321 }
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 7323 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().
07324 { 07325 struct ast_channel *chan; 07326 struct async_stat *as; 07327 int res = -1, cdr_res = -1; 07328 struct outgoing_helper oh; 07329 07330 if (synchronous) { 07331 oh.context = context; 07332 oh.exten = exten; 07333 oh.priority = priority; 07334 oh.cid_num = cid_num; 07335 oh.cid_name = cid_name; 07336 oh.account = account; 07337 oh.vars = vars; 07338 oh.parent_channel = NULL; 07339 07340 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07341 if (channel) { 07342 *channel = chan; 07343 if (chan) 07344 ast_channel_lock(chan); 07345 } 07346 if (chan) { 07347 if (chan->_state == AST_STATE_UP) { 07348 res = 0; 07349 ast_verb(4, "Channel %s was answered.\n", chan->name); 07350 07351 if (synchronous > 1) { 07352 if (channel) 07353 ast_channel_unlock(chan); 07354 if (ast_pbx_run(chan)) { 07355 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 07356 if (channel) 07357 *channel = NULL; 07358 ast_hangup(chan); 07359 chan = NULL; 07360 res = -1; 07361 } 07362 } else { 07363 if (ast_pbx_start(chan)) { 07364 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 07365 if (channel) { 07366 *channel = NULL; 07367 ast_channel_unlock(chan); 07368 } 07369 ast_hangup(chan); 07370 res = -1; 07371 } 07372 chan = NULL; 07373 } 07374 } else { 07375 ast_verb(4, "Channel %s was never answered.\n", chan->name); 07376 07377 if (chan->cdr) { /* update the cdr */ 07378 /* here we update the status of the call, which sould be busy. 07379 * if that fails then we set the status to failed */ 07380 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 07381 ast_cdr_failed(chan->cdr); 07382 } 07383 07384 if (channel) { 07385 *channel = NULL; 07386 ast_channel_unlock(chan); 07387 } 07388 ast_hangup(chan); 07389 chan = NULL; 07390 } 07391 } 07392 07393 if (res < 0) { /* the call failed for some reason */ 07394 if (*reason == 0) { /* if the call failed (not busy or no answer) 07395 * update the cdr with the failed message */ 07396 cdr_res = ast_pbx_outgoing_cdr_failed(); 07397 if (cdr_res != 0) { 07398 res = cdr_res; 07399 goto outgoing_exten_cleanup; 07400 } 07401 } 07402 07403 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 07404 /* check if "failed" exists */ 07405 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 07406 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed"); 07407 if (chan) { 07408 char failed_reason[4] = ""; 07409 if (!ast_strlen_zero(context)) 07410 ast_copy_string(chan->context, context, sizeof(chan->context)); 07411 set_ext_pri(chan, "failed", 1); 07412 ast_set_variables(chan, vars); 07413 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 07414 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 07415 if (account) 07416 ast_cdr_setaccount(chan, account); 07417 if (ast_pbx_run(chan)) { 07418 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 07419 ast_hangup(chan); 07420 } 07421 chan = NULL; 07422 } 07423 } 07424 } 07425 } else { 07426 if (!(as = ast_calloc(1, sizeof(*as)))) { 07427 res = -1; 07428 goto outgoing_exten_cleanup; 07429 } 07430 chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name); 07431 if (channel) { 07432 *channel = chan; 07433 if (chan) 07434 ast_channel_lock(chan); 07435 } 07436 if (!chan) { 07437 ast_free(as); 07438 res = -1; 07439 goto outgoing_exten_cleanup; 07440 } 07441 as->chan = chan; 07442 ast_copy_string(as->context, context, sizeof(as->context)); 07443 set_ext_pri(as->chan, exten, priority); 07444 as->timeout = timeout; 07445 ast_set_variables(chan, vars); 07446 if (account) 07447 ast_cdr_setaccount(chan, account); 07448 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 07449 ast_log(LOG_WARNING, "Failed to start async wait\n"); 07450 ast_free(as); 07451 if (channel) { 07452 *channel = NULL; 07453 ast_channel_unlock(chan); 07454 } 07455 ast_hangup(chan); 07456 res = -1; 07457 goto outgoing_exten_cleanup; 07458 } 07459 res = 0; 07460 } 07461 outgoing_exten_cleanup: 07462 ast_variables_destroy(vars); 07463 return res; 07464 }
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 4069 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().
04070 { 04071 return ast_pbx_run_args(c, NULL); 04072 }
static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 7474 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().
07475 { 07476 struct app_tmp *tmp = data; 07477 struct ast_app *app; 07478 app = pbx_findapp(tmp->app); 07479 if (app) { 07480 ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 07481 pbx_exec(tmp->chan, app, tmp->data); 07482 } else 07483 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 07484 ast_hangup(tmp->chan); 07485 ast_free(tmp); 07486 return NULL; 07487 }
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 4054 of file pbx.c.
References __ast_pbx_run(), AST_PBX_CALL_LIMIT, AST_PBX_SUCCESS, decrease_call_count(), and increase_call_count().
Referenced by ast_pbx_run(), dial_exec_full(), handle_gosub(), and try_calling().
04055 { 04056 enum ast_pbx_result res = AST_PBX_SUCCESS; 04057 04058 if (increase_call_count(c)) { 04059 return AST_PBX_CALL_LIMIT; 04060 } 04061 04062 res = __ast_pbx_run(c, args); 04063 04064 decrease_call_count(); 04065 04066 return res; 04067 }
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 4032 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().
04033 { 04034 pthread_t t; 04035 04036 if (!c) { 04037 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 04038 return AST_PBX_FAILED; 04039 } 04040 04041 if (increase_call_count(c)) 04042 return AST_PBX_CALL_LIMIT; 04043 04044 /* Start a new thread, and get something handling this channel. */ 04045 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 04046 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 04047 decrease_call_count(); 04048 return AST_PBX_FAILED; 04049 } 04050 04051 return AST_PBX_SUCCESS; 04052 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 4079 of file pbx.c.
References totalcalls.
Referenced by handle_chanlist(), and handle_showcalls().
04080 { 04081 return totalcalls; 04082 }
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 8699 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().
08700 { 08701 return ast_rwlock_rdlock(&con->lock); 08702 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 8681 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().
08682 { 08683 return ast_rwlock_rdlock(&conlock); 08684 }
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 4533 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().
04534 { 04535 struct ast_app *tmp, *cur = NULL; 04536 char tmps[80]; 04537 int length, res; 04538 04539 AST_RWLIST_WRLOCK(&apps); 04540 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 04541 if (!(res = strcasecmp(app, tmp->name))) { 04542 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 04543 AST_RWLIST_UNLOCK(&apps); 04544 return -1; 04545 } else if (res < 0) 04546 break; 04547 } 04548 04549 length = sizeof(*tmp) + strlen(app) + 1; 04550 04551 if (!(tmp = ast_calloc(1, length))) { 04552 AST_RWLIST_UNLOCK(&apps); 04553 return -1; 04554 } 04555 04556 strcpy(tmp->name, app); 04557 tmp->execute = execute; 04558 tmp->synopsis = synopsis; 04559 tmp->description = description; 04560 tmp->module = mod; 04561 04562 /* Store in alphabetical order */ 04563 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 04564 if (strcasecmp(tmp->name, cur->name) < 0) { 04565 AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list); 04566 break; 04567 } 04568 } 04569 AST_RWLIST_TRAVERSE_SAFE_END; 04570 if (!cur) 04571 AST_RWLIST_INSERT_TAIL(&apps, tmp, list); 04572 04573 ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 04574 04575 AST_RWLIST_UNLOCK(&apps); 04576 04577 return 0; 04578 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
Definition at line 4584 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().
04585 { 04586 struct ast_switch *tmp; 04587 04588 AST_RWLIST_WRLOCK(&switches); 04589 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 04590 if (!strcasecmp(tmp->name, sw->name)) { 04591 AST_RWLIST_UNLOCK(&switches); 04592 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 04593 return -1; 04594 } 04595 } 04596 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 04597 AST_RWLIST_UNLOCK(&switches); 04598 04599 return 0; 04600 }
static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
Remove hint from extension.
Definition at line 3569 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().
03570 { 03571 /* Cleanup the Notifys if hint is removed */ 03572 struct ast_hint *hint; 03573 struct ast_state_cb *cblist; 03574 int res = -1; 03575 03576 if (!e) 03577 return -1; 03578 03579 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) { 03580 if (hint->exten != e) 03581 continue; 03582 03583 while ((cblist = AST_LIST_REMOVE_HEAD(&hint->callbacks, entry))) { 03584 /* Notify with -1 and remove all callbacks */ 03585 cblist->callback(hint->exten->parent->name, hint->exten->exten, 03586 AST_EXTENSION_DEACTIVATED, cblist->data); 03587 ast_free(cblist); 03588 } 03589 03590 AST_RWLIST_REMOVE_CURRENT(list); 03591 ast_free(hint); 03592 03593 res = 0; 03594 03595 break; 03596 } 03597 AST_RWLIST_TRAVERSE_SAFE_END; 03598 03599 return res; 03600 }
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 3646 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().
03647 { 03648 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 03649 }
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 8704 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().
08705 { 08706 return ast_rwlock_unlock(&con->lock); 08707 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 8686 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().
08687 { 08688 return ast_rwlock_unlock(&conlock); 08689 }
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 5794 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().
05795 { 05796 struct ast_app *tmp; 05797 05798 AST_RWLIST_WRLOCK(&apps); 05799 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 05800 if (!strcasecmp(app, tmp->name)) { 05801 unreference_cached_app(tmp); 05802 AST_RWLIST_REMOVE_CURRENT(list); 05803 ast_verb(2, "Unregistered application '%s'\n", tmp->name); 05804 ast_free(tmp); 05805 break; 05806 } 05807 } 05808 AST_RWLIST_TRAVERSE_SAFE_END; 05809 AST_RWLIST_UNLOCK(&apps); 05810 05811 return tmp ? 0 : -1; 05812 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 4602 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().
04603 { 04604 AST_RWLIST_WRLOCK(&switches); 04605 AST_RWLIST_REMOVE(&switches, sw, list); 04606 AST_RWLIST_UNLOCK(&switches); 04607 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) |
Definition at line 8818 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().
08820 { 08821 if (!exten) 08822 return con ? con->root : NULL; 08823 else 08824 return exten->next; 08825 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) |
Definition at line 8851 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().
08853 { 08854 if (!ip) 08855 return con ? con->ignorepats : NULL; 08856 else 08857 return ip->next; 08858 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) |
Definition at line 8842 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().
08844 { 08845 if (!inc) 08846 return con ? con->includes : NULL; 08847 else 08848 return inc->next; 08849 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) |
Definition at line 8827 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().
08829 { 08830 if (!sw) 08831 return con ? AST_LIST_FIRST(&con->alts) : NULL; 08832 else 08833 return AST_LIST_NEXT(sw, list); 08834 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) |
Definition at line 8813 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 8836 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 8694 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().
08695 { 08696 return ast_rwlock_wrlock(&con->lock); 08697 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 8673 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().
08674 { 08675 int res = ast_rwlock_wrlock(&conlock); 08676 if (!res) 08677 ast_atomic_fetchadd_int(&conlock_wrlock_version, 1); 08678 return res; 08679 }
int ast_wrlock_contexts_version | ( | void | ) |
Definition at line 8665 of file pbx.c.
Referenced by ast_merge_contexts_and_delete().
08666 { 08667 return conlock_wrlock_version; 08668 }
static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 7236 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().
07237 { 07238 struct async_stat *as = data; 07239 struct ast_channel *chan = as->chan; 07240 int timeout = as->timeout; 07241 int res; 07242 struct ast_frame *f; 07243 struct ast_app *app; 07244 07245 while (timeout && (chan->_state != AST_STATE_UP)) { 07246 res = ast_waitfor(chan, timeout); 07247 if (res < 1) 07248 break; 07249 if (timeout > -1) 07250 timeout = res; 07251 f = ast_read(chan); 07252 if (!f) 07253 break; 07254 if (f->frametype == AST_FRAME_CONTROL) { 07255 if ((f->subclass == AST_CONTROL_BUSY) || 07256 (f->subclass == AST_CONTROL_CONGESTION) ) { 07257 ast_frfree(f); 07258 break; 07259 } 07260 } 07261 ast_frfree(f); 07262 } 07263 if (chan->_state == AST_STATE_UP) { 07264 if (!ast_strlen_zero(as->app)) { 07265 app = pbx_findapp(as->app); 07266 if (app) { 07267 ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 07268 pbx_exec(chan, app, as->appdata); 07269 } else 07270 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 07271 } else { 07272 if (!ast_strlen_zero(as->context)) 07273 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 07274 if (!ast_strlen_zero(as->exten)) 07275 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 07276 if (as->priority > 0) 07277 chan->priority = as->priority; 07278 /* Run the PBX */ 07279 if (ast_pbx_run(chan)) { 07280 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 07281 } else { 07282 /* PBX will have taken care of this */ 07283 chan = NULL; 07284 } 07285 } 07286 } 07287 ast_free(as); 07288 if (chan) 07289 ast_hangup(chan); 07290 return NULL; 07291 }
static void cli_match_char_tree | ( | struct match_char * | node, | |
char * | prefix, | |||
int | fd | |||
) | [static] |
Definition at line 1132 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().
01133 { 01134 char extenstr[40]; 01135 struct ast_str *my_prefix = ast_str_alloca(1024); 01136 01137 extenstr[0] = '\0'; 01138 01139 if (node && node->exten && node->exten) 01140 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01141 01142 if (strlen(node->x) > 1) { 01143 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01144 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01145 node->exten ? node->exten->exten : "", extenstr); 01146 } else { 01147 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01148 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01149 node->exten ? node->exten->exten : "", extenstr); 01150 } 01151 01152 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01153 01154 if (node->next_char) 01155 cli_match_char_tree(node->next_char, my_prefix->str, fd); 01156 01157 if (node->alt_char) 01158 cli_match_char_tree(node->alt_char, prefix, fd); 01159 }
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 3665 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.
03666 { 03667 int digit; 03668 03669 buf[pos] = '\0'; /* make sure it is properly terminated */ 03670 while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) { 03671 /* As long as we're willing to wait, and as long as it's not defined, 03672 keep reading digits until we can't possibly get a right answer anymore. */ 03673 digit = ast_waitfordigit(c, waittime); 03674 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 03675 c->_softhangup = 0; 03676 } else { 03677 if (!digit) /* No entry */ 03678 break; 03679 if (digit < 0) /* Error, maybe a hangup */ 03680 return -1; 03681 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 03682 buf[pos++] = digit; 03683 buf[pos] = '\0'; 03684 } 03685 waittime = c->pbx->dtimeoutms; 03686 } 03687 } 03688 return 0; 03689 }
static int compare_char | ( | const void * | a, | |
const void * | b | |||
) | [static] |
Definition at line 339 of file pbx.c.
Referenced by add_exten_to_pattern_tree().
00340 { 00341 const char *ac = a; 00342 const char *bc = b; 00343 if ((*ac) < (*bc)) 00344 return -1; 00345 else if ((*ac) == (*bc)) 00346 return 0; 00347 else 00348 return 1; 00349 }
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 4762 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().
04763 { 04764 struct ast_hint *hint; 04765 char *ret = NULL; 04766 int which = 0; 04767 int wordlen; 04768 04769 if (pos != 3) 04770 return NULL; 04771 04772 wordlen = strlen(word); 04773 04774 AST_RWLIST_RDLOCK(&hints); 04775 /* walk through all hints */ 04776 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04777 if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) { 04778 ret = ast_strdup(ast_get_extension_name(hint->exten)); 04779 break; 04780 } 04781 } 04782 AST_RWLIST_UNLOCK(&hints); 04783 04784 return ret; 04785 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 4958 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().
04960 { 04961 struct ast_context *c = NULL; 04962 char *ret = NULL; 04963 int which = 0; 04964 int wordlen; 04965 04966 /* we are do completion of [exten@]context on second position only */ 04967 if (pos != 2) 04968 return NULL; 04969 04970 ast_rdlock_contexts(); 04971 04972 wordlen = strlen(word); 04973 04974 /* walk through all contexts and return the n-th match */ 04975 while ( (c = ast_walk_contexts(c)) ) { 04976 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 04977 ret = ast_strdup(ast_get_context_name(c)); 04978 break; 04979 } 04980 } 04981 04982 ast_unlock_contexts(); 04983 04984 return ret; 04985 }
static void context_merge | ( | struct ast_context ** | extcontexts, | |
struct ast_hashtab * | exttable, | |||
struct ast_context * | context, | |||
const char * | registrar | |||
) | [static] |
Definition at line 5929 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::peer_table, ast_exten::priority, and ast_exten::registrar.
Referenced by ast_merge_contexts_and_delete().
05930 { 05931 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */ 05932 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item; 05933 struct ast_hashtab_iter *exten_iter; 05934 struct ast_hashtab_iter *prio_iter; 05935 int insert_count = 0; 05936 int first = 1; 05937 05938 /* We'll traverse all the extensions/prios, and see which are not registrar'd with 05939 the current registrar, and copy them to the new context. If the new context does not 05940 exist, we'll create it "on demand". If no items are in this context to copy, then we'll 05941 only create the empty matching context if the old one meets the criteria */ 05942 05943 if (context->root_table) { 05944 exten_iter = ast_hashtab_start_traversal(context->root_table); 05945 while ((exten_item=ast_hashtab_next(exten_iter))) { 05946 if (new) { 05947 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item); 05948 } else { 05949 new_exten_item = NULL; 05950 } 05951 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 05952 while ((prio_item=ast_hashtab_next(prio_iter))) { 05953 int res1; 05954 char *dupdstr; 05955 05956 if (new_exten_item) { 05957 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item); 05958 } else { 05959 new_prio_item = NULL; 05960 } 05961 if (strcmp(prio_item->registrar,registrar) == 0) { 05962 continue; 05963 } 05964 /* make sure the new context exists, so we have somewhere to stick this exten/prio */ 05965 if (!new) { 05966 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 */ 05967 } 05968 05969 /* copy in the includes, switches, and ignorepats */ 05970 if (first) { /* but, only need to do this once */ 05971 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 05972 first = 0; 05973 } 05974 05975 if (!new) { 05976 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name); 05977 return; /* no sense continuing. */ 05978 } 05979 /* we will not replace existing entries in the new context with stuff from the old context. 05980 but, if this is because of some sort of registrar conflict, we ought to say something... */ 05981 05982 dupdstr = ast_strdup(prio_item->data); 05983 05984 res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 05985 prio_item->cidmatch, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar); 05986 if (!res1 && new_exten_item && new_prio_item){ 05987 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n", 05988 context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar); 05989 } else { 05990 /* 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, 05991 and no double frees take place, either! */ 05992 insert_count++; 05993 } 05994 } 05995 ast_hashtab_end_traversal(prio_iter); 05996 } 05997 ast_hashtab_end_traversal(exten_iter); 05998 } 05999 06000 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 || 06001 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) { 06002 /* we could have given it the registrar of the other module who incremented the refcount, 06003 but that's not available, so we give it the registrar we know about */ 06004 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar); 06005 06006 /* copy in the includes, switches, and ignorepats */ 06007 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 06008 } 06009 }
static void context_merge_incls_swits_igps_other_registrars | ( | struct ast_context * | new, | |
struct ast_context * | old, | |||
const char * | registrar | |||
) | [static] |
Definition at line 5896 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().
05897 { 05898 struct ast_include *i; 05899 struct ast_ignorepat *ip; 05900 struct ast_sw *sw; 05901 05902 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); 05903 /* copy in the includes, switches, and ignorepats */ 05904 /* walk through includes */ 05905 for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) { 05906 if (strcmp(ast_get_include_registrar(i), registrar) == 0) 05907 continue; /* not mine */ 05908 ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i)); 05909 } 05910 05911 /* walk through switches */ 05912 for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) { 05913 if (strcmp(ast_get_switch_registrar(sw), registrar) == 0) 05914 continue; /* not mine */ 05915 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)); 05916 } 05917 05918 /* walk thru ignorepats ... */ 05919 for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) { 05920 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) 05921 continue; /* not mine */ 05922 ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip)); 05923 } 05924 }
static void create_match_char_tree | ( | struct ast_context * | con | ) | [static] |
Definition at line 1600 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().
01601 { 01602 struct ast_hashtab_iter *t1; 01603 struct ast_exten *e1; 01604 #ifdef NEED_DEBUG 01605 int biggest_bucket, resizes, numobjs, numbucks; 01606 01607 ast_log(LOG_DEBUG,"Creating Extension Trie for context %s\n", con->name); 01608 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks); 01609 ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n", 01610 numobjs, numbucks, biggest_bucket, resizes); 01611 #endif 01612 t1 = ast_hashtab_start_traversal(con->root_table); 01613 while( (e1 = ast_hashtab_next(t1)) ) { 01614 if (e1->exten) 01615 add_exten_to_pattern_tree(con, e1, 0); 01616 else 01617 ast_log(LOG_ERROR,"Attempt to create extension with no extension name.\n"); 01618 } 01619 ast_hashtab_end_traversal(t1); 01620 }
static void decrease_call_count | ( | void | ) | [static] |
Definition at line 3990 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().
03991 { 03992 ast_mutex_lock(&maxcalllock); 03993 if (countcalls > 0) 03994 countcalls--; 03995 ast_mutex_unlock(&maxcalllock); 03996 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 3998 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().
03999 { 04000 if (e->priority == PRIORITY_HINT) 04001 ast_remove_hint(e); 04002 04003 if (e->peer_table) 04004 ast_hashtab_destroy(e->peer_table,0); 04005 if (e->peer_label_table) 04006 ast_hashtab_destroy(e->peer_label_table, 0); 04007 if (e->datad) 04008 e->datad(e->data); 04009 ast_free(e); 04010 }
static void destroy_pattern_tree | ( | struct match_char * | pattern_tree | ) | [static] |
Definition at line 1622 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().
01623 { 01624 /* destroy all the alternates */ 01625 if (pattern_tree->alt_char) { 01626 destroy_pattern_tree(pattern_tree->alt_char); 01627 pattern_tree->alt_char = 0; 01628 } 01629 /* destroy all the nexts */ 01630 if (pattern_tree->next_char) { 01631 destroy_pattern_tree(pattern_tree->next_char); 01632 pattern_tree->next_char = 0; 01633 } 01634 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */ 01635 if (pattern_tree->x) 01636 free(pattern_tree->x); 01637 free(pattern_tree); 01638 }
static void device_state_cb | ( | const struct ast_event * | event, | |
void * | unused | |||
) | [static] |
Definition at line 8611 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().
08612 { 08613 const char *device; 08614 struct statechange *sc; 08615 08616 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 08617 if (ast_strlen_zero(device)) { 08618 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n"); 08619 return; 08620 } 08621 08622 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1))) 08623 return; 08624 strcpy(sc->dev, device); 08625 if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) { 08626 ast_free(sc); 08627 } 08628 }
static void exception_store_free | ( | void * | data | ) | [static] |
Definition at line 2564 of file pbx.c.
References ast_free, and ast_string_field_free_memory.
02565 { 02566 struct pbx_exception *exception = data; 02567 ast_string_field_free_memory(exception); 02568 ast_free(exception); 02569 }
static int ext_cmp | ( | const char * | a, | |
const char * | b | |||
) | [static] |
the full routine to compare extensions in rules.
Definition at line 1765 of file pbx.c.
References ext_cmp1().
Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().
01766 { 01767 /* make sure non-patterns come first. 01768 * If a is not a pattern, it either comes first or 01769 * we use strcmp to compare the strings. 01770 */ 01771 int ret = 0; 01772 01773 if (a[0] != '_') 01774 return (b[0] == '_') ? -1 : strcmp(a, b); 01775 01776 /* Now we know a is a pattern; if b is not, a comes first */ 01777 if (b[0] != '_') 01778 return 1; 01779 #if 0 /* old mode for ext matching */ 01780 return strcmp(a, b); 01781 #endif 01782 /* ok we need full pattern sorting routine */ 01783 while (!ret && a && b) 01784 ret = ext_cmp1(&a) - ext_cmp1(&b); 01785 if (ret == 0) 01786 return 0; 01787 else 01788 return (ret > 0) ? 1 : -1; 01789 }
static int ext_cmp1 | ( | const char ** | p | ) | [static] |
helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first.
ext_cmp1 compares individual characters (or sets of), returning an int where bits 0-7 are the ASCII code of the first char in the set, while bit 8-15 are the cardinality of the set minus 1. This way more specific patterns (smaller cardinality) appear first. Wildcards have a special value, so that we can directly compare them to sets by subtracting the two values. In particular: 0x000xx one character, xx 0x0yyxx yy character set starting with xx 0x10000 '.' (one or more of anything) 0x20000 '!' (zero or more of anything) 0x30000 NUL (end of string) 0x40000 error in set. The pointer to the string is advanced according to needs. NOTES: 1. the empty set is equivalent to NUL. 2. given that a full set has always 0 as the first element, we could encode the special cases as 0xffXX where XX is 1, 2, 3, 4 as used above.
Definition at line 1694 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ext_cmp().
01695 { 01696 uint32_t chars[8]; 01697 int c, cmin = 0xff, count = 0; 01698 const char *end; 01699 01700 /* load, sign extend and advance pointer until we find 01701 * a valid character. 01702 */ 01703 c = *(*p)++; 01704 01705 /* always return unless we have a set of chars */ 01706 switch (toupper(c)) { 01707 default: /* ordinary character */ 01708 return 0x0000 | (c & 0xff); 01709 01710 case 'N': /* 2..9 */ 01711 return 0x0800 | '2' ; 01712 01713 case 'X': /* 0..9 */ 01714 return 0x0A00 | '0'; 01715 01716 case 'Z': /* 1..9 */ 01717 return 0x0900 | '1'; 01718 01719 case '.': /* wildcard */ 01720 return 0x10000; 01721 01722 case '!': /* earlymatch */ 01723 return 0x20000; /* less specific than NULL */ 01724 01725 case '\0': /* empty string */ 01726 *p = NULL; 01727 return 0x30000; 01728 01729 case '[': /* pattern */ 01730 break; 01731 } 01732 /* locate end of set */ 01733 end = strchr(*p, ']'); 01734 01735 if (end == NULL) { 01736 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 01737 return 0x40000; /* XXX make this entry go last... */ 01738 } 01739 01740 memset(chars, '\0', sizeof(chars)); /* clear all chars in the set */ 01741 for (; *p < end ; (*p)++) { 01742 unsigned char c1, c2; /* first-last char in range */ 01743 c1 = (unsigned char)((*p)[0]); 01744 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 01745 c2 = (unsigned char)((*p)[2]); 01746 *p += 2; /* skip a total of 3 chars */ 01747 } else /* individual character */ 01748 c2 = c1; 01749 if (c1 < cmin) 01750 cmin = c1; 01751 for (; c1 <= c2; c1++) { 01752 uint32_t mask = 1 << (c1 % 32); 01753 if ( (chars[ c1 / 32 ] & mask) == 0) 01754 count += 0x100; 01755 chars[ c1 / 32 ] |= mask; 01756 } 01757 } 01758 (*p)++; 01759 return count == 0 ? 0x30000 : (count | cmin); 01760 }
static int ext_strncpy | ( | char * | dst, | |
const char * | src, | |||
int | len | |||
) | [static] |
copy a string skipping whitespace
Definition at line 6797 of file pbx.c.
Referenced by ast_add_extension2_lockopt().
06798 { 06799 int count = 0; 06800 06801 while (*src && (count < len - 1)) { 06802 switch (*src) { 06803 case ' ': 06804 /* otherwise exten => [a-b],1,... doesn't work */ 06805 /* case '-': */ 06806 /* Ignore */ 06807 break; 06808 default: 06809 *dst = *src; 06810 dst++; 06811 } 06812 src++; 06813 count++; 06814 } 06815 *dst = '\0'; 06816 06817 return count; 06818 }
static int extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 1972 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().
01973 { 01974 int i; 01975 static int prof_id = -2; /* marker for 'unallocated' id */ 01976 if (prof_id == -2) 01977 prof_id = ast_add_profile("ext_match", 0); 01978 ast_mark(prof_id, 1); 01979 i = _extension_match_core(pattern, data, mode); 01980 ast_mark(prof_id, 0); 01981 return i; 01982 }
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 4114 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), contexts_table, and fake_context::name.
Referenced by ast_add_extension_nolock().
04115 { 04116 struct ast_context *c = NULL; 04117 struct fake_context item; 04118 04119 ast_copy_string(item.name, context, sizeof(item.name)); 04120 04121 c = ast_hashtab_lookup(contexts_table,&item); 04122 04123 return c; 04124 }
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 4131 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().
04132 { 04133 struct ast_context *c = NULL; 04134 struct fake_context item; 04135 04136 ast_copy_string(item.name, context, sizeof(item.name)); 04137 04138 ast_rdlock_contexts(); 04139 c = ast_hashtab_lookup(contexts_table,&item); 04140 04141 #ifdef NOTNOW 04142 04143 while ( (c = ast_walk_contexts(c)) ) { 04144 if (!strcmp(ast_get_context_name(c), context)) 04145 return c; 04146 } 04147 #endif 04148 if (!c) 04149 ast_unlock_contexts(); 04150 04151 return c; 04152 }
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 2833 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), and ast_func_write().
02834 { 02835 char *args = strchr(function, '('); 02836 02837 if (!args) 02838 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n"); 02839 else { 02840 char *p; 02841 *args++ = '\0'; 02842 if ((p = strrchr(args, ')')) ) 02843 *p = '\0'; 02844 else 02845 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n"); 02846 } 02847 return args; 02848 }
static struct ast_exten * get_canmatch_exten | ( | struct match_char * | node | ) | [static] |
Definition at line 1161 of file pbx.c.
References ast_log(), ast_exten::exten, match_char::exten, LOG_NOTICE, and match_char::next_char.
01162 { 01163 /* find the exten at the end of the rope */ 01164 struct match_char *node2 = node; 01165 01166 for (node2 = node; node2; node2 = node2->next_char) { 01167 if (node2->exten) { 01168 #ifdef NEED_DEBUG_HERE 01169 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten); 01170 #endif 01171 return node2->exten; 01172 } 01173 } 01174 #ifdef NEED_DEBUG_HERE 01175 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x); 01176 #endif 01177 return 0; 01178 }
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 6191 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and s.
Referenced by ast_build_timing().
06192 { 06193 int s, e; /* start and ending position */ 06194 unsigned int mask = 0; 06195 06196 /* Check for whole range */ 06197 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 06198 s = 0; 06199 e = max - 1; 06200 } else { 06201 /* Get start and ending position */ 06202 char *c = strchr(src, '-'); 06203 if (c) 06204 *c++ = '\0'; 06205 /* Find the start */ 06206 s = lookup_name(src, names, max); 06207 if (!s) { 06208 ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src); 06209 return 0; 06210 } 06211 s--; 06212 if (c) { /* find end of range */ 06213 e = lookup_name(c, names, max); 06214 if (!e) { 06215 ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c); 06216 return 0; 06217 } 06218 e--; 06219 } else 06220 e = s; 06221 } 06222 /* Fill the mask. Remember that ranges are cyclic */ 06223 mask = 1 << e; /* initialize with last element */ 06224 while (s != e) { 06225 if (s >= max) { 06226 s = 0; 06227 mask |= (1 << s); 06228 } else { 06229 mask |= (1 << s); 06230 s++; 06231 } 06232 } 06233 return mask; 06234 }
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 6237 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
06238 { 06239 char *e; 06240 int x; 06241 int s1, s2; 06242 int e1, e2; 06243 /* int cth, ctm; */ 06244 06245 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 06246 memset(i->minmask, 0, sizeof(i->minmask)); 06247 06248 /* 2-minutes per bit, since the mask has only 32 bits :( */ 06249 /* Star is all times */ 06250 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 06251 for (x = 0; x < 24; x++) 06252 i->minmask[x] = 0x3fffffff; /* 30 bits */ 06253 return; 06254 } 06255 /* Otherwise expect a range */ 06256 e = strchr(times, '-'); 06257 if (!e) { 06258 ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n"); 06259 return; 06260 } 06261 *e++ = '\0'; 06262 /* XXX why skip non digits ? */ 06263 while (*e && !isdigit(*e)) 06264 e++; 06265 if (!*e) { 06266 ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n"); 06267 return; 06268 } 06269 if (sscanf(times, "%d:%d", &s1, &s2) != 2) { 06270 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times); 06271 return; 06272 } 06273 if (sscanf(e, "%d:%d", &e1, &e2) != 2) { 06274 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e); 06275 return; 06276 } 06277 /* XXX this needs to be optimized */ 06278 #if 1 06279 s1 = s1 * 30 + s2/2; 06280 if ((s1 < 0) || (s1 >= 24*30)) { 06281 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times); 06282 return; 06283 } 06284 e1 = e1 * 30 + e2/2; 06285 if ((e1 < 0) || (e1 >= 24*30)) { 06286 ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e); 06287 return; 06288 } 06289 /* Go through the time and enable each appropriate bit */ 06290 for (x=s1;x != e1;x = (x + 1) % (24 * 30)) { 06291 i->minmask[x/30] |= (1 << (x % 30)); 06292 } 06293 /* Do the last one */ 06294 i->minmask[x/30] |= (1 << (x % 30)); 06295 #else 06296 for (cth = 0; cth < 24; cth++) { 06297 /* Initialize masks to blank */ 06298 i->minmask[cth] = 0; 06299 for (ctm = 0; ctm < 30; ctm++) { 06300 if ( 06301 /* First hour with more than one hour */ 06302 (((cth == s1) && (ctm >= s2)) && 06303 ((cth < e1))) 06304 /* Only one hour */ 06305 || (((cth == s1) && (ctm >= s2)) && 06306 ((cth == e1) && (ctm <= e2))) 06307 /* In between first and last hours (more than 2 hours) */ 06308 || ((cth > s1) && 06309 (cth < e1)) 06310 /* Last hour with more than one hour */ 06311 || ((cth > s1) && 06312 ((cth == e1) && (ctm <= e2))) 06313 ) 06314 i->minmask[cth] |= (1 << (ctm / 2)); 06315 } 06316 } 06317 #endif 06318 /* All done */ 06319 return; 06320 }
static char* handle_debug_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Send ack once.
Definition at line 5283 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.
05284 { 05285 char *exten = NULL, *context = NULL; 05286 /* Variables used for different counters */ 05287 struct dialplan_counters counters; 05288 const char *incstack[AST_PBX_MAX_STACK]; 05289 05290 switch (cmd) { 05291 case CLI_INIT: 05292 e->command = "dialplan debug"; 05293 e->usage = 05294 "Usage: dialplan debug [context]\n" 05295 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n"; 05296 return NULL; 05297 case CLI_GENERATE: 05298 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 05299 } 05300 05301 memset(&counters, 0, sizeof(counters)); 05302 05303 if (a->argc != 2 && a->argc != 3) 05304 return CLI_SHOWUSAGE; 05305 05306 /* we obtain [exten@]context? if yes, split them ... */ 05307 /* note: we ignore the exten totally here .... */ 05308 if (a->argc == 3) { 05309 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 05310 context = ast_strdupa(a->argv[2]); 05311 exten = strsep(&context, "@"); 05312 /* change empty strings to NULL */ 05313 if (ast_strlen_zero(exten)) 05314 exten = NULL; 05315 } else { /* no '@' char, only context given */ 05316 context = a->argv[2]; 05317 } 05318 if (ast_strlen_zero(context)) 05319 context = NULL; 05320 } 05321 /* else Show complete dial plan, context and exten are NULL */ 05322 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 05323 05324 /* check for input failure and throw some error messages */ 05325 if (context && !counters.context_existence) { 05326 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 05327 return CLI_FAILURE; 05328 } 05329 05330 05331 ast_cli(a->fd,"-= %d %s. =-\n", 05332 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 05333 05334 /* everything ok */ 05335 return CLI_SUCCESS; 05336 }
static char* handle_set_chanvar | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5647 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().
05648 { 05649 struct ast_channel *chan; 05650 const char *chan_name, *var_name, *var_value; 05651 05652 switch (cmd) { 05653 case CLI_INIT: 05654 e->command = "dialplan set chanvar"; 05655 e->usage = 05656 "Usage: dialplan set chanvar <channel> <varname> <value>\n" 05657 " Set channel variable <varname> to <value>\n"; 05658 return NULL; 05659 case CLI_GENERATE: 05660 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 05661 } 05662 05663 if (a->argc != e->args + 3) 05664 return CLI_SHOWUSAGE; 05665 05666 chan_name = a->argv[e->args]; 05667 var_name = a->argv[e->args + 1]; 05668 var_value = a->argv[e->args + 2]; 05669 05670 if (!(chan = ast_get_channel_by_name_locked(chan_name))) { 05671 ast_cli(a->fd, "Channel '%s' not found\n", chan_name); 05672 return CLI_FAILURE; 05673 } 05674 05675 pbx_builtin_setvar_helper(chan, var_name, var_value); 05676 ast_channel_unlock(chan); 05677 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name); 05678 05679 return CLI_SUCCESS; 05680 }
static char* handle_set_chanvar_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5682 of file pbx.c.
References CLI_INIT, ast_cli_entry::command, and handle_set_chanvar().
05683 { 05684 char *res = handle_set_chanvar(e, cmd, a); 05685 if (cmd == CLI_INIT) 05686 e->command = "core set chanvar"; 05687 return res; 05688 }
static char* handle_set_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5690 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.
05691 { 05692 int oldval = 0; 05693 05694 switch (cmd) { 05695 case CLI_INIT: 05696 e->command = "dialplan set extenpatternmatchnew true"; 05697 e->usage = 05698 "Usage: dialplan set extenpatternmatchnew true|false\n" 05699 " Use the NEW extension pattern matching algorithm, true or false.\n"; 05700 return NULL; 05701 case CLI_GENERATE: 05702 return NULL; 05703 } 05704 05705 if (a->argc != 4) 05706 return CLI_SHOWUSAGE; 05707 05708 oldval = pbx_set_extenpatternmatchnew(1); 05709 05710 if (oldval) 05711 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n"); 05712 else 05713 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n"); 05714 05715 return CLI_SUCCESS; 05716 }
static char* handle_set_global | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5617 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().
05618 { 05619 switch (cmd) { 05620 case CLI_INIT: 05621 e->command = "dialplan set global"; 05622 e->usage = 05623 "Usage: dialplan set global <name> <value>\n" 05624 " Set global dialplan variable <name> to <value>\n"; 05625 return NULL; 05626 case CLI_GENERATE: 05627 return NULL; 05628 } 05629 05630 if (a->argc != e->args + 2) 05631 return CLI_SHOWUSAGE; 05632 05633 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]); 05634 ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]); 05635 05636 return CLI_SUCCESS; 05637 }
static char* handle_set_global_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5639 of file pbx.c.
References CLI_INIT, ast_cli_entry::command, and handle_set_global().
05640 { 05641 char *res = handle_set_global(e, cmd, a); 05642 if (cmd == CLI_INIT) 05643 e->command = "core set global"; 05644 return res; 05645 }
static char* handle_show_application | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4616 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.
04617 { 04618 struct ast_app *aa; 04619 int app, no_registered_app = 1; 04620 char *ret = NULL; 04621 int which = 0; 04622 int wordlen; 04623 04624 switch (cmd) { 04625 case CLI_INIT: 04626 e->command = "core show application"; 04627 e->usage = 04628 "Usage: core show application <application> [<application> [<application> [...]]]\n" 04629 " Describes a particular application.\n"; 04630 return NULL; 04631 case CLI_GENERATE: 04632 /* 04633 * There is a possibility to show informations about more than one 04634 * application at one time. You can type 'show application Dial Echo' and 04635 * you will see informations about these two applications ... 04636 */ 04637 wordlen = strlen(a->word); 04638 /* return the n-th [partial] matching entry */ 04639 AST_RWLIST_RDLOCK(&apps); 04640 AST_RWLIST_TRAVERSE(&apps, aa, list) { 04641 if (!strncasecmp(a->word, aa->name, wordlen) && ++which > a->n) { 04642 ret = ast_strdup(aa->name); 04643 break; 04644 } 04645 } 04646 AST_RWLIST_UNLOCK(&apps); 04647 04648 return ret; 04649 } 04650 04651 if (a->argc < 4) 04652 return CLI_SHOWUSAGE; 04653 04654 /* ... go through all applications ... */ 04655 AST_RWLIST_RDLOCK(&apps); 04656 AST_RWLIST_TRAVERSE(&apps, aa, list) { 04657 /* ... compare this application name with all arguments given 04658 * to 'show application' command ... */ 04659 for (app = 3; app < a->argc; app++) { 04660 if (!strcasecmp(aa->name, a->argv[app])) { 04661 /* Maximum number of characters added by terminal coloring is 22 */ 04662 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 04663 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 04664 int synopsis_size, description_size; 04665 04666 no_registered_app = 0; 04667 04668 if (aa->synopsis) 04669 synopsis_size = strlen(aa->synopsis) + 23; 04670 else 04671 synopsis_size = strlen("Not available") + 23; 04672 synopsis = alloca(synopsis_size); 04673 04674 if (aa->description) 04675 description_size = strlen(aa->description) + 23; 04676 else 04677 description_size = strlen("Not available") + 23; 04678 description = alloca(description_size); 04679 04680 if (synopsis && description) { 04681 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", aa->name); 04682 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 04683 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 04684 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 04685 term_color(synopsis, 04686 aa->synopsis ? aa->synopsis : "Not available", 04687 COLOR_CYAN, 0, synopsis_size); 04688 term_color(description, 04689 aa->description ? aa->description : "Not available", 04690 COLOR_CYAN, 0, description_size); 04691 04692 ast_cli(a->fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 04693 } else { 04694 /* ... one of our applications, show info ...*/ 04695 ast_cli(a->fd,"\n -= Info about application '%s' =- \n\n" 04696 "[Synopsis]\n %s\n\n" 04697 "[Description]\n%s\n", 04698 aa->name, 04699 aa->synopsis ? aa->synopsis : "Not available", 04700 aa->description ? aa->description : "Not available"); 04701 } 04702 } 04703 } 04704 } 04705 AST_RWLIST_UNLOCK(&apps); 04706 04707 /* we found at least one app? no? */ 04708 if (no_registered_app) { 04709 ast_cli(a->fd, "Your application(s) is (are) not registered\n"); 04710 return CLI_FAILURE; 04711 } 04712 04713 return CLI_SUCCESS; 04714 }
static char* handle_show_applications | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4872 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.
04873 { 04874 struct ast_app *aa; 04875 int like = 0, describing = 0; 04876 int total_match = 0; /* Number of matches in like clause */ 04877 int total_apps = 0; /* Number of apps registered */ 04878 static char* choices[] = { "like", "describing", NULL }; 04879 04880 switch (cmd) { 04881 case CLI_INIT: 04882 e->command = "core show applications [like|describing]"; 04883 e->usage = 04884 "Usage: core show applications [{like|describing} <text>]\n" 04885 " List applications which are currently available.\n" 04886 " If 'like', <text> will be a substring of the app name\n" 04887 " If 'describing', <text> will be a substring of the description\n"; 04888 return NULL; 04889 case CLI_GENERATE: 04890 return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n); 04891 } 04892 04893 AST_RWLIST_RDLOCK(&apps); 04894 04895 if (AST_RWLIST_EMPTY(&apps)) { 04896 ast_cli(a->fd, "There are no registered applications\n"); 04897 AST_RWLIST_UNLOCK(&apps); 04898 return CLI_SUCCESS; 04899 } 04900 04901 /* core list applications like <keyword> */ 04902 if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) { 04903 like = 1; 04904 } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) { 04905 describing = 1; 04906 } 04907 04908 /* core list applications describing <keyword1> [<keyword2>] [...] */ 04909 if ((!like) && (!describing)) { 04910 ast_cli(a->fd, " -= Registered Asterisk Applications =-\n"); 04911 } else { 04912 ast_cli(a->fd, " -= Matching Asterisk Applications =-\n"); 04913 } 04914 04915 AST_RWLIST_TRAVERSE(&apps, aa, list) { 04916 int printapp = 0; 04917 total_apps++; 04918 if (like) { 04919 if (strcasestr(aa->name, a->argv[4])) { 04920 printapp = 1; 04921 total_match++; 04922 } 04923 } else if (describing) { 04924 if (aa->description) { 04925 /* Match all words on command line */ 04926 int i; 04927 printapp = 1; 04928 for (i = 4; i < a->argc; i++) { 04929 if (!strcasestr(aa->description, a->argv[i])) { 04930 printapp = 0; 04931 } else { 04932 total_match++; 04933 } 04934 } 04935 } 04936 } else { 04937 printapp = 1; 04938 } 04939 04940 if (printapp) { 04941 ast_cli(a->fd," %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>"); 04942 } 04943 } 04944 if ((!like) && (!describing)) { 04945 ast_cli(a->fd, " -= %d Applications Registered =-\n",total_apps); 04946 } else { 04947 ast_cli(a->fd, " -= %d Applications Matching =-\n",total_match); 04948 } 04949 04950 AST_RWLIST_UNLOCK(&apps); 04951 04952 return CLI_SUCCESS; 04953 }
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 5585 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.
05586 { 05587 struct ast_channel *chan = NULL; 05588 struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */ 05589 05590 switch (cmd) { 05591 case CLI_INIT: 05592 e->command = "dialplan show chanvar"; 05593 e->usage = 05594 "Usage: dialplan show chanvar <channel>\n" 05595 " List current channel variables and their values\n"; 05596 return NULL; 05597 case CLI_GENERATE: 05598 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 05599 } 05600 05601 if (a->argc != e->args + 1) 05602 return CLI_SHOWUSAGE; 05603 05604 if (!(chan = ast_get_channel_by_name_locked(a->argv[e->args]))) { 05605 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]); 05606 return CLI_FAILURE; 05607 } 05608 05609 pbx_builtin_serialize_variables(chan, &vars); 05610 if (vars->str) { 05611 ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], vars->str); 05612 } 05613 ast_channel_unlock(chan); 05614 return CLI_SUCCESS; 05615 }
static char* handle_show_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5216 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.
05217 { 05218 char *exten = NULL, *context = NULL; 05219 /* Variables used for different counters */ 05220 struct dialplan_counters counters; 05221 const char *incstack[AST_PBX_MAX_STACK]; 05222 05223 switch (cmd) { 05224 case CLI_INIT: 05225 e->command = "dialplan show"; 05226 e->usage = 05227 "Usage: dialplan show [[exten@]context]\n" 05228 " Show dialplan\n"; 05229 return NULL; 05230 case CLI_GENERATE: 05231 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 05232 } 05233 05234 memset(&counters, 0, sizeof(counters)); 05235 05236 if (a->argc != 2 && a->argc != 3) 05237 return CLI_SHOWUSAGE; 05238 05239 /* we obtain [exten@]context? if yes, split them ... */ 05240 if (a->argc == 3) { 05241 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 05242 context = ast_strdupa(a->argv[2]); 05243 exten = strsep(&context, "@"); 05244 /* change empty strings to NULL */ 05245 if (ast_strlen_zero(exten)) 05246 exten = NULL; 05247 } else { /* no '@' char, only context given */ 05248 context = a->argv[2]; 05249 } 05250 if (ast_strlen_zero(context)) 05251 context = NULL; 05252 } 05253 /* else Show complete dial plan, context and exten are NULL */ 05254 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 05255 05256 /* check for input failure and throw some error messages */ 05257 if (context && !counters.context_existence) { 05258 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 05259 return CLI_FAILURE; 05260 } 05261 05262 if (exten && !counters.extension_existence) { 05263 if (context) 05264 ast_cli(a->fd, "There is no existence of %s@%s extension\n", 05265 exten, context); 05266 else 05267 ast_cli(a->fd, 05268 "There is no existence of '%s' extension in all contexts\n", 05269 exten); 05270 return CLI_FAILURE; 05271 } 05272 05273 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n", 05274 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 05275 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 05276 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 05277 05278 /* everything ok */ 05279 return CLI_SUCCESS; 05280 }
static char* handle_show_function | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2682 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.
02683 { 02684 struct ast_custom_function *acf; 02685 /* Maximum number of characters added by terminal coloring is 22 */ 02686 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 02687 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 02688 char stxtitle[40], *syntax = NULL; 02689 int synopsis_size, description_size, syntax_size; 02690 char *ret = NULL; 02691 int which = 0; 02692 int wordlen; 02693 02694 switch (cmd) { 02695 case CLI_INIT: 02696 e->command = "core show function"; 02697 e->usage = 02698 "Usage: core show function <function>\n" 02699 " Describe a particular dialplan function.\n"; 02700 return NULL; 02701 case CLI_GENERATE: 02702 wordlen = strlen(a->word); 02703 /* case-insensitive for convenience in this 'complete' function */ 02704 AST_RWLIST_RDLOCK(&acf_root); 02705 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 02706 if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) { 02707 ret = ast_strdup(acf->name); 02708 break; 02709 } 02710 } 02711 AST_RWLIST_UNLOCK(&acf_root); 02712 02713 return ret; 02714 } 02715 02716 if (a->argc < 4) 02717 return CLI_SHOWUSAGE; 02718 02719 if (!(acf = ast_custom_function_find(a->argv[3]))) { 02720 ast_cli(a->fd, "No function by that name registered.\n"); 02721 return CLI_FAILURE; 02722 02723 } 02724 02725 if (acf->synopsis) 02726 synopsis_size = strlen(acf->synopsis) + 23; 02727 else 02728 synopsis_size = strlen("Not available") + 23; 02729 synopsis = alloca(synopsis_size); 02730 02731 if (acf->desc) 02732 description_size = strlen(acf->desc) + 23; 02733 else 02734 description_size = strlen("Not available") + 23; 02735 description = alloca(description_size); 02736 02737 if (acf->syntax) 02738 syntax_size = strlen(acf->syntax) + 23; 02739 else 02740 syntax_size = strlen("Not available") + 23; 02741 syntax = alloca(syntax_size); 02742 02743 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name); 02744 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 02745 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 02746 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 02747 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 02748 term_color(syntax, 02749 acf->syntax ? acf->syntax : "Not available", 02750 COLOR_CYAN, 0, syntax_size); 02751 term_color(synopsis, 02752 acf->synopsis ? acf->synopsis : "Not available", 02753 COLOR_CYAN, 0, synopsis_size); 02754 term_color(description, 02755 acf->desc ? acf->desc : "Not available", 02756 COLOR_CYAN, 0, description_size); 02757 02758 ast_cli(a->fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description); 02759 02760 return CLI_SUCCESS; 02761 }
static char* handle_show_functions | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2643 of file pbx.c.
References ast_custom_function::acflist, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_custom_function::name, ast_custom_function::synopsis, ast_custom_function::syntax, and ast_cli_entry::usage.
02644 { 02645 struct ast_custom_function *acf; 02646 int count_acf = 0; 02647 int like = 0; 02648 02649 switch (cmd) { 02650 case CLI_INIT: 02651 e->command = "core show functions [like]"; 02652 e->usage = 02653 "Usage: core show functions [like <text>]\n" 02654 " List builtin functions, optionally only those matching a given string\n"; 02655 return NULL; 02656 case CLI_GENERATE: 02657 return NULL; 02658 } 02659 02660 if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) { 02661 like = 1; 02662 } else if (a->argc != 3) { 02663 return CLI_SHOWUSAGE; 02664 } 02665 02666 ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 02667 02668 AST_RWLIST_RDLOCK(&acf_root); 02669 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 02670 if (!like || strstr(acf->name, a->argv[4])) { 02671 count_acf++; 02672 ast_cli(a->fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis); 02673 } 02674 } 02675 AST_RWLIST_UNLOCK(&acf_root); 02676 02677 ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 02678 02679 return CLI_SUCCESS; 02680 }
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 5548 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().
05549 { 05550 int i = 0; 05551 struct ast_var_t *newvariable; 05552 05553 switch (cmd) { 05554 case CLI_INIT: 05555 e->command = "dialplan show globals"; 05556 e->usage = 05557 "Usage: dialplan show globals\n" 05558 " List current global dialplan variables and their values\n"; 05559 return NULL; 05560 case CLI_GENERATE: 05561 return NULL; 05562 } 05563 05564 ast_rwlock_rdlock(&globalslock); 05565 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 05566 i++; 05567 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 05568 } 05569 ast_rwlock_unlock(&globalslock); 05570 ast_cli(a->fd, "\n -- %d variable(s)\n", i); 05571 05572 return CLI_SUCCESS; 05573 }
static char* handle_show_globals_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5575 of file pbx.c.
References CLI_INIT, ast_cli_entry::command, and handle_show_globals().
05576 { 05577 05578 char *res = handle_show_globals(e, cmd, a); 05579 if (cmd == CLI_INIT) 05580 e->command = "core show globals"; 05581 return res; 05582 }
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 4788 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.
04789 { 04790 struct ast_hint *hint; 04791 int watchers; 04792 int num = 0, extenlen; 04793 struct ast_state_cb *watcher; 04794 04795 switch (cmd) { 04796 case CLI_INIT: 04797 e->command = "core show hint"; 04798 e->usage = 04799 "Usage: core show hint <exten>\n" 04800 " List registered hint\n"; 04801 return NULL; 04802 case CLI_GENERATE: 04803 return complete_core_show_hint(a->line, a->word, a->pos, a->n); 04804 } 04805 04806 if (a->argc < 4) 04807 return CLI_SHOWUSAGE; 04808 04809 AST_RWLIST_RDLOCK(&hints); 04810 if (AST_RWLIST_EMPTY(&hints)) { 04811 ast_cli(a->fd, "There are no registered dialplan hints\n"); 04812 AST_RWLIST_UNLOCK(&hints); 04813 return CLI_SUCCESS; 04814 } 04815 extenlen = strlen(a->argv[3]); 04816 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04817 if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) { 04818 watchers = 0; 04819 AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) { 04820 watchers++; 04821 } 04822 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 04823 ast_get_extension_name(hint->exten), 04824 ast_get_context_name(ast_get_extension_context(hint->exten)), 04825 ast_get_extension_app(hint->exten), 04826 ast_extension_state2str(hint->laststate), watchers); 04827 num++; 04828 } 04829 } 04830 AST_RWLIST_UNLOCK(&hints); 04831 if (!num) 04832 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]); 04833 else 04834 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]); 04835 return CLI_SUCCESS; 04836 }
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 4717 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.
04718 { 04719 struct ast_hint *hint; 04720 int num = 0; 04721 int watchers; 04722 struct ast_state_cb *watcher; 04723 04724 switch (cmd) { 04725 case CLI_INIT: 04726 e->command = "core show hints"; 04727 e->usage = 04728 "Usage: core show hints\n" 04729 " List registered hints\n"; 04730 return NULL; 04731 case CLI_GENERATE: 04732 return NULL; 04733 } 04734 04735 AST_RWLIST_RDLOCK(&hints); 04736 if (AST_RWLIST_EMPTY(&hints)) { 04737 ast_cli(a->fd, "There are no registered dialplan hints\n"); 04738 AST_RWLIST_UNLOCK(&hints); 04739 return CLI_SUCCESS; 04740 } 04741 /* ... we have hints ... */ 04742 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 04743 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04744 watchers = 0; 04745 AST_LIST_TRAVERSE(&hint->callbacks, watcher, entry) { 04746 watchers++; 04747 } 04748 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 04749 ast_get_extension_name(hint->exten), 04750 ast_get_context_name(ast_get_extension_context(hint->exten)), 04751 ast_get_extension_app(hint->exten), 04752 ast_extension_state2str(hint->laststate), watchers); 04753 num++; 04754 } 04755 ast_cli(a->fd, "----------------\n"); 04756 ast_cli(a->fd, "- %d hints registered\n", num); 04757 AST_RWLIST_UNLOCK(&hints); 04758 return CLI_SUCCESS; 04759 }
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 4840 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.
04841 { 04842 struct ast_switch *sw; 04843 04844 switch (cmd) { 04845 case CLI_INIT: 04846 e->command = "core show switches"; 04847 e->usage = 04848 "Usage: core show switches\n" 04849 " List registered switches\n"; 04850 return NULL; 04851 case CLI_GENERATE: 04852 return NULL; 04853 } 04854 04855 AST_RWLIST_RDLOCK(&switches); 04856 04857 if (AST_RWLIST_EMPTY(&switches)) { 04858 AST_RWLIST_UNLOCK(&switches); 04859 ast_cli(a->fd, "There are no registered alternative switches\n"); 04860 return CLI_SUCCESS; 04861 } 04862 04863 ast_cli(a->fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 04864 AST_RWLIST_TRAVERSE(&switches, sw, list) 04865 ast_cli(a->fd, "%s: %s\n", sw->name, sw->description); 04866 04867 AST_RWLIST_UNLOCK(&switches); 04868 04869 return CLI_SUCCESS; 04870 }
static int handle_statechange | ( | void * | datap | ) | [static] |
Definition at line 3324 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().
03325 { 03326 struct ast_hint *hint; 03327 struct statechange *sc = datap; 03328 03329 ast_rdlock_contexts(); 03330 AST_RWLIST_RDLOCK(&hints); 03331 03332 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03333 struct ast_state_cb *cblist; 03334 char buf[AST_MAX_EXTENSION]; 03335 char *parse = buf; 03336 char *cur; 03337 int state; 03338 03339 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf)); 03340 while ( (cur = strsep(&parse, "&")) ) { 03341 if (!strcasecmp(cur, sc->dev)) 03342 break; 03343 } 03344 if (!cur) 03345 continue; 03346 03347 /* Get device state for this hint */ 03348 state = ast_extension_state2(hint->exten); 03349 03350 if ((state == -1) || (state == hint->laststate)) 03351 continue; 03352 03353 /* Device state changed since last check - notify the watchers */ 03354 03355 /* For general callbacks */ 03356 AST_LIST_TRAVERSE(&statecbs, cblist, entry) { 03357 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 03358 } 03359 03360 /* For extension callbacks */ 03361 AST_LIST_TRAVERSE(&hint->callbacks, cblist, entry) { 03362 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 03363 } 03364 03365 hint->laststate = state; /* record we saw the change */ 03366 } 03367 AST_RWLIST_UNLOCK(&hints); 03368 ast_unlock_contexts(); 03369 ast_free(sc); 03370 return 0; 03371 }
static char* handle_unset_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5718 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.
05719 { 05720 int oldval = 0; 05721 05722 switch (cmd) { 05723 case CLI_INIT: 05724 e->command = "dialplan set extenpatternmatchnew false"; 05725 e->usage = 05726 "Usage: dialplan set extenpatternmatchnew true|false\n" 05727 " Use the NEW extension pattern matching algorithm, true or false.\n"; 05728 return NULL; 05729 case CLI_GENERATE: 05730 return NULL; 05731 } 05732 05733 if (a->argc != 4) 05734 return CLI_SHOWUSAGE; 05735 05736 oldval = pbx_set_extenpatternmatchnew(0); 05737 05738 if (!oldval) 05739 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n"); 05740 else 05741 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n"); 05742 05743 return CLI_SUCCESS; 05744 }
static int hashtab_compare_exten_labels | ( | const void * | ah_a, | |
const void * | ah_b | |||
) | [static] |
Definition at line 388 of file pbx.c.
References ast_exten::label.
Referenced by ast_add_extension2_lockopt().
00389 { 00390 const struct ast_exten *ac = ah_a; 00391 const struct ast_exten *bc = ah_b; 00392 return strcmp(ac->label, bc->label); 00393 }
static int hashtab_compare_exten_numbers | ( | const void * | ah_a, | |
const void * | ah_b | |||
) | [static] |
Definition at line 381 of file pbx.c.
References ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
00382 { 00383 const struct ast_exten *ac = ah_a; 00384 const struct ast_exten *bc = ah_b; 00385 return ac->priority != bc->priority; 00386 }
static int hashtab_compare_extens | ( | const void * | ha_a, | |
const void * | ah_b | |||
) | [static] |
Definition at line 362 of file pbx.c.
References ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
00363 { 00364 const struct ast_exten *ac = ah_a; 00365 const struct ast_exten *bc = ah_b; 00366 int x = strcmp(ac->exten, bc->exten); 00367 if (x) { /* if exten names are diff, then return */ 00368 return x; 00369 } 00370 00371 /* but if they are the same, do the cidmatch values match? */ 00372 if (ac->matchcid && bc->matchcid) { 00373 return strcmp(ac->cidmatch,bc->cidmatch); 00374 } else if (!ac->matchcid && !bc->matchcid) { 00375 return 0; /* if there's no matchcid on either side, then this is a match */ 00376 } else { 00377 return 1; /* if there's matchcid on one but not the other, they are different */ 00378 } 00379 }
static unsigned int hashtab_hash_extens | ( | const void * | obj | ) | [static] |
Definition at line 401 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().
00402 { 00403 const struct ast_exten *ac = obj; 00404 unsigned int x = ast_hashtab_hash_string(ac->exten); 00405 unsigned int y = 0; 00406 if (ac->matchcid) 00407 y = ast_hashtab_hash_string(ac->cidmatch); 00408 return x+y; 00409 }
static unsigned int hashtab_hash_labels | ( | const void * | obj | ) | [static] |
Definition at line 417 of file pbx.c.
References ast_hashtab_hash_string(), and ast_exten::label.
Referenced by ast_add_extension2_lockopt().
00418 { 00419 const struct ast_exten *ac = obj; 00420 return ast_hashtab_hash_string(ac->label); 00421 }
static unsigned int hashtab_hash_priority | ( | const void * | obj | ) | [static] |
Definition at line 411 of file pbx.c.
References ast_hashtab_hash_int(), and ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
00412 { 00413 const struct ast_exten *ac = obj; 00414 return ast_hashtab_hash_int(ac->priority); 00415 }
static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 1000 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
Referenced by pbx_find_extension().
01001 { 01002 if (!i->hastime) 01003 return 1; 01004 01005 return ast_check_timing(&(i->timing)); 01006 }
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 3943 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().
03944 { 03945 int failed = 0; 03946 double curloadavg; 03947 #if defined(HAVE_SYSINFO) 03948 long curfreemem; 03949 struct sysinfo sys_info; 03950 #endif 03951 03952 ast_mutex_lock(&maxcalllock); 03953 if (option_maxcalls) { 03954 if (countcalls >= option_maxcalls) { 03955 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 03956 failed = -1; 03957 } 03958 } 03959 if (option_maxload) { 03960 getloadavg(&curloadavg, 1); 03961 if (curloadavg >= option_maxload) { 03962 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 03963 failed = -1; 03964 } 03965 } 03966 #if defined(HAVE_SYSINFO) 03967 if (option_minmemfree) { 03968 if (!sysinfo(&sys_info)) { 03969 /* make sure that the free system memory is above the configured low watermark 03970 * convert the amount of freeram from mem_units to MB */ 03971 curfreemem = sys_info.freeram / sys_info.mem_unit; 03972 curfreemem /= 1024*1024; 03973 if (curfreemem < option_minmemfree) { 03974 ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree); 03975 failed = -1; 03976 } 03977 } 03978 } 03979 #endif 03980 03981 if (!failed) { 03982 countcalls++; 03983 totalcalls++; 03984 } 03985 ast_mutex_unlock(&maxcalllock); 03986 03987 return failed; 03988 }
static void insert_in_next_chars_alt_char_list | ( | struct match_char ** | parent_ptr, | |
struct match_char * | node | |||
) | [static] |
Definition at line 1401 of file pbx.c.
References match_char::alt_char, and match_char::specificity.
Referenced by add_pattern_node().
01402 { 01403 struct match_char *curr, *lcurr; 01404 01405 /* insert node into the tree at "current", so the alt_char list from current is 01406 sorted in increasing value as you go to the leaves */ 01407 if (!(*parent_ptr)) { 01408 *parent_ptr = node; 01409 } else { 01410 if ((*parent_ptr)->specificity > node->specificity){ 01411 /* insert at head */ 01412 node->alt_char = (*parent_ptr); 01413 *parent_ptr = node; 01414 } else { 01415 lcurr = *parent_ptr; 01416 for (curr=(*parent_ptr)->alt_char; curr; curr = curr->alt_char) { 01417 if (curr->specificity > node->specificity) { 01418 node->alt_char = curr; 01419 lcurr->alt_char = node; 01420 break; 01421 } 01422 lcurr = curr; 01423 } 01424 if (!curr) 01425 { 01426 lcurr->alt_char = node; 01427 } 01428 } 01429 } 01430 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 8630 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().
08631 { 08632 int x; 08633 08634 /* Initialize the PBX */ 08635 ast_verb(1, "Asterisk PBX Core Initializing\n"); 08636 if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) { 08637 ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n"); 08638 } 08639 08640 ast_verb(1, "Registering builtin applications:\n"); 08641 ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry)); 08642 __ast_custom_function_register(&exception_function, NULL); 08643 08644 /* Register builtin applications */ 08645 for (x = 0; x < sizeof(builtins) / sizeof(struct pbx_builtin); x++) { 08646 ast_verb(1, "[%s]\n", builtins[x].name); 08647 if (ast_register_application2(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description, NULL)) { 08648 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 08649 return -1; 08650 } 08651 } 08652 08653 /* Register manager application */ 08654 ast_manager_register2("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan, "List dialplan", mandescr_show_dialplan); 08655 08656 if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, NULL, 08657 AST_EVENT_IE_END))) { 08658 return -1; 08659 } 08660 08661 return 0; 08662 }
void log_match_char_tree | ( | struct match_char * | node, | |
char * | prefix | |||
) |
Definition at line 1103 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().
01104 { 01105 char extenstr[40]; 01106 struct ast_str *my_prefix = ast_str_alloca(1024); 01107 01108 extenstr[0] = '\0'; 01109 01110 if (node && node->exten && node->exten) 01111 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01112 01113 if (strlen(node->x) > 1) { 01114 ast_debug(1, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', 01115 node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"", 01116 node->exten ? node->exten->exten : "", extenstr); 01117 } else { 01118 ast_debug(1, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', 01119 node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"", 01120 node->exten ? node->exten->exten : "", extenstr); 01121 } 01122 01123 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01124 01125 if (node->next_char) 01126 log_match_char_tree(node->next_char, my_prefix->str); 01127 01128 if (node->alt_char) 01129 log_match_char_tree(node->alt_char, prefix); 01130 }
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 6173 of file pbx.c.
Referenced by get_range().
06174 { 06175 int i; 06176 06177 if (names) { 06178 for (i = 0; names[i]; i++) { 06179 if (!strcasecmp(s, names[i])) 06180 return i+1; 06181 } 06182 } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) { 06183 return i; 06184 } 06185 return 0; /* error return */ 06186 }
static void manager_dpsendack | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Send ack once.
Definition at line 5339 of file pbx.c.
References astman_send_listack(), and s.
Referenced by manager_show_dialplan_helper().
05340 { 05341 astman_send_listack(s, m, "DialPlan list will follow", "start"); 05342 }
static int manager_show_dialplan | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager listing of dial plan.
Definition at line 5485 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().
05486 { 05487 const char *exten, *context; 05488 const char *id = astman_get_header(m, "ActionID"); 05489 char idtext[256]; 05490 int res; 05491 05492 /* Variables used for different counters */ 05493 struct dialplan_counters counters; 05494 05495 if (!ast_strlen_zero(id)) 05496 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 05497 else 05498 idtext[0] = '\0'; 05499 05500 memset(&counters, 0, sizeof(counters)); 05501 05502 exten = astman_get_header(m, "Extension"); 05503 context = astman_get_header(m, "Context"); 05504 05505 res = manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL); 05506 05507 if (context && !counters.context_existence) { 05508 char errorbuf[BUFSIZ]; 05509 05510 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context); 05511 astman_send_error(s, m, errorbuf); 05512 return 0; 05513 } 05514 if (exten && !counters.extension_existence) { 05515 char errorbuf[BUFSIZ]; 05516 05517 if (context) 05518 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context); 05519 else 05520 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten); 05521 astman_send_error(s, m, errorbuf); 05522 return 0; 05523 } 05524 05525 manager_event(EVENT_FLAG_CONFIG, "ShowDialPlanComplete", 05526 "EventList: Complete\r\n" 05527 "ListItems: %d\r\n" 05528 "ListExtensions: %d\r\n" 05529 "ListPriorities: %d\r\n" 05530 "ListContexts: %d\r\n" 05531 "%s" 05532 "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext); 05533 05534 /* everything ok */ 05535 return 0; 05536 }
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 5348 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().
05352 { 05353 struct ast_context *c; 05354 int res = 0, old_total_exten = dpc->total_exten; 05355 05356 if (ast_strlen_zero(exten)) 05357 exten = NULL; 05358 if (ast_strlen_zero(context)) 05359 context = NULL; 05360 05361 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten); 05362 05363 /* try to lock contexts */ 05364 if (ast_rdlock_contexts()) { 05365 astman_send_error(s, m, "Failed to lock contexts"); 05366 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n"); 05367 return -1; 05368 } 05369 05370 c = NULL; /* walk all contexts ... */ 05371 while ( (c = ast_walk_contexts(c)) ) { 05372 struct ast_exten *e; 05373 struct ast_include *i; 05374 struct ast_ignorepat *ip; 05375 05376 if (context && strcmp(ast_get_context_name(c), context) != 0) 05377 continue; /* not the name we want */ 05378 05379 dpc->context_existence = 1; 05380 05381 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c)); 05382 05383 if (ast_rdlock_context(c)) { /* failed to lock */ 05384 ast_debug(3, "manager_show_dialplan: Failed to lock context\n"); 05385 continue; 05386 } 05387 05388 /* XXX note- an empty context is not printed */ 05389 e = NULL; /* walk extensions in context */ 05390 while ( (e = ast_walk_context_extensions(c, e)) ) { 05391 struct ast_exten *p; 05392 05393 /* looking for extension? is this our extension? */ 05394 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) { 05395 /* not the one we are looking for, continue */ 05396 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e)); 05397 continue; 05398 } 05399 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e)); 05400 05401 dpc->extension_existence = 1; 05402 05403 /* may we print context info? */ 05404 dpc->total_context++; 05405 dpc->total_exten++; 05406 05407 p = NULL; /* walk next extension peers */ 05408 while ( (p = ast_walk_extension_priorities(e, p)) ) { 05409 int prio = ast_get_extension_priority(p); 05410 05411 dpc->total_prio++; 05412 if (!dpc->total_items++) 05413 manager_dpsendack(s, m); 05414 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 05415 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) ); 05416 05417 /* XXX maybe make this conditional, if p != e ? */ 05418 if (ast_get_extension_label(p)) 05419 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p)); 05420 05421 if (prio == PRIORITY_HINT) { 05422 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p)); 05423 } else { 05424 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)); 05425 } 05426 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e)); 05427 } 05428 } 05429 05430 i = NULL; /* walk included and write info ... */ 05431 while ( (i = ast_walk_context_includes(c, i)) ) { 05432 if (exten) { 05433 /* Check all includes for the requested extension */ 05434 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i); 05435 } else { 05436 if (!dpc->total_items++) 05437 manager_dpsendack(s, m); 05438 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 05439 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)); 05440 astman_append(s, "\r\n"); 05441 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i)); 05442 } 05443 } 05444 05445 ip = NULL; /* walk ignore patterns and write info ... */ 05446 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 05447 const char *ipname = ast_get_ignorepat_name(ip); 05448 char ignorepat[AST_MAX_EXTENSION]; 05449 05450 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 05451 if (!exten || ast_extension_match(ignorepat, exten)) { 05452 if (!dpc->total_items++) 05453 manager_dpsendack(s, m); 05454 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 05455 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip)); 05456 astman_append(s, "\r\n"); 05457 } 05458 } 05459 if (!rinclude) { 05460 struct ast_sw *sw = NULL; 05461 while ( (sw = ast_walk_context_switches(c, sw)) ) { 05462 if (!dpc->total_items++) 05463 manager_dpsendack(s, m); 05464 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 05465 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)); 05466 astman_append(s, "\r\n"); 05467 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw)); 05468 } 05469 } 05470 05471 ast_unlock_context(c); 05472 } 05473 ast_unlock_contexts(); 05474 05475 if (dpc->total_exten == old_total_exten) { 05476 ast_debug(3, "manager_show_dialplan: Found nothing new\n"); 05477 /* Nothing new under the sun */ 05478 return -1; 05479 } else { 05480 return res; 05481 } 05482 }
static int matchcid | ( | const char * | cidpattern, | |
const char * | callerid | |||
) | [static] |
Definition at line 2038 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
02039 { 02040 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 02041 failing to get a number should count as a match, otherwise not */ 02042 02043 if (ast_strlen_zero(callerid)) 02044 return ast_strlen_zero(cidpattern) ? 1 : 0; 02045 02046 return ast_extension_match(cidpattern, callerid); 02047 }
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 1233 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().
01234 { 01235 struct match_char *p; /* note minimal stack storage requirements */ 01236 struct ast_exten pattern = { .label = label }; 01237 #ifdef DEBUG_THIS 01238 if (tree) 01239 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action)); 01240 else 01241 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action)); 01242 #endif 01243 for (p=tree; p; p=p->alt_char) { 01244 if (p->x[0] == 'N') { 01245 if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) { 01246 #define NEW_MATCHER_CHK_MATCH \ 01247 if (p->exten && !(*(str+1))) { /* if a shorter pattern matches along the way, might as well report it */ \ 01248 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \ 01249 update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted, p); \ 01250 if (!p->deleted) { \ 01251 if (action == E_FINDLABEL) { \ 01252 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \ 01253 ast_debug(4, "Found label in preferred extension\n"); \ 01254 return; \ 01255 } \ 01256 } else { \ 01257 ast_debug(4,"returning an exact match-- first found-- %s\n", p->exten->exten); \ 01258 return; /* the first match, by definition, will be the best, because of the sorted tree */ \ 01259 } \ 01260 } \ 01261 } \ 01262 } 01263 01264 #define NEW_MATCHER_RECURSE \ 01265 if (p->next_char && ( *(str+1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \ 01266 || p->next_char->x[0] == '!')) { \ 01267 if (*(str+1) || p->next_char->x[0] == '!') { \ 01268 new_find_extension(str+1, score, p->next_char, length+1, spec+p->specificity, callerid, label, action); \ 01269 if (score->exten) { \ 01270 ast_debug(4,"returning an exact match-- %s\n", score->exten->exten); \ 01271 return; /* the first match is all we need */ \ 01272 } \ 01273 } else { \ 01274 new_find_extension("/", score, p->next_char, length+1, spec+p->specificity, callerid, label, action); \ 01275 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \ 01276 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \ 01277 "NULL"); \ 01278 return; /* the first match is all we need */ \ 01279 } \ 01280 } \ 01281 } else if (p->next_char && !*(str+1)) { \ 01282 score->canmatch = 1; \ 01283 score->canmatch_exten = get_canmatch_exten(p); \ 01284 if (action == E_CANMATCH || action == E_MATCHMORE) { \ 01285 ast_debug(4,"returning a canmatch/matchmore--- str=%s\n", str); \ 01286 return; \ 01287 } \ 01288 } 01289 01290 NEW_MATCHER_CHK_MATCH; 01291 NEW_MATCHER_RECURSE; 01292 } 01293 } else if (p->x[0] == 'Z') { 01294 if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) { 01295 NEW_MATCHER_CHK_MATCH; 01296 NEW_MATCHER_RECURSE; 01297 } 01298 } else if (p->x[0] == 'X') { 01299 if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) { 01300 NEW_MATCHER_CHK_MATCH; 01301 NEW_MATCHER_RECURSE; 01302 } 01303 } else if (p->x[0] == '.' && p->x[1] == 0) { 01304 /* how many chars will the . match against? */ 01305 int i = 0; 01306 const char *str2 = str; 01307 while (*str2 && *str2 != '/') { 01308 str2++; 01309 i++; 01310 } 01311 if (p->exten && *str2 != '/') { 01312 update_scoreboard(score, length+i, spec+(i*p->specificity), p->exten, '.', callerid, p->deleted, p); 01313 if (score->exten) { 01314 ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten); 01315 return; /* the first match is all we need */ 01316 } 01317 } 01318 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01319 new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid, label, action); 01320 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01321 ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL"); 01322 return; /* the first match is all we need */ 01323 } 01324 } 01325 } else if (p->x[0] == '!' && p->x[1] == 0) { 01326 /* how many chars will the . match against? */ 01327 int i = 1; 01328 const char *str2 = str; 01329 while (*str2 && *str2 != '/') { 01330 str2++; 01331 i++; 01332 } 01333 if (p->exten && *str2 != '/') { 01334 update_scoreboard(score, length+1, spec+(p->specificity*i), p->exten, '!', callerid, p->deleted, p); 01335 if (score->exten) { 01336 ast_debug(4,"return because scoreboard has a '!' match--- %s\n", score->exten->exten); 01337 return; /* the first match is all we need */ 01338 } 01339 } 01340 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01341 new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid, label, action); 01342 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01343 ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01344 return; /* the first match is all we need */ 01345 } 01346 } 01347 } else if (p->x[0] == '/' && p->x[1] == 0) { 01348 /* the pattern in the tree includes the cid match! */ 01349 if (p->next_char && callerid && *callerid) { 01350 new_find_extension(callerid, score, p->next_char, length+1, spec, callerid, label, action); 01351 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01352 ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01353 return; /* the first match is all we need */ 01354 } 01355 } 01356 } else if (strchr(p->x, *str)) { 01357 ast_debug(4, "Nothing strange about this match\n"); 01358 NEW_MATCHER_CHK_MATCH; 01359 NEW_MATCHER_RECURSE; 01360 } 01361 } 01362 ast_debug(4,"return at end of func\n"); 01363 }
static int parse_variable_name | ( | char * | var, | |
int * | offset, | |||
int * | length, | |||
int * | isfunc | |||
) | [static] |
extract offset:length from variable name.
Definition at line 2373 of file pbx.c.
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
02374 { 02375 int parens = 0; 02376 02377 *offset = 0; 02378 *length = INT_MAX; 02379 *isfunc = 0; 02380 for (; *var; var++) { 02381 if (*var == '(') { 02382 (*isfunc)++; 02383 parens++; 02384 } else if (*var == ')') { 02385 parens--; 02386 } else if (*var == ':' && parens == 0) { 02387 *var++ = '\0'; 02388 sscanf(var, "%d:%d", offset, length); 02389 return 1; /* offset:length valid */ 02390 } 02391 } 02392 return 0; 02393 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 8510 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().
08511 { 08512 struct ast_var_t *vardata; 08513 08514 ast_rwlock_wrlock(&globalslock); 08515 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 08516 ast_var_delete(vardata); 08517 ast_rwlock_unlock(&globalslock); 08518 }
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 8280 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_eivr_getvariable(), ast_feature_interpret(), ast_monitor_stop(), ast_park_call_full(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), dahdi_call(), dahdi_hangup(), dial_exec_full(), do_forward(), do_timelimit(), dundi_exec(), dundi_helper(), findparkinglotname(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_exec(), import_ch(), leave_voicemail(), local_hangup(), local_read(), login_exec(), macro_fixup(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_space_reserve(), pickup_by_mark(), queue_exec(), real_ctx(), retrydial_exec(), ring_entry(), run_agi(), set_config_flags(), set_local_info(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), and update_bridge_vars().
08281 { 08282 struct ast_var_t *variables; 08283 const char *ret = NULL; 08284 int i; 08285 struct varshead *places[2] = { NULL, &globals }; 08286 08287 if (!name) 08288 return NULL; 08289 08290 if (chan) { 08291 ast_channel_lock(chan); 08292 places[0] = &chan->varshead; 08293 } 08294 08295 for (i = 0; i < 2; i++) { 08296 if (!places[i]) 08297 continue; 08298 if (places[i] == &globals) 08299 ast_rwlock_rdlock(&globalslock); 08300 AST_LIST_TRAVERSE(places[i], variables, entries) { 08301 if (!strcmp(name, ast_var_name(variables))) { 08302 ret = ast_var_value(variables); 08303 break; 08304 } 08305 } 08306 if (places[i] == &globals) 08307 ast_rwlock_unlock(&globalslock); 08308 if (ret) 08309 break; 08310 } 08311 08312 if (chan) 08313 ast_channel_unlock(chan); 08314 08315 return ret; 08316 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 8532 of file pbx.c.
References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), chan, LOG_WARNING, pbx_builtin_goto(), pbx_checkcondition(), and strsep().
08533 { 08534 char *condition, *branch1, *branch2, *branch; 08535 char *stringp; 08536 08537 if (ast_strlen_zero(data)) { 08538 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 08539 return 0; 08540 } 08541 08542 stringp = ast_strdupa(data); 08543 condition = strsep(&stringp,"?"); 08544 branch1 = strsep(&stringp,":"); 08545 branch2 = strsep(&stringp,""); 08546 branch = pbx_checkcondition(condition) ? branch1 : branch2; 08547 08548 if (ast_strlen_zero(branch)) { 08549 ast_debug(1, "Not taking any branch\n"); 08550 return 0; 08551 } 08552 08553 return pbx_builtin_goto(chan, branch); 08554 }
int pbx_builtin_importvar | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 8468 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.
08469 { 08470 char *name; 08471 char *value; 08472 char *channel; 08473 char tmp[VAR_BUF_SIZE]; 08474 static int deprecation_warning = 0; 08475 08476 if (ast_strlen_zero(data)) { 08477 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 08478 return 0; 08479 } 08480 tmp[0] = 0; 08481 if (!deprecation_warning) { 08482 ast_log(LOG_WARNING, "ImportVar is deprecated. Please use Set(varname=${IMPORT(channel,variable)}) instead.\n"); 08483 deprecation_warning = 1; 08484 } 08485 08486 value = ast_strdupa(data); 08487 name = strsep(&value,"="); 08488 channel = strsep(&value,","); 08489 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 08490 struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel); 08491 if (chan2) { 08492 char *s = alloca(strlen(value) + 4); 08493 if (s) { 08494 sprintf(s, "${%s}", value); 08495 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 08496 } 08497 ast_channel_unlock(chan2); 08498 } 08499 pbx_builtin_setvar_helper(chan, name, tmp); 08500 } 08501 08502 return(0); 08503 }
static int pbx_builtin_incomplete | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 7901 of file pbx.c.
References __ast_answer(), ast_channel::_state, ast_check_hangup(), AST_PBX_INCOMPLETE, AST_STATE_UP, ast_strlen_zero(), and chan.
07902 { 07903 char *options = data; 07904 int answer = 1; 07905 07906 /* Some channels can receive DTMF in unanswered state; some cannot */ 07907 if (!ast_strlen_zero(options) && strchr(options, 'n')) { 07908 answer = 0; 07909 } 07910 07911 /* If the channel is hungup, stop waiting */ 07912 if (ast_check_hangup(chan)) { 07913 return -1; 07914 } else if (chan->_state != AST_STATE_UP && answer) { 07915 __ast_answer(chan, 0, 1); 07916 } 07917 07918 return AST_PBX_INCOMPLETE; 07919 }
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 8318 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().
08319 { 08320 struct ast_var_t *newvariable; 08321 struct varshead *headp; 08322 08323 if (name[strlen(name)-1] == ')') { 08324 char *function = ast_strdupa(name); 08325 08326 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 08327 ast_func_write(chan, function, value); 08328 return; 08329 } 08330 08331 if (chan) { 08332 ast_channel_lock(chan); 08333 headp = &chan->varshead; 08334 } else { 08335 ast_rwlock_wrlock(&globalslock); 08336 headp = &globals; 08337 } 08338 08339 if (value) { 08340 if (headp == &globals) 08341 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 08342 newvariable = ast_var_assign(name, value); 08343 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 08344 } 08345 08346 if (chan) 08347 ast_channel_unlock(chan); 08348 else 08349 ast_rwlock_unlock(&globalslock); 08350 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
void * | vreason | |||
) |
Definition at line 2576 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().
02577 { 02578 const char *reason = vreason; 02579 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 02580 struct pbx_exception *exception = NULL; 02581 02582 if (!ds) { 02583 ds = ast_datastore_alloc(&exception_store_info, NULL); 02584 if (!ds) 02585 return -1; 02586 exception = ast_calloc(1, sizeof(struct pbx_exception)); 02587 if (!exception) { 02588 ast_datastore_free(ds); 02589 return -1; 02590 } 02591 if (ast_string_field_init(exception, 128)) { 02592 ast_free(exception); 02593 ast_datastore_free(ds); 02594 return -1; 02595 } 02596 ds->data = exception; 02597 ast_channel_datastore_add(chan, ds); 02598 } else 02599 exception = ds->data; 02600 02601 ast_string_field_set(exception, reason, reason); 02602 ast_string_field_set(exception, context, chan->context); 02603 ast_string_field_set(exception, exten, chan->exten); 02604 exception->priority = chan->priority; 02605 set_ext_pri(chan, "e", 0); 02606 return 0; 02607 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 8593 of file pbx.c.
References ast_say_character_str(), chan, and ast_channel::language.
08594 { 08595 int res = 0; 08596 08597 if (data) 08598 res = ast_say_character_str(chan, data, "", chan->language); 08599 return res; 08600 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 8584 of file pbx.c.
References ast_say_digit_str(), chan, and ast_channel::language.
08585 { 08586 int res = 0; 08587 08588 if (data) 08589 res = ast_say_digit_str(chan, data, "", chan->language); 08590 return res; 08591 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 8556 of file pbx.c.
References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), chan, ast_channel::language, LOG_WARNING, and strsep().
08557 { 08558 char tmp[256]; 08559 char *number = tmp; 08560 char *options; 08561 08562 if (ast_strlen_zero(data)) { 08563 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 08564 return -1; 08565 } 08566 ast_copy_string(tmp, data, sizeof(tmp)); 08567 strsep(&number, ","); 08568 options = strsep(&number, ","); 08569 if (options) { 08570 if ( strcasecmp(options, "f") && strcasecmp(options, "m") && 08571 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 08572 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 08573 return -1; 08574 } 08575 } 08576 08577 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 08578 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 08579 } 08580 08581 return 0; 08582 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 8602 of file pbx.c.
References ast_say_phonetic_str(), chan, and ast_channel::language.
08603 { 08604 int res = 0; 08605 08606 if (data) 08607 res = ast_say_phonetic_str(chan, data, "", chan->language); 08608 return res; 08609 }
int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
struct ast_str ** | buf | |||
) |
Definition at line 8248 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().
08249 { 08250 struct ast_var_t *variables; 08251 const char *var, *val; 08252 int total = 0; 08253 08254 if (!chan) 08255 return 0; 08256 08257 (*buf)->used = 0; 08258 (*buf)->str[0] = '\0'; 08259 08260 ast_channel_lock(chan); 08261 08262 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 08263 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 08264 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 08265 ) { 08266 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 08267 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 08268 break; 08269 } else 08270 total++; 08271 } else 08272 break; 08273 } 08274 08275 ast_channel_unlock(chan); 08276 08277 return total; 08278 }
int pbx_builtin_setvar | ( | struct ast_channel * | , | |
void * | ||||
) |
Definition at line 8409 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().
08410 { 08411 char *name, *value, *mydata; 08412 08413 if (ast_compat_app_set) { 08414 return pbx_builtin_setvar_multiple(chan, data); 08415 } 08416 08417 if (ast_strlen_zero(data)) { 08418 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 08419 return 0; 08420 } 08421 08422 mydata = ast_strdupa(data); 08423 name = strsep(&mydata, "="); 08424 value = mydata; 08425 if (strchr(name, ' ')) 08426 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 08427 08428 pbx_builtin_setvar_helper(chan, name, value); 08429 return(0); 08430 }
void pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Definition at line 8352 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE, AST_LIST_TRAVERSE, ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, 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_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(), 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().
08353 { 08354 struct ast_var_t *newvariable; 08355 struct varshead *headp; 08356 const char *nametail = name; 08357 08358 if (name[strlen(name) - 1] == ')') { 08359 char *function = ast_strdupa(name); 08360 08361 ast_func_write(chan, function, value); 08362 return; 08363 } 08364 08365 if (chan) { 08366 ast_channel_lock(chan); 08367 headp = &chan->varshead; 08368 } else { 08369 ast_rwlock_wrlock(&globalslock); 08370 headp = &globals; 08371 } 08372 08373 /* For comparison purposes, we have to strip leading underscores */ 08374 if (*nametail == '_') { 08375 nametail++; 08376 if (*nametail == '_') 08377 nametail++; 08378 } 08379 08380 AST_LIST_TRAVERSE (headp, newvariable, entries) { 08381 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) { 08382 /* there is already such a variable, delete it */ 08383 AST_LIST_REMOVE(headp, newvariable, entries); 08384 ast_var_delete(newvariable); 08385 break; 08386 } 08387 } 08388 08389 if (value) { 08390 if (headp == &globals) 08391 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 08392 newvariable = ast_var_assign(name, value); 08393 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 08394 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 08395 "Channel: %s\r\n" 08396 "Variable: %s\r\n" 08397 "Value: %s\r\n" 08398 "Uniqueid: %s\r\n", 08399 chan ? chan->name : "none", name, value, 08400 chan ? chan->uniqueid : "none"); 08401 } 08402 08403 if (chan) 08404 ast_channel_unlock(chan); 08405 else 08406 ast_rwlock_unlock(&globalslock); 08407 }
int pbx_builtin_setvar_multiple | ( | struct ast_channel * | , | |
void * | ||||
) |
Definition at line 8432 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(), set_queue_variables(), and try_calling().
08433 { 08434 char *data; 08435 int x; 08436 AST_DECLARE_APP_ARGS(args, 08437 AST_APP_ARG(pair)[24]; 08438 ); 08439 AST_DECLARE_APP_ARGS(pair, 08440 AST_APP_ARG(name); 08441 AST_APP_ARG(value); 08442 ); 08443 08444 if (ast_strlen_zero(vdata)) { 08445 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 08446 return 0; 08447 } 08448 08449 data = ast_strdupa(vdata); 08450 AST_STANDARD_APP_ARGS(args, data); 08451 08452 for (x = 0; x < args.argc; x++) { 08453 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 08454 if (pair.argc == 2) { 08455 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 08456 if (strchr(pair.name, ' ')) 08457 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); 08458 } else if (!chan) { 08459 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 08460 } else { 08461 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 08462 } 08463 } 08464 08465 return 0; 08466 }
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 8520 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().
08521 { 08522 int res; 08523 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 08524 return 0; 08525 } else if (sscanf(condition, "%d", &res) == 1) { /* Numbers are evaluated for truth */ 08526 return res; 08527 } else { /* Strings are true */ 08528 return 1; 08529 } 08530 }
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 932 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_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(), milliwatt_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), try_calling(), and tryexec_exec().
00935 { 00936 int res; 00937 struct ast_module_user *u = NULL; 00938 const char *saved_c_appl; 00939 const char *saved_c_data; 00940 00941 if (c->cdr && !ast_check_hangup(c)) 00942 ast_cdr_setapp(c->cdr, app->name, data); 00943 00944 /* save channel values */ 00945 saved_c_appl= c->appl; 00946 saved_c_data= c->data; 00947 00948 c->appl = app->name; 00949 c->data = data; 00950 if (app->module) 00951 u = __ast_module_user_add(app->module, c); 00952 if (!ast_strlen_zero(data) && strchr(data, '|') && !strchr(data, ',')) { 00953 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 00954 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 00955 app->name, (char *) data); 00956 } 00957 res = app->execute(c, S_OR(data, "")); 00958 if (app->module && u) 00959 __ast_module_user_remove(app->module, u); 00960 /* restore channel values */ 00961 c->appl = saved_c_appl; 00962 c->data = saved_c_data; 00963 return res; 00964 }
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 3134 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, 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().
03137 { 03138 struct ast_exten *e; 03139 struct ast_app *app; 03140 int res; 03141 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 03142 char passdata[EXT_DATA_SIZE]; 03143 03144 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 03145 03146 ast_rdlock_contexts(); 03147 if (found) 03148 *found = 0; 03149 03150 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 03151 if (e) { 03152 if (found) 03153 *found = 1; 03154 if (matching_action) { 03155 ast_unlock_contexts(); 03156 return -1; /* success, we found it */ 03157 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 03158 res = e->priority; 03159 ast_unlock_contexts(); 03160 return res; /* the priority we were looking for */ 03161 } else { /* spawn */ 03162 if (!e->cached_app) 03163 e->cached_app = pbx_findapp(e->app); 03164 app = e->cached_app; 03165 ast_unlock_contexts(); 03166 if (!app) { 03167 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 03168 return -1; 03169 } 03170 if (c->context != context) 03171 ast_copy_string(c->context, context, sizeof(c->context)); 03172 if (c->exten != exten) 03173 ast_copy_string(c->exten, exten, sizeof(c->exten)); 03174 c->priority = priority; 03175 pbx_substitute_variables(passdata, sizeof(passdata), c, e); 03176 #ifdef CHANNEL_TRACE 03177 ast_channel_trace_update(c); 03178 #endif 03179 ast_debug(1, "Launching '%s'\n", app->name); 03180 if (VERBOSITY_ATLEAST(3)) { 03181 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 03182 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 03183 exten, context, priority, 03184 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 03185 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 03186 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 03187 "in new stack"); 03188 } 03189 manager_event(EVENT_FLAG_DIALPLAN, "Newexten", 03190 "Channel: %s\r\n" 03191 "Context: %s\r\n" 03192 "Extension: %s\r\n" 03193 "Priority: %d\r\n" 03194 "Application: %s\r\n" 03195 "AppData: %s\r\n" 03196 "Uniqueid: %s\r\n", 03197 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 03198 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 03199 } 03200 } else if (q.swo) { /* not found here, but in another switch */ 03201 if (found) 03202 *found = 1; 03203 ast_unlock_contexts(); 03204 if (matching_action) { 03205 return -1; 03206 } else { 03207 if (!q.swo->exec) { 03208 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 03209 res = -1; 03210 } 03211 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 03212 } 03213 } else { /* not found anywhere, see what happened */ 03214 ast_unlock_contexts(); 03215 switch (q.status) { 03216 case STATUS_NO_CONTEXT: 03217 if (!matching_action && !combined_find_spawn) 03218 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context); 03219 break; 03220 case STATUS_NO_EXTENSION: 03221 if (!matching_action && !combined_find_spawn) 03222 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context); 03223 break; 03224 case STATUS_NO_PRIORITY: 03225 if (!matching_action && !combined_find_spawn) 03226 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context); 03227 break; 03228 case STATUS_NO_LABEL: 03229 if (context && !combined_find_spawn) 03230 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context); 03231 break; 03232 default: 03233 ast_debug(1, "Shouldn't happen!\n"); 03234 } 03235 03236 return (matching_action) ? 0 : -1; 03237 } 03238 }
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 2049 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().
02053 { 02054 int x, res; 02055 struct ast_context *tmp = NULL; 02056 struct ast_exten *e = NULL, *eroot = NULL; 02057 struct ast_include *i = NULL; 02058 struct ast_sw *sw = NULL; 02059 struct ast_exten pattern = {NULL, }; 02060 struct scoreboard score = {0, }; 02061 struct ast_str *tmpdata = NULL; 02062 02063 pattern.label = label; 02064 pattern.priority = priority; 02065 #ifdef NEED_DEBUG_HERE 02066 ast_log(LOG_NOTICE,"Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int)action); 02067 #endif 02068 02069 /* Initialize status if appropriate */ 02070 if (q->stacklen == 0) { 02071 q->status = STATUS_NO_CONTEXT; 02072 q->swo = NULL; 02073 q->data = NULL; 02074 q->foundcontext = NULL; 02075 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02076 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02077 return NULL; 02078 } 02079 02080 /* Check first to see if we've already been checked */ 02081 for (x = 0; x < q->stacklen; x++) { 02082 if (!strcasecmp(q->incstack[x], context)) 02083 return NULL; 02084 } 02085 02086 if (bypass) /* bypass means we only look there */ 02087 tmp = bypass; 02088 else { /* look in contexts */ 02089 struct fake_context item; 02090 02091 ast_copy_string(item.name, context, sizeof(item.name)); 02092 02093 tmp = ast_hashtab_lookup(contexts_table, &item); 02094 #ifdef NOTNOW 02095 tmp = NULL; 02096 while ((tmp = ast_walk_contexts(tmp)) ) { 02097 if (!strcmp(tmp->name, context)) 02098 break; 02099 } 02100 #endif 02101 if (!tmp) 02102 return NULL; 02103 02104 } 02105 02106 if (q->status < STATUS_NO_EXTENSION) 02107 q->status = STATUS_NO_EXTENSION; 02108 02109 /* Do a search for matching extension */ 02110 02111 eroot = NULL; 02112 score.total_specificity = 0; 02113 score.exten = 0; 02114 score.total_length = 0; 02115 if (!tmp->pattern_tree && tmp->root_table) 02116 { 02117 create_match_char_tree(tmp); 02118 #ifdef NEED_DEBUG 02119 ast_log(LOG_DEBUG,"Tree Created in context %s:\n", context); 02120 log_match_char_tree(tmp->pattern_tree," "); 02121 #endif 02122 } 02123 #ifdef NEED_DEBUG 02124 ast_log(LOG_NOTICE,"The Trie we are searching in:\n"); 02125 log_match_char_tree(tmp->pattern_tree, ":: "); 02126 #endif 02127 02128 do { 02129 if (!ast_strlen_zero(overrideswitch)) { 02130 char *osw = ast_strdupa(overrideswitch), *name; 02131 struct ast_switch *asw; 02132 ast_switch_f *aswf = NULL; 02133 char *datap; 02134 int eval = 0; 02135 02136 name = strsep(&osw, "/"); 02137 asw = pbx_findswitch(name); 02138 02139 if (!asw) { 02140 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 02141 break; 02142 } 02143 02144 if (osw && strchr(osw, '$')) { 02145 eval = 1; 02146 } 02147 02148 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02149 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!"); 02150 break; 02151 } else if (eval) { 02152 /* Substitute variables now */ 02153 pbx_substitute_variables_helper(chan, osw, tmpdata->str, tmpdata->len); 02154 datap = tmpdata->str; 02155 } else { 02156 datap = osw; 02157 } 02158 02159 /* equivalent of extension_match_core() at the switch level */ 02160 if (action == E_CANMATCH) 02161 aswf = asw->canmatch; 02162 else if (action == E_MATCHMORE) 02163 aswf = asw->matchmore; 02164 else /* action == E_MATCH */ 02165 aswf = asw->exists; 02166 if (!aswf) { 02167 res = 0; 02168 } else { 02169 if (chan) { 02170 ast_autoservice_start(chan); 02171 } 02172 res = aswf(chan, context, exten, priority, callerid, datap); 02173 if (chan) { 02174 ast_autoservice_stop(chan); 02175 } 02176 } 02177 if (res) { /* Got a match */ 02178 q->swo = asw; 02179 q->data = datap; 02180 q->foundcontext = context; 02181 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02182 return NULL; 02183 } 02184 } 02185 } while (0); 02186 02187 if (extenpatternmatchnew) { 02188 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02189 eroot = score.exten; 02190 02191 if (score.last_char == '!' && action == E_MATCHMORE) { 02192 /* We match an extension ending in '!'. 02193 * The decision in this case is final and is NULL (no match). 02194 */ 02195 #ifdef NEED_DEBUG_HERE 02196 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02197 #endif 02198 return NULL; 02199 } 02200 02201 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02202 q->status = STATUS_SUCCESS; 02203 #ifdef NEED_DEBUG_HERE 02204 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02205 #endif 02206 return score.canmatch_exten; 02207 } 02208 02209 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02210 if (score.node) { 02211 struct ast_exten *z = trie_find_next_match(score.node); 02212 if (z) { 02213 #ifdef NEED_DEBUG_HERE 02214 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02215 #endif 02216 } else { 02217 if (score.canmatch_exten) { 02218 #ifdef NEED_DEBUG_HERE 02219 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02220 #endif 02221 return score.canmatch_exten; 02222 } else { 02223 #ifdef NEED_DEBUG_HERE 02224 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02225 #endif 02226 } 02227 } 02228 return z; 02229 } 02230 #ifdef NEED_DEBUG_HERE 02231 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02232 #endif 02233 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02234 } 02235 02236 if (eroot) { 02237 /* found entry, now look for the right priority */ 02238 if (q->status < STATUS_NO_PRIORITY) 02239 q->status = STATUS_NO_PRIORITY; 02240 e = NULL; 02241 if (action == E_FINDLABEL && label ) { 02242 if (q->status < STATUS_NO_LABEL) 02243 q->status = STATUS_NO_LABEL; 02244 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02245 } else { 02246 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02247 } 02248 if (e) { /* found a valid match */ 02249 q->status = STATUS_SUCCESS; 02250 q->foundcontext = context; 02251 #ifdef NEED_DEBUG_HERE 02252 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 02253 #endif 02254 return e; 02255 } 02256 } 02257 } else { /* the old/current default exten pattern match algorithm */ 02258 02259 /* scan the list trying to match extension and CID */ 02260 eroot = NULL; 02261 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 02262 int match = extension_match_core(eroot->exten, exten, action); 02263 /* 0 on fail, 1 on match, 2 on earlymatch */ 02264 02265 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 02266 continue; /* keep trying */ 02267 if (match == 2 && action == E_MATCHMORE) { 02268 /* We match an extension ending in '!'. 02269 * The decision in this case is final and is NULL (no match). 02270 */ 02271 return NULL; 02272 } 02273 /* found entry, now look for the right priority */ 02274 if (q->status < STATUS_NO_PRIORITY) 02275 q->status = STATUS_NO_PRIORITY; 02276 e = NULL; 02277 if (action == E_FINDLABEL && label ) { 02278 if (q->status < STATUS_NO_LABEL) 02279 q->status = STATUS_NO_LABEL; 02280 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02281 } else { 02282 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02283 } 02284 #ifdef NOTNOW 02285 while ( (e = ast_walk_extension_priorities(eroot, e)) ) { 02286 /* Match label or priority */ 02287 if (action == E_FINDLABEL) { 02288 if (q->status < STATUS_NO_LABEL) 02289 q->status = STATUS_NO_LABEL; 02290 if (label && e->label && !strcmp(label, e->label)) 02291 break; /* found it */ 02292 } else if (e->priority == priority) { 02293 break; /* found it */ 02294 } /* else keep searching */ 02295 } 02296 #endif 02297 if (e) { /* found a valid match */ 02298 q->status = STATUS_SUCCESS; 02299 q->foundcontext = context; 02300 return e; 02301 } 02302 } 02303 } 02304 02305 02306 /* Check alternative switches */ 02307 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 02308 struct ast_switch *asw = pbx_findswitch(sw->name); 02309 ast_switch_f *aswf = NULL; 02310 char *datap; 02311 02312 if (!asw) { 02313 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 02314 continue; 02315 } 02316 /* Substitute variables now */ 02317 02318 if (sw->eval) { 02319 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02320 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 02321 continue; 02322 } 02323 pbx_substitute_variables_helper(chan, sw->data, tmpdata->str, tmpdata->len); 02324 } 02325 02326 /* equivalent of extension_match_core() at the switch level */ 02327 if (action == E_CANMATCH) 02328 aswf = asw->canmatch; 02329 else if (action == E_MATCHMORE) 02330 aswf = asw->matchmore; 02331 else /* action == E_MATCH */ 02332 aswf = asw->exists; 02333 datap = sw->eval ? tmpdata->str : sw->data; 02334 if (!aswf) 02335 res = 0; 02336 else { 02337 if (chan) 02338 ast_autoservice_start(chan); 02339 res = aswf(chan, context, exten, priority, callerid, datap); 02340 if (chan) 02341 ast_autoservice_stop(chan); 02342 } 02343 if (res) { /* Got a match */ 02344 q->swo = asw; 02345 q->data = datap; 02346 q->foundcontext = context; 02347 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02348 return NULL; 02349 } 02350 } 02351 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 02352 /* Now try any includes we have in this context */ 02353 for (i = tmp->includes; i; i = i->next) { 02354 if (include_valid(i)) { 02355 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 02356 #ifdef NEED_DEBUG_HERE 02357 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 02358 #endif 02359 return e; 02360 } 02361 if (q->swo) 02362 return NULL; 02363 } 02364 } 02365 return NULL; 02366 }
struct ast_app* pbx_findapp | ( | const char * | app | ) |
Look up an application.
app | name of the app |
Definition at line 972 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(), milliwatt_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), try_calling(), and tryexec_exec().
00973 { 00974 struct ast_app *tmp; 00975 00976 AST_RWLIST_RDLOCK(&apps); 00977 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 00978 if (!strcasecmp(tmp->name, app)) 00979 break; 00980 } 00981 AST_RWLIST_UNLOCK(&apps); 00982 00983 return tmp; 00984 }
static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static] |
Definition at line 986 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().
00987 { 00988 struct ast_switch *asw; 00989 00990 AST_RWLIST_RDLOCK(&switches); 00991 AST_RWLIST_TRAVERSE(&switches, asw, list) { 00992 if (!strcasecmp(asw->name, sw)) 00993 break; 00994 } 00995 AST_RWLIST_UNLOCK(&switches); 00996 00997 return asw; 00998 }
static int pbx_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string, | |||
int | async | |||
) | [static] |
Definition at line 8908 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, exten, LOG_WARNING, ast_channel::priority, and strsep().
Referenced by ast_async_parseable_goto(), and ast_parseable_goto().
08909 { 08910 char *exten, *pri, *context; 08911 char *stringp; 08912 int ipri; 08913 int mode = 0; 08914 08915 if (ast_strlen_zero(goto_string)) { 08916 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n"); 08917 return -1; 08918 } 08919 stringp = ast_strdupa(goto_string); 08920 context = strsep(&stringp, ","); /* guaranteed non-null */ 08921 exten = strsep(&stringp, ","); 08922 pri = strsep(&stringp, ","); 08923 if (!exten) { /* Only a priority in this one */ 08924 pri = context; 08925 exten = NULL; 08926 context = NULL; 08927 } else if (!pri) { /* Only an extension and priority in this one */ 08928 pri = exten; 08929 exten = context; 08930 context = NULL; 08931 } 08932 if (*pri == '+') { 08933 mode = 1; 08934 pri++; 08935 } else if (*pri == '-') { 08936 mode = -1; 08937 pri++; 08938 } 08939 if (sscanf(pri, "%d", &ipri) != 1) { 08940 if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten, 08941 pri, chan->cid.cid_num)) < 1) { 08942 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 08943 return -1; 08944 } else 08945 mode = 0; 08946 } 08947 /* At this point we have a priority and maybe an extension and a context */ 08948 08949 if (mode) 08950 ipri = chan->priority + (ipri * mode); 08951 08952 if (async) 08953 ast_async_goto(chan, context, exten, ipri); 08954 else 08955 ast_explicit_goto(chan, context, exten, ipri); 08956 08957 return 0; 08958 08959 }
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 2448 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().
02449 { 02450 const char not_found = '\0'; 02451 char *tmpvar; 02452 const char *s; /* the result */ 02453 int offset, length; 02454 int i, need_substring; 02455 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 02456 02457 if (c) { 02458 ast_channel_lock(c); 02459 places[0] = &c->varshead; 02460 } 02461 /* 02462 * Make a copy of var because parse_variable_name() modifies the string. 02463 * Then if called directly, we might need to run substring() on the result; 02464 * remember this for later in 'need_substring', 'offset' and 'length' 02465 */ 02466 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 02467 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 02468 02469 /* 02470 * Look first into predefined variables, then into variable lists. 02471 * Variable 's' points to the result, according to the following rules: 02472 * s == ¬_found (set at the beginning) means that we did not find a 02473 * matching variable and need to look into more places. 02474 * If s != ¬_found, s is a valid result string as follows: 02475 * s = NULL if the variable does not have a value; 02476 * you typically do this when looking for an unset predefined variable. 02477 * s = workspace if the result has been assembled there; 02478 * typically done when the result is built e.g. with an snprintf(), 02479 * so we don't need to do an additional copy. 02480 * s != workspace in case we have a string, that needs to be copied 02481 * (the ast_copy_string is done once for all at the end). 02482 * Typically done when the result is already available in some string. 02483 */ 02484 s = ¬_found; /* default value */ 02485 if (c) { /* This group requires a valid channel */ 02486 /* Names with common parts are looked up a piece at a time using strncmp. */ 02487 if (!strncmp(var, "CALL", 4)) { 02488 if (!strncmp(var + 4, "ING", 3)) { 02489 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 02490 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres); 02491 s = workspace; 02492 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 02493 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2); 02494 s = workspace; 02495 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 02496 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton); 02497 s = workspace; 02498 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 02499 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns); 02500 s = workspace; 02501 } 02502 } 02503 } else if (!strcmp(var, "HINT")) { 02504 s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL; 02505 } else if (!strcmp(var, "HINTNAME")) { 02506 s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL; 02507 } else if (!strcmp(var, "EXTEN")) { 02508 s = c->exten; 02509 } else if (!strcmp(var, "CONTEXT")) { 02510 s = c->context; 02511 } else if (!strcmp(var, "PRIORITY")) { 02512 snprintf(workspace, workspacelen, "%d", c->priority); 02513 s = workspace; 02514 } else if (!strcmp(var, "CHANNEL")) { 02515 s = c->name; 02516 } else if (!strcmp(var, "UNIQUEID")) { 02517 s = c->uniqueid; 02518 } else if (!strcmp(var, "HANGUPCAUSE")) { 02519 snprintf(workspace, workspacelen, "%d", c->hangupcause); 02520 s = workspace; 02521 } 02522 } 02523 if (s == ¬_found) { /* look for more */ 02524 if (!strcmp(var, "EPOCH")) { 02525 snprintf(workspace, workspacelen, "%u",(int)time(NULL)); 02526 s = workspace; 02527 } else if (!strcmp(var, "SYSTEMNAME")) { 02528 s = ast_config_AST_SYSTEM_NAME; 02529 } else if (!strcmp(var, "ENTITYID")) { 02530 ast_eid_to_str(workspace, workspacelen, &ast_eid_default); 02531 s = workspace; 02532 } 02533 } 02534 /* if not found, look into chanvars or global vars */ 02535 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 02536 struct ast_var_t *variables; 02537 if (!places[i]) 02538 continue; 02539 if (places[i] == &globals) 02540 ast_rwlock_rdlock(&globalslock); 02541 AST_LIST_TRAVERSE(places[i], variables, entries) { 02542 if (!strcasecmp(ast_var_name(variables), var)) { 02543 s = ast_var_value(variables); 02544 break; 02545 } 02546 } 02547 if (places[i] == &globals) 02548 ast_rwlock_unlock(&globalslock); 02549 } 02550 if (s == ¬_found || s == NULL) 02551 *ret = NULL; 02552 else { 02553 if (s != workspace) 02554 ast_copy_string(workspace, s, workspacelen); 02555 *ret = workspace; 02556 if (need_substring) 02557 *ret = substring(*ret, offset, length, workspace, workspacelen); 02558 } 02559 02560 if (c) 02561 ast_channel_unlock(c); 02562 }
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 4084 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
04085 { 04086 int oldval = autofallthrough; 04087 autofallthrough = newval; 04088 return oldval; 04089 }
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 4091 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
04092 { 04093 int oldval = extenpatternmatchnew; 04094 extenpatternmatchnew = newval; 04095 return oldval; 04096 }
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 4098 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
04099 { 04100 if (overrideswitch) { 04101 ast_free(overrideswitch); 04102 } 04103 if (!ast_strlen_zero(newval)) { 04104 overrideswitch = ast_strdup(newval); 04105 } else { 04106 overrideswitch = NULL; 04107 } 04108 }
static void pbx_substitute_variables | ( | char * | passdata, | |
int | datalen, | |||
struct ast_channel * | c, | |||
struct ast_exten * | e | |||
) | [static] |
Definition at line 3099 of file pbx.c.
References ast_copy_string(), ast_exten::data, and pbx_substitute_variables_helper().
Referenced by pbx_extension_helper().
03100 { 03101 const char *tmp; 03102 03103 /* Nothing more to do */ 03104 if (!e->data) 03105 return; 03106 03107 /* No variables or expressions in e->data, so why scan it? */ 03108 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) { 03109 ast_copy_string(passdata, e->data, datalen); 03110 return; 03111 } 03112 03113 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1); 03114 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 3089 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(), sqlite3_log(), store_curl(), substituted(), try_calling(), tryexec_exec(), and update_curl().
03090 { 03091 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count); 03092 }
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 2897 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().
02898 { 02899 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 02900 char *cp4; 02901 const char *tmp, *whereweare; 02902 int length, offset, offset2, isfunction; 02903 char *workspace = NULL; 02904 char *ltmp = NULL, *var = NULL; 02905 char *nextvar, *nextexp, *nextthing; 02906 char *vars, *vare; 02907 int pos, brackets, needsub, len; 02908 02909 *cp2 = 0; /* just in case nothing ends up there */ 02910 whereweare=tmp=cp1; 02911 while (!ast_strlen_zero(whereweare) && count) { 02912 /* Assume we're copying the whole remaining string */ 02913 pos = strlen(whereweare); 02914 nextvar = NULL; 02915 nextexp = NULL; 02916 nextthing = strchr(whereweare, '$'); 02917 if (nextthing) { 02918 switch (nextthing[1]) { 02919 case '{': 02920 nextvar = nextthing; 02921 pos = nextvar - whereweare; 02922 break; 02923 case '[': 02924 nextexp = nextthing; 02925 pos = nextexp - whereweare; 02926 break; 02927 default: 02928 pos = 1; 02929 } 02930 } 02931 02932 if (pos) { 02933 /* Can't copy more than 'count' bytes */ 02934 if (pos > count) 02935 pos = count; 02936 02937 /* Copy that many bytes */ 02938 memcpy(cp2, whereweare, pos); 02939 02940 count -= pos; 02941 cp2 += pos; 02942 whereweare += pos; 02943 *cp2 = 0; 02944 } 02945 02946 if (nextvar) { 02947 /* We have a variable. Find the start and end, and determine 02948 if we are going to have to recursively call ourselves on the 02949 contents */ 02950 vars = vare = nextvar + 2; 02951 brackets = 1; 02952 needsub = 0; 02953 02954 /* Find the end of it */ 02955 while (brackets && *vare) { 02956 if ((vare[0] == '$') && (vare[1] == '{')) { 02957 needsub++; 02958 } else if (vare[0] == '{') { 02959 brackets++; 02960 } else if (vare[0] == '}') { 02961 brackets--; 02962 } else if ((vare[0] == '$') && (vare[1] == '[')) 02963 needsub++; 02964 vare++; 02965 } 02966 if (brackets) 02967 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 02968 len = vare - vars - 1; 02969 02970 /* Skip totally over variable string */ 02971 whereweare += (len + 3); 02972 02973 if (!var) 02974 var = alloca(VAR_BUF_SIZE); 02975 02976 /* Store variable name (and truncate) */ 02977 ast_copy_string(var, vars, len + 1); 02978 02979 /* Substitute if necessary */ 02980 if (needsub) { 02981 if (!ltmp) 02982 ltmp = alloca(VAR_BUF_SIZE); 02983 02984 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 02985 vars = ltmp; 02986 } else { 02987 vars = var; 02988 } 02989 02990 if (!workspace) 02991 workspace = alloca(VAR_BUF_SIZE); 02992 02993 workspace[0] = '\0'; 02994 02995 parse_variable_name(vars, &offset, &offset2, &isfunction); 02996 if (isfunction) { 02997 /* Evaluate function */ 02998 if (c || !headp) 02999 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03000 else { 03001 struct varshead old; 03002 struct ast_channel *bogus = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars); 03003 if (bogus) { 03004 memcpy(&old, &bogus->varshead, sizeof(old)); 03005 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 03006 cp4 = ast_func_read(bogus, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03007 /* Don't deallocate the varshead that was passed in */ 03008 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 03009 ast_channel_free(bogus); 03010 } else 03011 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03012 } 03013 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03014 } else { 03015 /* Retrieve variable value */ 03016 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 03017 } 03018 if (cp4) { 03019 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 03020 03021 length = strlen(cp4); 03022 if (length > count) 03023 length = count; 03024 memcpy(cp2, cp4, length); 03025 count -= length; 03026 cp2 += length; 03027 *cp2 = 0; 03028 } 03029 } else if (nextexp) { 03030 /* We have an expression. Find the start and end, and determine 03031 if we are going to have to recursively call ourselves on the 03032 contents */ 03033 vars = vare = nextexp + 2; 03034 brackets = 1; 03035 needsub = 0; 03036 03037 /* Find the end of it */ 03038 while (brackets && *vare) { 03039 if ((vare[0] == '$') && (vare[1] == '[')) { 03040 needsub++; 03041 brackets++; 03042 vare++; 03043 } else if (vare[0] == '[') { 03044 brackets++; 03045 } else if (vare[0] == ']') { 03046 brackets--; 03047 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03048 needsub++; 03049 vare++; 03050 } 03051 vare++; 03052 } 03053 if (brackets) 03054 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03055 len = vare - vars - 1; 03056 03057 /* Skip totally over expression */ 03058 whereweare += (len + 3); 03059 03060 if (!var) 03061 var = alloca(VAR_BUF_SIZE); 03062 03063 /* Store variable name (and truncate) */ 03064 ast_copy_string(var, vars, len + 1); 03065 03066 /* Substitute if necessary */ 03067 if (needsub) { 03068 if (!ltmp) 03069 ltmp = alloca(VAR_BUF_SIZE); 03070 03071 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 03072 vars = ltmp; 03073 } else { 03074 vars = var; 03075 } 03076 03077 length = ast_expr(vars, cp2, count, c); 03078 03079 if (length) { 03080 ast_debug(1, "Expression result is '%s'\n", cp2); 03081 count -= length; 03082 cp2 += length; 03083 *cp2 = 0; 03084 } 03085 } 03086 } 03087 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 3094 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().
03095 { 03096 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count); 03097 }
static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 4012 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
04013 { 04014 /* Oh joyeous kernel, we're a new thread, with nothing to do but 04015 answer this channel and get it going. 04016 */ 04017 /* NOTE: 04018 The launcher of this function _MUST_ increment 'countcalls' 04019 before invoking the function; it will be decremented when the 04020 PBX has finished running on the channel 04021 */ 04022 struct ast_channel *c = data; 04023 04024 __ast_pbx_run(c, NULL); 04025 decrease_call_count(); 04026 04027 pthread_exit(NULL); 04028 04029 return NULL; 04030 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 4998 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().
04999 { 05000 int prio = ast_get_extension_priority(e); 05001 if (prio == PRIORITY_HINT) { 05002 snprintf(buf, buflen, "hint: %s", 05003 ast_get_extension_app(e)); 05004 } else { 05005 snprintf(buf, buflen, "%d. %s(%s)", 05006 prio, ast_get_extension_app(e), 05007 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 05008 } 05009 }
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 3652 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().
03653 { 03654 ast_channel_lock(c); 03655 ast_copy_string(c->exten, exten, sizeof(c->exten)); 03656 c->priority = pri; 03657 ast_channel_unlock(c); 03658 }
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 5163 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().
05164 { 05165 struct ast_context *c = NULL; 05166 int res = 0, old_total_exten = dpc->total_exten; 05167 05168 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n"); 05169 05170 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n"); 05171 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n"); 05172 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n"); 05173 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n"); 05174 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n"); 05175 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n"); 05176 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n"); 05177 ast_rdlock_contexts(); 05178 05179 /* walk all contexts ... */ 05180 while ( (c = ast_walk_contexts(c)) ) { 05181 int context_info_printed = 0; 05182 05183 if (context && strcmp(ast_get_context_name(c), context)) 05184 continue; /* skip this one, name doesn't match */ 05185 05186 dpc->context_existence = 1; 05187 05188 if (!c->pattern_tree) 05189 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */ 05190 05191 ast_rdlock_context(c); 05192 05193 dpc->total_context++; 05194 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 05195 ast_get_context_name(c), ast_get_context_registrar(c)); 05196 context_info_printed = 1; 05197 05198 if (c->pattern_tree) 05199 { 05200 cli_match_char_tree(c->pattern_tree, " ", fd); 05201 } else { 05202 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n"); 05203 } 05204 05205 ast_unlock_context(c); 05206 05207 /* if we print something in context, make an empty line */ 05208 if (context_info_printed) 05209 ast_cli(fd, "\n"); 05210 } 05211 ast_unlock_contexts(); 05212 05213 return (dpc->total_exten == old_total_exten) ? -1 : res; 05214 }
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 5012 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().
05013 { 05014 struct ast_context *c = NULL; 05015 int res = 0, old_total_exten = dpc->total_exten; 05016 05017 ast_rdlock_contexts(); 05018 05019 /* walk all contexts ... */ 05020 while ( (c = ast_walk_contexts(c)) ) { 05021 struct ast_exten *e; 05022 struct ast_include *i; 05023 struct ast_ignorepat *ip; 05024 char buf[256], buf2[256]; 05025 int context_info_printed = 0; 05026 05027 if (context && strcmp(ast_get_context_name(c), context)) 05028 continue; /* skip this one, name doesn't match */ 05029 05030 dpc->context_existence = 1; 05031 05032 ast_rdlock_context(c); 05033 05034 /* are we looking for exten too? if yes, we print context 05035 * only if we find our extension. 05036 * Otherwise print context even if empty ? 05037 * XXX i am not sure how the rinclude is handled. 05038 * I think it ought to go inside. 05039 */ 05040 if (!exten) { 05041 dpc->total_context++; 05042 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 05043 ast_get_context_name(c), ast_get_context_registrar(c)); 05044 context_info_printed = 1; 05045 } 05046 05047 /* walk extensions ... */ 05048 e = NULL; 05049 while ( (e = ast_walk_context_extensions(c, e)) ) { 05050 struct ast_exten *p; 05051 05052 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 05053 continue; /* skip, extension match failed */ 05054 05055 dpc->extension_existence = 1; 05056 05057 /* may we print context info? */ 05058 if (!context_info_printed) { 05059 dpc->total_context++; 05060 if (rinclude) { /* TODO Print more info about rinclude */ 05061 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 05062 ast_get_context_name(c), ast_get_context_registrar(c)); 05063 } else { 05064 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 05065 ast_get_context_name(c), ast_get_context_registrar(c)); 05066 } 05067 context_info_printed = 1; 05068 } 05069 dpc->total_prio++; 05070 05071 /* write extension name and first peer */ 05072 if (e->matchcid) 05073 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch); 05074 else 05075 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 05076 05077 print_ext(e, buf2, sizeof(buf2)); 05078 05079 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 05080 ast_get_extension_registrar(e)); 05081 05082 dpc->total_exten++; 05083 /* walk next extension peers */ 05084 p = e; /* skip the first one, we already got it */ 05085 while ( (p = ast_walk_extension_priorities(e, p)) ) { 05086 const char *el = ast_get_extension_label(p); 05087 dpc->total_prio++; 05088 if (el) 05089 snprintf(buf, sizeof(buf), " [%s]", el); 05090 else 05091 buf[0] = '\0'; 05092 print_ext(p, buf2, sizeof(buf2)); 05093 05094 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 05095 ast_get_extension_registrar(p)); 05096 } 05097 } 05098 05099 /* walk included and write info ... */ 05100 i = NULL; 05101 while ( (i = ast_walk_context_includes(c, i)) ) { 05102 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 05103 if (exten) { 05104 /* Check all includes for the requested extension */ 05105 if (includecount >= AST_PBX_MAX_STACK) { 05106 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n"); 05107 } else { 05108 int dupe = 0; 05109 int x; 05110 for (x = 0; x < includecount; x++) { 05111 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 05112 dupe++; 05113 break; 05114 } 05115 } 05116 if (!dupe) { 05117 includes[includecount] = ast_get_include_name(i); 05118 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 05119 } else { 05120 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 05121 } 05122 } 05123 } else { 05124 ast_cli(fd, " Include => %-45s [%s]\n", 05125 buf, ast_get_include_registrar(i)); 05126 } 05127 } 05128 05129 /* walk ignore patterns and write info ... */ 05130 ip = NULL; 05131 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 05132 const char *ipname = ast_get_ignorepat_name(ip); 05133 char ignorepat[AST_MAX_EXTENSION]; 05134 snprintf(buf, sizeof(buf), "'%s'", ipname); 05135 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 05136 if (!exten || ast_extension_match(ignorepat, exten)) { 05137 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 05138 buf, ast_get_ignorepat_registrar(ip)); 05139 } 05140 } 05141 if (!rinclude) { 05142 struct ast_sw *sw = NULL; 05143 while ( (sw = ast_walk_context_switches(c, sw)) ) { 05144 snprintf(buf, sizeof(buf), "'%s/%s'", 05145 ast_get_switch_name(sw), 05146 ast_get_switch_data(sw)); 05147 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 05148 buf, ast_get_switch_registrar(sw)); 05149 } 05150 } 05151 05152 ast_unlock_context(c); 05153 05154 /* if we print something in context, make an empty line */ 05155 if (context_info_printed) 05156 ast_cli(fd, "\n"); 05157 } 05158 ast_unlock_contexts(); 05159 05160 return (dpc->total_exten == old_total_exten) ? -1 : res; 05161 }
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 2406 of file pbx.c.
References ast_copy_string().
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
02407 { 02408 char *ret = workspace; 02409 int lr; /* length of the input string after the copy */ 02410 02411 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 02412 02413 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 02414 02415 /* Quick check if no need to do anything */ 02416 if (offset == 0 && length >= lr) /* take the whole string */ 02417 return ret; 02418 02419 if (offset < 0) { /* translate negative offset into positive ones */ 02420 offset = lr + offset; 02421 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 02422 offset = 0; 02423 } 02424 02425 /* too large offset result in empty string so we know what to return */ 02426 if (offset >= lr) 02427 return ret + lr; /* the final '\0' */ 02428 02429 ret += offset; /* move to the start position */ 02430 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 02431 ret[length] = '\0'; 02432 else if (length < 0) { 02433 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 02434 ret[lr + length - offset] = '\0'; 02435 else 02436 ret[0] = '\0'; 02437 } 02438 02439 return ret; 02440 }
static struct ast_exten* trie_find_next_match | ( | struct match_char * | node | ) | [static] |
Definition at line 1180 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().
01181 { 01182 struct match_char *m3; 01183 struct match_char *m4; 01184 struct ast_exten *e3; 01185 01186 if (node && node->x[0] == '.' && !node->x[1]) /* dot and ! will ALWAYS be next match in a matchmore */ 01187 return node->exten; 01188 01189 if (node && node->x[0] == '!' && !node->x[1]) 01190 return node->exten; 01191 01192 if (!node || !node->next_char) 01193 return NULL; 01194 01195 m3 = node->next_char; 01196 01197 if (m3->exten) 01198 return m3->exten; 01199 for(m4=m3->alt_char; m4; m4 = m4->alt_char) { 01200 if (m4->exten) 01201 return m4->exten; 01202 } 01203 for(m4=m3; m4; m4 = m4->alt_char) { 01204 e3 = trie_find_next_match(m3); 01205 if (e3) 01206 return e3; 01207 } 01208 return NULL; 01209 }
static void unreference_cached_app | ( | struct ast_app * | app | ) | [static] |
Definition at line 5775 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().
05776 { 05777 struct ast_context *context = NULL; 05778 struct ast_exten *eroot = NULL, *e = NULL; 05779 05780 ast_rdlock_contexts(); 05781 while ((context = ast_walk_contexts(context))) { 05782 while ((eroot = ast_walk_context_extensions(context, eroot))) { 05783 while ((e = ast_walk_extension_priorities(eroot, e))) { 05784 if (e->cached_app == app) 05785 e->cached_app = NULL; 05786 } 05787 } 05788 } 05789 ast_unlock_contexts(); 05790 05791 return; 05792 }
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 1087 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().
01088 { 01089 /* if this extension is marked as deleted, then skip this -- if it never shows 01090 on the scoreboard, it will never be found, nor will halt the traversal. */ 01091 if (deleted) 01092 return; 01093 board->total_specificity = spec; 01094 board->total_length = length; 01095 board->exten = exten; 01096 board->last_char = last; 01097 board->node = node; 01098 #ifdef NEED_DEBUG_HERE 01099 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec); 01100 #endif 01101 }
static void wait_for_hangup | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 7805 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().
07806 { 07807 int res; 07808 struct ast_frame *f; 07809 double waitsec; 07810 int waittime; 07811 07812 if (ast_strlen_zero(data) || (sscanf(data, "%lg", &waitsec) != 1) || (waitsec < 0)) 07813 waitsec = -1; 07814 if (waitsec > -1) { 07815 waittime = waitsec * 1000.0; 07816 ast_safe_sleep(chan, waittime); 07817 } else do { 07818 res = ast_waitfor(chan, -1); 07819 if (res < 0) 07820 return; 07821 f = ast_read(chan); 07822 if (f) 07823 ast_frfree(f); 07824 } while(f); 07825 }
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 732 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 729 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 730 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 435 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 432 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 2571 of file pbx.c.
Referenced by acf_exception_read(), and pbx_builtin_raise_exception().
int extenpatternmatchnew = 0 [static] |
Definition at line 428 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 425 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 424 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 434 of file pbx.c.
Referenced by decrease_call_count(), and increase_call_count().
char* months[] [static] |
char* overrideswitch = NULL [static] |
Definition at line 429 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 436 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] |