#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"
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 | 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_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 matchcid, const char *registrar) |
int | ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcid, 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) |
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 sync, 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 sync, 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 * | device_state_thread (void *data) |
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_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_set_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_set_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_set_global (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_application (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_applications (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_function (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_functions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_globals (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
CLI support for listing global variables in a parseable way. | |
static char * | handle_show_hint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
handle_show_hint: CLI support for listing registered dial plan hint | |
static char * | handle_show_hints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
handle_show_hints: CLI support for listing registered dial plan hints | |
static char * | handle_show_switches (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
handle_show_switches: CLI support for listing registered dial plan switches | |
static void | handle_statechange (const char *device) |
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_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) |
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_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[]) |
static int | statechange_queue (const char *dev) |
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 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 [] |
struct { | |
ast_cond_t cond | |
ast_mutex_t lock | |
struct { | |
statechange * first | |
statechange * last | |
} state_change_q | |
unsigned int stop:1 | |
pthread_t thread | |
} | device_state |
Data used by the device state thread. | |
static struct ast_event_sub * | device_state_sub |
Subscription for device state change events. | |
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 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) },} |
ast_state_cb * | statecbs |
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 962 of file pbx.c.
Referenced by handle_show_dialplan(), pbx_find_extension(), and show_dialplan_helper().
#define BACKGROUND_MATCHEXTEN (1 << 2) |
#define BACKGROUND_NOANSWER (1 << 1) |
#define BACKGROUND_PLAYBACK (1 << 3) |
#define BACKGROUND_SKIP (1 << 0) |
#define EXT_DATA_SIZE 8192 |
A new algorithm to do searching based on a 'compiled' pattern tree is introduced here, and shows a fairly flat (constant) search time, even for over 10000 patterns.
Also, using a hash table for context/priority name lookup can help prevent the find_extension routines from absorbing exponential cpu cycles as the number of contexts/priorities grow. I've previously tested find_extension with red-black trees, which have O(log2(n)) speed. Right now, I'm using hash tables, which do searches (ideally) in O(1) time. While these techniques do not yield much speed in small dialplans, they are worth the trouble in large dialplans.
Definition at line 92 of file pbx.c.
Referenced by pbx_extension_helper().
#define NEW_MATCHER_CHK_MATCH |
Referenced by new_find_extension().
#define NEW_MATCHER_RECURSE |
#define STATUS_NO_CONTEXT 1 |
Definition at line 2019 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_EXTENSION 2 |
Definition at line 2020 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_LABEL 4 |
Definition at line 2022 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_NO_PRIORITY 3 |
Definition at line 2021 of file pbx.c.
Referenced by pbx_extension_helper(), and pbx_find_extension().
#define STATUS_SUCCESS 5 |
#define VAR_BUF_SIZE 4096 |
Definition at line 97 of file pbx.c.
Referenced by ast_add_extension2_lockopt(), build_user_routes(), pbx_builtin_importvar(), pbx_substitute_variables_helper_full(), phoneprov_callback(), 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 7398 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().
07399 { 07400 struct ast_context *tmp, *tmpl=NULL; 07401 struct ast_exten *exten_item, *prio_item; 07402 07403 for (tmp = list; tmp; ) { 07404 struct ast_context *next = NULL; /* next starting point */ 07405 /* The following code used to skip forward to the next 07406 context with matching registrar, but this didn't 07407 make sense; individual priorities registrar'd to 07408 the matching registrar could occur in any context! */ 07409 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar); 07410 if (con) { 07411 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */ 07412 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar); 07413 if ( !strcasecmp(tmp->name, con->name) ) { 07414 break; /* found it */ 07415 } 07416 } 07417 } 07418 07419 if (!tmp) /* not found, we are done */ 07420 break; 07421 ast_wrlock_context(tmp); 07422 07423 if (registrar) { 07424 /* then search thru and remove any extens that match registrar. */ 07425 struct ast_hashtab_iter *exten_iter; 07426 struct ast_hashtab_iter *prio_iter; 07427 struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL; 07428 struct ast_include *i, *pi = NULL, *ni = NULL; 07429 struct ast_sw *sw = NULL; 07430 07431 /* remove any ignorepats whose registrar matches */ 07432 for (ip = tmp->ignorepats; ip; ip = ipn) { 07433 ipn = ip->next; 07434 if (!strcmp(ip->registrar, registrar)) { 07435 if (ipl) { 07436 ipl->next = ip->next; 07437 ast_free(ip); 07438 continue; /* don't change ipl */ 07439 } else { 07440 tmp->ignorepats = ip->next; 07441 ast_free(ip); 07442 continue; /* don't change ipl */ 07443 } 07444 } 07445 ipl = ip; 07446 } 07447 /* remove any includes whose registrar matches */ 07448 for (i = tmp->includes; i; i = ni) { 07449 ni = i->next; 07450 if (strcmp(i->registrar, registrar) == 0) { 07451 /* remove from list */ 07452 if (pi) { 07453 pi->next = i->next; 07454 /* free include */ 07455 ast_free(i); 07456 continue; /* don't change pi */ 07457 } else { 07458 tmp->includes = i->next; 07459 /* free include */ 07460 ast_free(i); 07461 continue; /* don't change pi */ 07462 } 07463 } 07464 pi = i; 07465 } 07466 /* remove any switches whose registrar matches */ 07467 AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) { 07468 if (strcmp(sw->registrar,registrar) == 0) { 07469 AST_LIST_REMOVE_CURRENT(list); 07470 ast_free(sw); 07471 } 07472 } 07473 AST_LIST_TRAVERSE_SAFE_END 07474 07475 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */ 07476 exten_iter = ast_hashtab_start_traversal(tmp->root_table); 07477 while ((exten_item=ast_hashtab_next(exten_iter))) { 07478 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 07479 while ((prio_item=ast_hashtab_next(prio_iter))) { 07480 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) { 07481 continue; 07482 } 07483 ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n", 07484 tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL); 07485 /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */ 07486 ast_context_remove_extension_callerid2(tmp, prio_item->exten, prio_item->priority, prio_item->cidmatch, 1, NULL, 1); 07487 } 07488 ast_hashtab_end_traversal(prio_iter); 07489 } 07490 ast_hashtab_end_traversal(exten_iter); 07491 } 07492 07493 /* delete the context if it's registrar matches, is empty, has refcount of 1, */ 07494 /* it's not empty, if it has includes, ignorepats, or switches that are registered from 07495 another registrar. It's not empty if there are any extensions */ 07496 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) { 07497 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 07498 ast_hashtab_remove_this_object(contexttab, tmp); 07499 07500 next = tmp->next; 07501 if (tmpl) 07502 tmpl->next = next; 07503 else 07504 contexts = next; 07505 /* Okay, now we're safe to let it go -- in a sense, we were 07506 ready to let it go as soon as we locked it. */ 07507 ast_unlock_context(tmp); 07508 __ast_internal_context_destroy(tmp); 07509 } else { 07510 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar, 07511 tmp->refcount, tmp->root); 07512 ast_unlock_context(tmp); 07513 next = tmp->next; 07514 tmpl = tmp; 07515 } 07516 } else if (con) { 07517 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar); 07518 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 07519 ast_hashtab_remove_this_object(contexttab, tmp); 07520 07521 next = tmp->next; 07522 if (tmpl) 07523 tmpl->next = next; 07524 else 07525 contexts = next; 07526 /* Okay, now we're safe to let it go -- in a sense, we were 07527 ready to let it go as soon as we locked it. */ 07528 ast_unlock_context(tmp); 07529 __ast_internal_context_destroy(tmp); 07530 } 07531 07532 /* if we have a specific match, we are done, otherwise continue */ 07533 tmp = con ? NULL : next; 07534 } 07535 }
int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
struct ast_module * | mod | |||
) |
Register a custom function.
Definition at line 2714 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().
02715 { 02716 struct ast_custom_function *cur; 02717 char tmps[80]; 02718 02719 if (!acf) 02720 return -1; 02721 02722 acf->mod = mod; 02723 02724 AST_RWLIST_WRLOCK(&acf_root); 02725 02726 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 02727 if (!strcmp(acf->name, cur->name)) { 02728 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 02729 AST_RWLIST_UNLOCK(&acf_root); 02730 return -1; 02731 } 02732 } 02733 02734 /* Store in alphabetical order */ 02735 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 02736 if (strcasecmp(acf->name, cur->name) < 0) { 02737 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 02738 break; 02739 } 02740 } 02741 AST_RWLIST_TRAVERSE_SAFE_END; 02742 if (!cur) 02743 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 02744 02745 AST_RWLIST_UNLOCK(&acf_root); 02746 02747 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 02748 02749 return 0; 02750 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 8606 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().
08607 { 08608 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 08609 08610 if (!chan) 08611 return -2; 08612 08613 if (context == NULL) 08614 context = chan->context; 08615 if (exten == NULL) 08616 exten = chan->exten; 08617 08618 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 08619 if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num)) 08620 return goto_func(chan, context, exten, priority); 08621 else 08622 return -3; 08623 }
static void __ast_internal_context_destroy | ( | struct ast_context * | con | ) | [static] |
Definition at line 7351 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().
07352 { 07353 struct ast_include *tmpi; 07354 struct ast_sw *sw; 07355 struct ast_exten *e, *el, *en; 07356 struct ast_ignorepat *ipi; 07357 struct ast_context *tmp = con; 07358 07359 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 07360 struct ast_include *tmpil = tmpi; 07361 tmpi = tmpi->next; 07362 ast_free(tmpil); 07363 } 07364 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 07365 struct ast_ignorepat *ipl = ipi; 07366 ipi = ipi->next; 07367 ast_free(ipl); 07368 } 07369 if (tmp->registrar) 07370 ast_free(tmp->registrar); 07371 07372 /* destroy the hash tabs */ 07373 if (tmp->root_table) { 07374 ast_hashtab_destroy(tmp->root_table, 0); 07375 } 07376 /* and destroy the pattern tree */ 07377 if (tmp->pattern_tree) 07378 destroy_pattern_tree(tmp->pattern_tree); 07379 07380 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 07381 ast_free(sw); 07382 for (e = tmp->root; e;) { 07383 for (en = e->peer; en;) { 07384 el = en; 07385 en = en->peer; 07386 destroy_exten(el); 07387 } 07388 el = e; 07389 e = e->next; 07390 destroy_exten(el); 07391 } 07392 tmp->root = NULL; 07393 ast_rwlock_destroy(&tmp->lock); 07394 ast_free(tmp); 07395 }
static enum ast_pbx_result __ast_pbx_run | ( | struct ast_channel * | c, | |
struct ast_pbx_args * | args | |||
) | [static] |
Definition at line 3659 of file pbx.c.
References ast_channel::_softhangup, ast_calloc, ast_copy_string(), ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_free, ast_log(), ast_set_flag, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_test_flag, ast_verb, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_pbx::dtimeout, ast_channel::exten, LOG_WARNING, ast_channel::name, ast_channel::pbx, pbx_builtin_raise_exception(), ast_channel::priority, ast_pbx::rtimeout, set_ext_pri(), and ast_channel::whentohangup.
Referenced by ast_pbx_run_args(), and pbx_thread().
03661 { 03662 int found = 0; /* set if we find at least one match */ 03663 int res = 0; 03664 int autoloopflag; 03665 int error = 0; /* set an error conditions */ 03666 03667 /* A little initial setup here */ 03668 if (c->pbx) { 03669 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 03670 /* XXX and now what ? */ 03671 ast_free(c->pbx); 03672 } 03673 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 03674 return -1; 03675 /* Set reasonable defaults */ 03676 c->pbx->rtimeout = 10; 03677 c->pbx->dtimeout = 5; 03678 03679 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 03680 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 03681 03682 /* Start by trying whatever the channel is set to */ 03683 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 03684 /* If not successful fall back to 's' */ 03685 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); 03686 /* XXX the original code used the existing priority in the call to 03687 * ast_exists_extension(), and reset it to 1 afterwards. 03688 * I believe the correct thing is to set it to 1 immediately. 03689 */ 03690 set_ext_pri(c, "s", 1); 03691 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 03692 /* JK02: And finally back to default if everything else failed */ 03693 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); 03694 ast_copy_string(c->context, "default", sizeof(c->context)); 03695 } 03696 } 03697 for (;;) { 03698 char dst_exten[256]; /* buffer to accumulate digits */ 03699 int pos = 0; /* XXX should check bounds */ 03700 int digit = 0; 03701 03702 /* loop on priorities in this context/exten */ 03703 while ( !(res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found,1))) { 03704 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) { 03705 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */ 03706 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 03707 c->whentohangup = 0; 03708 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 03709 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03710 pbx_builtin_raise_exception(c, "ABSOLUTETIMEOUT"); 03711 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 03712 c->whentohangup = 0; 03713 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 03714 } else if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 03715 c->_softhangup = 0; 03716 continue; 03717 } else if (ast_check_hangup(c)) { 03718 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n", 03719 c->exten, c->priority); 03720 error = 1; 03721 break; 03722 } 03723 c->priority++; 03724 } /* end while - from here on we can use 'break' to go out */ 03725 if (found && res) { 03726 /* Something bad happened, or a hangup has been requested. */ 03727 if (strchr("0123456789ABCDEF*#", res)) { 03728 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res); 03729 pos = 0; 03730 dst_exten[pos++] = digit = res; 03731 dst_exten[pos] = '\0'; 03732 } else { 03733 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 03734 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 03735 03736 if ((res == AST_PBX_ERROR) && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03737 /* if we are already on the 'e' exten, don't jump to it again */ 03738 if (!strcmp(c->exten, "e")) { 03739 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); 03740 error = 1; 03741 } else { 03742 pbx_builtin_raise_exception(c, "ERROR"); 03743 continue; 03744 } 03745 } 03746 03747 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 03748 c->_softhangup = 0; 03749 continue; 03750 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) { 03751 set_ext_pri(c, "T", 1); 03752 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 03753 c->whentohangup = 0; 03754 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 03755 continue; 03756 } else { 03757 if (c->cdr) 03758 ast_cdr_update(c); 03759 error = 1; 03760 break; 03761 } 03762 } 03763 } 03764 if (error) 03765 break; 03766 03767 /*!\note 03768 * We get here on a failure of some kind: non-existing extension or 03769 * hangup. We have options, here. We can either catch the failure 03770 * and continue, or we can drop out entirely. */ 03771 03772 if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) { 03773 /*!\note 03774 * If there is no match at priority 1, it is not a valid extension anymore. 03775 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if 03776 * neither exist. 03777 */ 03778 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 03779 ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 03780 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 03781 set_ext_pri(c, "i", 1); 03782 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03783 pbx_builtin_raise_exception(c, "INVALID"); 03784 } else { 03785 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 03786 c->name, c->exten, c->context); 03787 error = 1; /* we know what to do with it */ 03788 break; 03789 } 03790 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 03791 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 03792 c->_softhangup = 0; 03793 } else { /* keypress received, get more digits for a full extension */ 03794 int waittime = 0; 03795 if (digit) 03796 waittime = c->pbx->dtimeout; 03797 else if (!autofallthrough) 03798 waittime = c->pbx->rtimeout; 03799 if (!waittime) { 03800 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 03801 if (!status) 03802 status = "UNKNOWN"; 03803 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 03804 if (!strcasecmp(status, "CONGESTION")) 03805 res = pbx_builtin_congestion(c, "10"); 03806 else if (!strcasecmp(status, "CHANUNAVAIL")) 03807 res = pbx_builtin_congestion(c, "10"); 03808 else if (!strcasecmp(status, "BUSY")) 03809 res = pbx_builtin_busy(c, "10"); 03810 error = 1; /* XXX disable message */ 03811 break; /* exit from the 'for' loop */ 03812 } 03813 03814 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 03815 break; 03816 if (ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */ 03817 set_ext_pri(c, dst_exten, 1); 03818 else { 03819 /* No such extension */ 03820 if (!ast_strlen_zero(dst_exten)) { 03821 /* An invalid extension */ 03822 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 03823 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 03824 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 03825 set_ext_pri(c, "i", 1); 03826 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03827 pbx_builtin_raise_exception(c, "INVALID"); 03828 } else { 03829 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context); 03830 found = 1; /* XXX disable message */ 03831 break; 03832 } 03833 } else { 03834 /* A simple timeout */ 03835 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) { 03836 ast_verb(3, "Timeout on %s\n", c->name); 03837 set_ext_pri(c, "t", 1); 03838 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) { 03839 pbx_builtin_raise_exception(c, "RESPONSETIMEOUT"); 03840 } else { 03841 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); 03842 found = 1; /* XXX disable message */ 03843 break; 03844 } 03845 } 03846 } 03847 if (c->cdr) { 03848 ast_verb(2, "CDR updated on %s\n",c->name); 03849 ast_cdr_update(c); 03850 } 03851 } 03852 } 03853 03854 if (!found && !error) { 03855 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 03856 } 03857 03858 if (!args || !args->no_hangup_chan) { 03859 ast_softhangup(c, c->hangupcause ? c->hangupcause : AST_CAUSE_NORMAL_CLEARING); 03860 } 03861 03862 if ((!args || !args->no_hangup_chan) && 03863 !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) && 03864 ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) { 03865 set_ext_pri(c, "h", 1); 03866 if (c->cdr && ast_opt_end_cdr_before_h_exten) { 03867 ast_cdr_end(c->cdr); 03868 } 03869 while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found, 1)) == 0) { 03870 c->priority++; 03871 } 03872 if (found && res) { 03873 /* Something bad happened, or a hangup has been requested. */ 03874 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 03875 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 03876 } 03877 } 03878 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 03879 ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */ 03880 pbx_destroy(c->pbx); 03881 c->pbx = NULL; 03882 03883 if (!args || !args->no_hangup_chan) { 03884 ast_hangup(c); 03885 } 03886 03887 return 0; 03888 }
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 1797 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, LOG_NOTICE, and LOG_WARNING.
Referenced by extension_match_core().
01798 { 01799 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 01800 01801 #ifdef NEED_DEBUG_HERE 01802 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode); 01803 #endif 01804 01805 if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */ 01806 #ifdef NEED_DEBUG_HERE 01807 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n"); 01808 #endif 01809 return 1; 01810 } 01811 01812 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 01813 int ld = strlen(data), lp = strlen(pattern); 01814 01815 if (lp < ld) { /* pattern too short, cannot match */ 01816 #ifdef NEED_DEBUG_HERE 01817 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n"); 01818 #endif 01819 return 0; 01820 } 01821 /* depending on the mode, accept full or partial match or both */ 01822 if (mode == E_MATCH) { 01823 #ifdef NEED_DEBUG_HERE 01824 ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data); 01825 #endif 01826 return !strcmp(pattern, data); /* 1 on match, 0 on fail */ 01827 } 01828 if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */ 01829 #ifdef NEED_DEBUG_HERE 01830 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld); 01831 #endif 01832 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 01833 } else { 01834 #ifdef NEED_DEBUG_HERE 01835 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data); 01836 #endif 01837 return 0; 01838 } 01839 } 01840 pattern++; /* skip leading _ */ 01841 /* 01842 * XXX below we stop at '/' which is a separator for the CID info. However we should 01843 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 01844 */ 01845 while (*data && *pattern && *pattern != '/') { 01846 const char *end; 01847 01848 if (*data == '-') { /* skip '-' in data (just a separator) */ 01849 data++; 01850 continue; 01851 } 01852 switch (toupper(*pattern)) { 01853 case '[': /* a range */ 01854 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */ 01855 if (end == NULL) { 01856 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 01857 return 0; /* unconditional failure */ 01858 } 01859 for (pattern++; pattern != end; pattern++) { 01860 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 01861 if (*data >= pattern[0] && *data <= pattern[2]) 01862 break; /* match found */ 01863 else { 01864 pattern += 2; /* skip a total of 3 chars */ 01865 continue; 01866 } 01867 } else if (*data == pattern[0]) 01868 break; /* match found */ 01869 } 01870 if (pattern == end) { 01871 #ifdef NEED_DEBUG_HERE 01872 ast_log(LOG_NOTICE,"return (0) when pattern==end\n"); 01873 #endif 01874 return 0; 01875 } 01876 pattern = end; /* skip and continue */ 01877 break; 01878 case 'N': 01879 if (*data < '2' || *data > '9') { 01880 #ifdef NEED_DEBUG_HERE 01881 ast_log(LOG_NOTICE,"return (0) N is matched\n"); 01882 #endif 01883 return 0; 01884 } 01885 break; 01886 case 'X': 01887 if (*data < '0' || *data > '9') { 01888 #ifdef NEED_DEBUG_HERE 01889 ast_log(LOG_NOTICE,"return (0) X is matched\n"); 01890 #endif 01891 return 0; 01892 } 01893 break; 01894 case 'Z': 01895 if (*data < '1' || *data > '9') { 01896 #ifdef NEED_DEBUG_HERE 01897 ast_log(LOG_NOTICE,"return (0) Z is matched\n"); 01898 #endif 01899 return 0; 01900 } 01901 break; 01902 case '.': /* Must match, even with more digits */ 01903 #ifdef NEED_DEBUG_HERE 01904 ast_log(LOG_NOTICE,"return (1) when '.' is matched\n"); 01905 #endif 01906 return 1; 01907 case '!': /* Early match */ 01908 #ifdef NEED_DEBUG_HERE 01909 ast_log(LOG_NOTICE,"return (2) when '!' is matched\n"); 01910 #endif 01911 return 2; 01912 case ' ': 01913 case '-': /* Ignore these in patterns */ 01914 data--; /* compensate the final data++ */ 01915 break; 01916 default: 01917 if (*data != *pattern) { 01918 #ifdef NEED_DEBUG_HERE 01919 ast_log(LOG_NOTICE,"return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern); 01920 #endif 01921 return 0; 01922 } 01923 01924 } 01925 data++; 01926 pattern++; 01927 } 01928 if (*data) /* data longer than pattern, no match */ { 01929 #ifdef NEED_DEBUG_HERE 01930 ast_log(LOG_NOTICE,"return (0) when data longer than pattern\n"); 01931 #endif 01932 return 0; 01933 } 01934 01935 /* 01936 * match so far, but ran off the end of the data. 01937 * Depending on what is next, determine match or not. 01938 */ 01939 if (*pattern == '\0' || *pattern == '/') { /* exact match */ 01940 #ifdef NEED_DEBUG_HERE 01941 ast_log(LOG_NOTICE,"at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1); 01942 #endif 01943 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 01944 } else if (*pattern == '!') { /* early match */ 01945 #ifdef NEED_DEBUG_HERE 01946 ast_log(LOG_NOTICE,"at end, return (2) when '!' is matched\n"); 01947 #endif 01948 return 2; 01949 } else { /* partial match */ 01950 #ifdef NEED_DEBUG_HERE 01951 ast_log(LOG_NOTICE,"at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1); 01952 #endif 01953 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 01954 } 01955 }
static int acf_exception_read | ( | struct ast_channel * | chan, | |
const char * | name, | |||
char * | data, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 2531 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.
02532 { 02533 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 02534 struct pbx_exception *exception = NULL; 02535 if (!ds || !ds->data) 02536 return -1; 02537 exception = ds->data; 02538 if (!strcasecmp(data, "REASON")) 02539 ast_copy_string(buf, exception->reason, buflen); 02540 else if (!strcasecmp(data, "CONTEXT")) 02541 ast_copy_string(buf, exception->context, buflen); 02542 else if (!strncasecmp(data, "EXTEN", 5)) 02543 ast_copy_string(buf, exception->exten, buflen); 02544 else if (!strcasecmp(data, "PRIORITY")) 02545 snprintf(buf, buflen, "%d", exception->priority); 02546 else 02547 return -1; 02548 return 0; 02549 }
static struct match_char * add_exten_to_pattern_tree | ( | struct ast_context * | con, | |
struct ast_exten * | e1, | |||
int | findonly | |||
) | [static] |
Definition at line 1465 of file pbx.c.
References add_pattern_node(), already_in_tree(), 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().
01466 { 01467 struct match_char *m1 = NULL, *m2 = NULL, **m0; 01468 int specif; 01469 int already; 01470 int pattern = 0; 01471 char buf[256]; 01472 char extenbuf[512]; 01473 char *s1 = extenbuf; 01474 int l1 = strlen(e1->exten) + strlen(e1->cidmatch) + 2; 01475 01476 01477 strncpy(extenbuf,e1->exten,sizeof(extenbuf)); 01478 if (e1->matchcid && l1 <= sizeof(extenbuf)) { 01479 strcat(extenbuf,"/"); 01480 strcat(extenbuf,e1->cidmatch); 01481 } else if (l1 > sizeof(extenbuf)) { 01482 ast_log(LOG_ERROR,"The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", e1->exten, e1->cidmatch); 01483 return 0; 01484 } 01485 #ifdef NEED_DEBUG 01486 ast_log(LOG_DEBUG,"Adding exten %s%c%s to tree\n", s1, e1->matchcid? '/':' ', e1->matchcid? e1->cidmatch : ""); 01487 #endif 01488 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */ 01489 m0 = &con->pattern_tree; 01490 already = 1; 01491 01492 if ( *s1 == '_') { 01493 pattern = 1; 01494 s1++; 01495 } 01496 while( *s1 ) { 01497 if (pattern && *s1 == '[' && *(s1-1) != '\\') { 01498 char *s2 = buf; 01499 buf[0] = 0; 01500 s1++; /* get past the '[' */ 01501 while (*s1 != ']' && *(s1-1) != '\\' ) { 01502 if (*s1 == '\\') { 01503 if (*(s1+1) == ']') { 01504 *s2++ = ']'; 01505 s1++;s1++; 01506 } else if (*(s1+1) == '\\') { 01507 *s2++ = '\\'; 01508 s1++;s1++; 01509 } else if (*(s1+1) == '-') { 01510 *s2++ = '-'; 01511 s1++; s1++; 01512 } else if (*(s1+1) == '[') { 01513 *s2++ = '['; 01514 s1++; s1++; 01515 } 01516 } else if (*s1 == '-') { /* remember to add some error checking to all this! */ 01517 char s3 = *(s1-1); 01518 char s4 = *(s1+1); 01519 for (s3++; s3 <= s4; s3++) { 01520 *s2++ = s3; 01521 } 01522 s1++; s1++; 01523 } else if (*s1 == '\0') { 01524 ast_log(LOG_WARNING, "A matching ']' was not found for '[' in pattern string '%s'\n", extenbuf); 01525 break; 01526 } else { 01527 *s2++ = *s1++; 01528 } 01529 } 01530 *s2 = 0; /* null terminate the exploded range */ 01531 /* sort the characters */ 01532 01533 specif = strlen(buf); 01534 qsort(buf, specif, 1, compare_char); 01535 specif <<= 8; 01536 specif += buf[0]; 01537 } else { 01538 01539 if (*s1 == '\\') { 01540 s1++; 01541 buf[0] = *s1; 01542 } else { 01543 if (pattern) { 01544 if (*s1 == 'n') /* make sure n,x,z patterns are canonicalized to N,X,Z */ 01545 *s1 = 'N'; 01546 else if (*s1 == 'x') 01547 *s1 = 'X'; 01548 else if (*s1 == 'z') 01549 *s1 = 'Z'; 01550 } 01551 buf[0] = *s1; 01552 } 01553 buf[1] = 0; 01554 specif = 1; 01555 } 01556 m2 = 0; 01557 if (already && (m2=already_in_tree(m1,buf)) && m2->next_char) { 01558 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... 01559 a shorter pattern might win if the longer one doesn't match */ 01560 m2->exten = e1; 01561 m2->deleted = 0; 01562 } 01563 m1 = m2->next_char; /* m1 points to the node to compare against */ 01564 m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */ 01565 } else { /* not already OR not m2 OR nor m2->next_char */ 01566 if (m2) { 01567 if (findonly) 01568 return m2; 01569 m1 = m2; /* while m0 stays the same */ 01570 } else { 01571 if (findonly) 01572 return m1; 01573 m1 = add_pattern_node(con, m1, buf, pattern, already,specif, m0); /* m1 is the node just added */ 01574 m0 = &m1->next_char; 01575 } 01576 01577 if (!(*(s1+1))) { 01578 m1->deleted = 0; 01579 m1->exten = e1; 01580 } 01581 01582 already = 0; 01583 } 01584 s1++; /* advance to next char */ 01585 } 01586 return m1; 01587 }
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 1425 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().
01426 { 01427 struct match_char *m; 01428 01429 if (!(m = ast_calloc(1, sizeof(*m)))) 01430 return NULL; 01431 01432 if (!(m->x = ast_strdup(pattern))) { 01433 ast_free(m); 01434 return NULL; 01435 } 01436 01437 /* the specificity scores are the same as used in the old 01438 pattern matcher. */ 01439 m->is_pattern = is_pattern; 01440 if (specificity == 1 && is_pattern && pattern[0] == 'N') 01441 m->specificity = 0x0802; 01442 else if (specificity == 1 && is_pattern && pattern[0] == 'Z') 01443 m->specificity = 0x0901; 01444 else if (specificity == 1 && is_pattern && pattern[0] == 'X') 01445 m->specificity = 0x0a00; 01446 else if (specificity == 1 && is_pattern && pattern[0] == '.') 01447 m->specificity = 0x10000; 01448 else if (specificity == 1 && is_pattern && pattern[0] == '!') 01449 m->specificity = 0x20000; 01450 else 01451 m->specificity = specificity; 01452 01453 if (!con->pattern_tree) { 01454 insert_in_next_chars_alt_char_list(&con->pattern_tree, m); 01455 } else { 01456 if (already) { /* switch to the new regime (traversing vs appending)*/ 01457 insert_in_next_chars_alt_char_list(nextcharptr, m); 01458 } else { 01459 insert_in_next_chars_alt_char_list(¤t->next_char, m); 01460 } 01461 } 01462 return m; 01463 }
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 6565 of file pbx.c.
References add_pri_lockopt(), and el.
Referenced by ast_add_extension2_lockopt().
06567 { 06568 return add_pri_lockopt(con, tmp, el, e, replace, 1); 06569 }
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 6576 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().
06578 { 06579 struct ast_exten *ep; 06580 struct ast_exten *eh=e; 06581 06582 for (ep = NULL; e ; ep = e, e = e->peer) { 06583 if (e->priority >= tmp->priority) 06584 break; 06585 } 06586 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 06587 ast_hashtab_insert_safe(eh->peer_table, tmp); 06588 06589 if (tmp->label) { 06590 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 06591 } 06592 ep->peer = tmp; 06593 return 0; /* success */ 06594 } 06595 if (e->priority == tmp->priority) { 06596 /* Can't have something exactly the same. Is this a 06597 replacement? If so, replace, otherwise, bonk. */ 06598 if (!replace) { 06599 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 06600 if (tmp->datad) { 06601 tmp->datad(tmp->data); 06602 /* if you free this, null it out */ 06603 tmp->data = NULL; 06604 } 06605 06606 ast_free(tmp); 06607 return -1; 06608 } 06609 /* we are replacing e, so copy the link fields and then update 06610 * whoever pointed to e to point to us 06611 */ 06612 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 06613 tmp->peer = e->peer; /* always meaningful */ 06614 if (ep) { /* We're in the peer list, just insert ourselves */ 06615 ast_hashtab_remove_object_via_lookup(eh->peer_table,e); 06616 06617 if (e->label) { 06618 ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e); 06619 } 06620 06621 ast_hashtab_insert_safe(eh->peer_table,tmp); 06622 if (tmp->label) { 06623 ast_hashtab_insert_safe(eh->peer_label_table,tmp); 06624 } 06625 06626 ep->peer = tmp; 06627 } else if (el) { /* We're the first extension. Take over e's functions */ 06628 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 06629 tmp->peer_table = e->peer_table; 06630 tmp->peer_label_table = e->peer_label_table; 06631 ast_hashtab_remove_object_via_lookup(tmp->peer_table,e); 06632 ast_hashtab_insert_safe(tmp->peer_table,tmp); 06633 if (e->label) { 06634 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 06635 } 06636 if (tmp->label) { 06637 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 06638 } 06639 06640 ast_hashtab_remove_object_via_lookup(con->root_table, e); 06641 ast_hashtab_insert_safe(con->root_table, tmp); 06642 el->next = tmp; 06643 /* The pattern trie points to this exten; replace the pointer, 06644 and all will be well */ 06645 if (x) { /* if the trie isn't formed yet, don't sweat this */ 06646 if (x->exten) { /* this test for safety purposes */ 06647 x->exten = tmp; /* replace what would become a bad pointer */ 06648 } else { 06649 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 06650 } 06651 } 06652 } else { /* We're the very first extension. */ 06653 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 06654 ast_hashtab_remove_object_via_lookup(con->root_table, e); 06655 ast_hashtab_insert_safe(con->root_table, tmp); 06656 tmp->peer_table = e->peer_table; 06657 tmp->peer_label_table = e->peer_label_table; 06658 ast_hashtab_remove_object_via_lookup(tmp->peer_table, e); 06659 ast_hashtab_insert_safe(tmp->peer_table, tmp); 06660 if (e->label) { 06661 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 06662 } 06663 if (tmp->label) { 06664 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 06665 } 06666 06667 ast_hashtab_remove_object_via_lookup(con->root_table, e); 06668 ast_hashtab_insert_safe(con->root_table, tmp); 06669 con->root = tmp; 06670 /* The pattern trie points to this exten; replace the pointer, 06671 and all will be well */ 06672 if (x) { /* if the trie isn't formed yet; no problem */ 06673 if (x->exten) { /* this test for safety purposes */ 06674 x->exten = tmp; /* replace what would become a bad pointer */ 06675 } else { 06676 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 06677 } 06678 } 06679 } 06680 if (tmp->priority == PRIORITY_HINT) 06681 ast_change_hint(e,tmp); 06682 /* Destroy the old one */ 06683 if (e->datad) 06684 e->datad(e->data); 06685 ast_free(e); 06686 } else { /* Slip ourselves in just before e */ 06687 tmp->peer = e; 06688 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 06689 if (ep) { /* Easy enough, we're just in the peer list */ 06690 if (tmp->label) { 06691 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 06692 } 06693 ast_hashtab_insert_safe(eh->peer_table, tmp); 06694 ep->peer = tmp; 06695 } else { /* we are the first in some peer list, so link in the ext list */ 06696 tmp->peer_table = e->peer_table; 06697 tmp->peer_label_table = e->peer_label_table; 06698 e->peer_table = 0; 06699 e->peer_label_table = 0; 06700 ast_hashtab_insert_safe(tmp->peer_table, tmp); 06701 if (tmp->label) { 06702 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 06703 } 06704 ast_hashtab_remove_object_via_lookup(con->root_table, e); 06705 ast_hashtab_insert_safe(con->root_table, tmp); 06706 if (el) 06707 el->next = tmp; /* in the middle... */ 06708 else 06709 con->root = tmp; /* ... or at the head */ 06710 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 06711 } 06712 /* And immediately return success. */ 06713 if (tmp->priority == PRIORITY_HINT) { 06714 if (lockhints) { 06715 ast_add_hint(tmp); 06716 } else { 06717 ast_add_hint_nolock(tmp); 06718 } 06719 } 06720 } 06721 return 0; 06722 }
static struct match_char * already_in_tree | ( | struct match_char * | current, | |
char * | pat | |||
) | [static] |
Definition at line 1376 of file pbx.c.
References match_char::alt_char, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01377 { 01378 struct match_char *t; 01379 if (!current) 01380 return 0; 01381 for (t=current; t; t=t->alt_char) { 01382 if (strcmp(pat,t->x) == 0) /* uh, we may want to sort exploded [] contents to make matching easy */ 01383 return t; 01384 } 01385 return 0; 01386 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 4026 of file pbx.c.
Referenced by handle_chanlist(), handle_showcalls(), and sysinfo_helper().
04027 { 04028 return countcalls; 04029 }
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 6431 of file pbx.c.
References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_extension(), park_add_hints(), register_exten(), register_peer_exten(), and RegisterExtension().
06434 { 06435 int ret = -1; 06436 struct ast_context *c = find_context_locked(context); 06437 06438 if (c) { 06439 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 06440 application, data, datad, registrar); 06441 ast_unlock_contexts(); 06442 } 06443 06444 return ret; 06445 }
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 6749 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by ast_add_extension(), context_merge(), do_parking_thread(), load_module(), park_call_full(), pbx_load_config(), and pbx_load_users().
06753 { 06754 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1); 06755 }
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 6762 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_debug, ast_hashtab_create(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), AST_LIST_FIRST, ast_log(), ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, ast_exten::data, ast_exten::datad, el, errno, ext_cmp(), ext_strncpy(), ast_exten::exten, globals, globalslock, 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_varshead(), 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().
06766 { 06767 /* 06768 * Sort extensions (or patterns) according to the rules indicated above. 06769 * These are implemented by the function ext_cmp()). 06770 * All priorities for the same ext/pattern/cid are kept in a list, 06771 * using the 'peer' field as a link field.. 06772 */ 06773 struct ast_exten *tmp, *tmp2, *e, *el = NULL; 06774 int res; 06775 int length; 06776 char *p; 06777 char expand_buf[VAR_BUF_SIZE]; 06778 struct ast_exten dummy_exten = {0}; 06779 char dummy_name[1024]; 06780 06781 if (ast_strlen_zero(extension)) { 06782 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", 06783 con->name); 06784 return -1; 06785 } 06786 /* if we are adding a hint, and there are global variables, and the hint 06787 contains variable references, then expand them 06788 */ 06789 ast_rwlock_rdlock(&globalslock); 06790 if (priority == PRIORITY_HINT && AST_LIST_FIRST(&globals) && strstr(application, "${")) { 06791 pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf)); 06792 application = expand_buf; 06793 } 06794 ast_rwlock_unlock(&globalslock); 06795 06796 length = sizeof(struct ast_exten); 06797 length += strlen(extension) + 1; 06798 length += strlen(application) + 1; 06799 if (label) 06800 length += strlen(label) + 1; 06801 if (callerid) 06802 length += strlen(callerid) + 1; 06803 else 06804 length ++; /* just the '\0' */ 06805 06806 /* Be optimistic: Build the extension structure first */ 06807 if (!(tmp = ast_calloc(1, length))) 06808 return -1; 06809 06810 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */ 06811 label = 0; 06812 06813 /* use p as dst in assignments, as the fields are const char * */ 06814 p = tmp->stuff; 06815 if (label) { 06816 tmp->label = p; 06817 strcpy(p, label); 06818 p += strlen(label) + 1; 06819 } 06820 tmp->exten = p; 06821 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 06822 tmp->priority = priority; 06823 tmp->cidmatch = p; /* but use p for assignments below */ 06824 if (!ast_strlen_zero(callerid)) { 06825 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 06826 tmp->matchcid = 1; 06827 } else { 06828 *p++ = '\0'; 06829 tmp->matchcid = 0; 06830 } 06831 tmp->app = p; 06832 strcpy(p, application); 06833 tmp->parent = con; 06834 tmp->data = data; 06835 tmp->datad = datad; 06836 tmp->registrar = registrar; 06837 06838 if (lockconts) { 06839 ast_wrlock_context(con); 06840 } 06841 06842 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding 06843 an extension, and the trie exists, then we need to incrementally add this pattern to it. */ 06844 strncpy(dummy_name,extension,sizeof(dummy_name)); 06845 dummy_exten.exten = dummy_name; 06846 dummy_exten.matchcid = 0; 06847 dummy_exten.cidmatch = 0; 06848 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten); 06849 if (!tmp2) { 06850 /* hmmm, not in the trie; */ 06851 add_exten_to_pattern_tree(con, tmp, 0); 06852 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */ 06853 } 06854 } 06855 res = 0; /* some compilers will think it is uninitialized otherwise */ 06856 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 06857 res = ext_cmp(e->exten, tmp->exten); 06858 if (res == 0) { /* extension match, now look at cidmatch */ 06859 if (!e->matchcid && !tmp->matchcid) 06860 res = 0; 06861 else if (tmp->matchcid && !e->matchcid) 06862 res = 1; 06863 else if (e->matchcid && !tmp->matchcid) 06864 res = -1; 06865 else 06866 res = strcasecmp(e->cidmatch, tmp->cidmatch); 06867 } 06868 if (res >= 0) 06869 break; 06870 } 06871 if (e && res == 0) { /* exact match, insert in the pri chain */ 06872 res = add_pri(con, tmp, el, e, replace); 06873 if (lockconts) { 06874 ast_unlock_context(con); 06875 } 06876 if (res < 0) { 06877 errno = EEXIST; /* XXX do we care ? */ 06878 return 0; /* XXX should we return -1 maybe ? */ 06879 } 06880 } else { 06881 /* 06882 * not an exact match, this is the first entry with this pattern, 06883 * so insert in the main list right before 'e' (if any) 06884 */ 06885 tmp->next = e; 06886 if (el) { /* there is another exten already in this context */ 06887 el->next = tmp; 06888 tmp->peer_table = ast_hashtab_create(13, 06889 hashtab_compare_exten_numbers, 06890 ast_hashtab_resize_java, 06891 ast_hashtab_newsize_java, 06892 hashtab_hash_priority, 06893 0); 06894 tmp->peer_label_table = ast_hashtab_create(7, 06895 hashtab_compare_exten_labels, 06896 ast_hashtab_resize_java, 06897 ast_hashtab_newsize_java, 06898 hashtab_hash_labels, 06899 0); 06900 if (label) { 06901 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 06902 } 06903 ast_hashtab_insert_safe(tmp->peer_table, tmp); 06904 } else { /* this is the first exten in this context */ 06905 if (!con->root_table) 06906 con->root_table = ast_hashtab_create(27, 06907 hashtab_compare_extens, 06908 ast_hashtab_resize_java, 06909 ast_hashtab_newsize_java, 06910 hashtab_hash_extens, 06911 0); 06912 con->root = tmp; 06913 con->root->peer_table = ast_hashtab_create(13, 06914 hashtab_compare_exten_numbers, 06915 ast_hashtab_resize_java, 06916 ast_hashtab_newsize_java, 06917 hashtab_hash_priority, 06918 0); 06919 con->root->peer_label_table = ast_hashtab_create(7, 06920 hashtab_compare_exten_labels, 06921 ast_hashtab_resize_java, 06922 ast_hashtab_newsize_java, 06923 hashtab_hash_labels, 06924 0); 06925 if (label) { 06926 ast_hashtab_insert_safe(con->root->peer_label_table, tmp); 06927 } 06928 ast_hashtab_insert_safe(con->root->peer_table, tmp); 06929 06930 } 06931 ast_hashtab_insert_safe(con->root_table, tmp); 06932 if (lockconts) { 06933 ast_unlock_context(con); 06934 } 06935 if (tmp->priority == PRIORITY_HINT) { 06936 if (lockhints) { 06937 ast_add_hint(tmp); 06938 } else { 06939 ast_add_hint_nolock(tmp); 06940 } 06941 } 06942 } 06943 if (option_debug) { 06944 if (tmp->matchcid) { 06945 ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 06946 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 06947 } else { 06948 ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n", 06949 tmp->exten, tmp->priority, con->name, con); 06950 } 06951 } 06952 06953 if (tmp->matchcid) { 06954 ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 06955 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 06956 } else { 06957 ast_verb(3, "Added extension '%s' priority %d to %s (%p)\n", 06958 tmp->exten, tmp->priority, con->name, con); 06959 } 06960 06961 return 0; 06962 }
static int ast_add_hint | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state.
Definition at line 3506 of file pbx.c.
References ast_add_hint_nolock(), AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by ast_add_extension2_lockopt().
03507 { 03508 int ret; 03509 03510 AST_RWLIST_WRLOCK(&hints); 03511 ret = ast_add_hint_nolock(e); 03512 AST_RWLIST_UNLOCK(&hints); 03513 03514 return ret; 03515 }
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 3477 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().
03478 { 03479 struct ast_hint *hint; 03480 03481 if (!e) 03482 return -1; 03483 03484 /* Search if hint exists, do nothing */ 03485 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03486 if (hint->exten == e) { 03487 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 03488 return -1; 03489 } 03490 } 03491 03492 ast_debug(2, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 03493 03494 if (!(hint = ast_calloc(1, sizeof(*hint)))) { 03495 return -1; 03496 } 03497 /* Initialize and insert new item at the top */ 03498 hint->exten = e; 03499 hint->laststate = ast_extension_state2(e); 03500 AST_RWLIST_INSERT_HEAD(&hints, hint, list); 03501 03502 return 0; 03503 }
int ast_async_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6470 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().
06471 { 06472 int res = 0; 06473 06474 ast_channel_lock(chan); 06475 06476 if (chan->pbx) { /* This channel is currently in the PBX */ 06477 ast_explicit_goto(chan, context, exten, priority + 1); 06478 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 06479 } else { 06480 /* In order to do it when the channel doesn't really exist within 06481 the PBX, we have to make a new channel, masquerade, and start the PBX 06482 at the new location */ 06483 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name); 06484 if (!tmpchan) { 06485 res = -1; 06486 } else { 06487 if (chan->cdr) { 06488 ast_cdr_discard(tmpchan->cdr); 06489 tmpchan->cdr = ast_cdr_dup(chan->cdr); /* share the love */ 06490 } 06491 /* Make formats okay */ 06492 tmpchan->readformat = chan->readformat; 06493 tmpchan->writeformat = chan->writeformat; 06494 /* Setup proper location */ 06495 ast_explicit_goto(tmpchan, 06496 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 06497 06498 /* Masquerade into temp channel */ 06499 if (ast_channel_masquerade(tmpchan, chan)) { 06500 /* Failed to set up the masquerade. It's probably chan_local 06501 * in the middle of optimizing itself out. Sad. :( */ 06502 ast_hangup(tmpchan); 06503 tmpchan = NULL; 06504 res = -1; 06505 } else { 06506 /* Grab the locks and get going */ 06507 ast_channel_lock(tmpchan); 06508 ast_do_masquerade(tmpchan); 06509 ast_channel_unlock(tmpchan); 06510 /* Start the PBX going on our stolen channel */ 06511 if (ast_pbx_start(tmpchan)) { 06512 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 06513 ast_hangup(tmpchan); 06514 res = -1; 06515 } 06516 } 06517 } 06518 } 06519 ast_channel_unlock(chan); 06520 return res; 06521 }
int ast_async_goto_by_name | ( | const char * | channame, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6523 of file pbx.c.
References ast_async_goto(), ast_channel_unlock, ast_get_channel_by_name_locked(), and chan.
06524 { 06525 struct ast_channel *chan; 06526 int res = -1; 06527 06528 chan = ast_get_channel_by_name_locked(channame); 06529 if (chan) { 06530 res = ast_async_goto(chan, context, exten, priority); 06531 ast_channel_unlock(chan); 06532 } 06533 return res; 06534 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8630 of file pbx.c.
References __ast_goto_if_exists(), and chan.
08631 { 08632 return __ast_goto_if_exists(chan, context, exten, priority, 1); 08633 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 8693 of file pbx.c.
References chan, and pbx_parseable_goto().
Referenced by asyncgoto_exec().
08694 { 08695 return pbx_parseable_goto(chan, goto_string, 1); 08696 }
int ast_build_timing | ( | struct ast_timing * | i, | |
const char * | info_in | |||
) |
Definition at line 6110 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().
06111 { 06112 char info_save[256]; 06113 char *info; 06114 06115 /* Check for empty just in case */ 06116 if (ast_strlen_zero(info_in)) 06117 return 0; 06118 /* make a copy just in case we were passed a static string */ 06119 ast_copy_string(info_save, info_in, sizeof(info_save)); 06120 info = info_save; 06121 /* Assume everything except time */ 06122 i->monthmask = 0xfff; /* 12 bits */ 06123 i->daymask = 0x7fffffffU; /* 31 bits */ 06124 i->dowmask = 0x7f; /* 7 bits */ 06125 /* on each call, use strsep() to move info to the next argument */ 06126 get_timerange(i, strsep(&info, "|,")); 06127 if (info) 06128 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 06129 if (info) 06130 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 06131 if (info) 06132 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 06133 return 1; 06134 }
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 3604 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), handle_link_data(), handle_link_phone_dtmf(), leave_voicemail(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), phone_check_exception(), skinny_ss(), ss_thread(), and valid_exit().
03605 { 03606 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 03607 }
Change hint for an extension.
Definition at line 3518 of file pbx.c.
References AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_hint::exten, and ast_hint::list.
03519 { 03520 struct ast_hint *hint; 03521 int res = -1; 03522 03523 AST_RWLIST_WRLOCK(&hints); 03524 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03525 if (hint->exten == oe) { 03526 hint->exten = ne; 03527 res = 0; 03528 break; 03529 } 03530 } 03531 AST_RWLIST_UNLOCK(&hints); 03532 03533 return res; 03534 }
int ast_check_timing | ( | const struct ast_timing * | i | ) |
Definition at line 6136 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().
06137 { 06138 struct ast_tm tm; 06139 struct timeval tv = ast_tvnow(); 06140 06141 ast_localtime(&tv, &tm, NULL); 06142 06143 /* If it's not the right month, return */ 06144 if (!(i->monthmask & (1 << tm.tm_mon))) 06145 return 0; 06146 06147 /* If it's not that time of the month.... */ 06148 /* Warning, tm_mday has range 1..31! */ 06149 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 06150 return 0; 06151 06152 /* If it's not the right day of the week */ 06153 if (!(i->dowmask & (1 << tm.tm_wday))) 06154 return 0; 06155 06156 /* Sanity check the hour just to be safe */ 06157 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 06158 ast_log(LOG_WARNING, "Insane time...\n"); 06159 return 0; 06160 } 06161 06162 /* Now the tough part, we calculate if it fits 06163 in the right time based on min/hour */ 06164 if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2)))) 06165 return 0; 06166 06167 /* If we got this far, then we're good */ 06168 return 1; 06169 }
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 6362 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
06363 { 06364 int ret = -1; 06365 struct ast_context *c = find_context_locked(context); 06366 06367 if (c) { 06368 ret = ast_context_add_ignorepat2(c, value, registrar); 06369 ast_unlock_contexts(); 06370 } 06371 return ret; 06372 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 6374 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().
06375 { 06376 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 06377 int length; 06378 char *pattern; 06379 length = sizeof(struct ast_ignorepat); 06380 length += strlen(value) + 1; 06381 if (!(ignorepat = ast_calloc(1, length))) 06382 return -1; 06383 /* The cast to char * is because we need to write the initial value. 06384 * The field is not supposed to be modified otherwise. Also, gcc 4.2 06385 * sees the cast as dereferencing a type-punned pointer and warns about 06386 * it. This is the workaround (we're telling gcc, yes, that's really 06387 * what we wanted to do). 06388 */ 06389 pattern = (char *) ignorepat->pattern; 06390 strcpy(pattern, value); 06391 ignorepat->next = NULL; 06392 ignorepat->registrar = registrar; 06393 ast_wrlock_context(con); 06394 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 06395 ignorepatl = ignorepatc; 06396 if (!strcasecmp(ignorepatc->pattern, value)) { 06397 /* Already there */ 06398 ast_unlock_context(con); 06399 errno = EEXIST; 06400 return -1; 06401 } 06402 } 06403 if (ignorepatl) 06404 ignorepatl->next = ignorepat; 06405 else 06406 con->ignorepats = ignorepat; 06407 ast_unlock_context(con); 06408 return 0; 06409 06410 }
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 5916 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
05917 { 05918 int ret = -1; 05919 struct ast_context *c = find_context_locked(context); 05920 05921 if (c) { 05922 ret = ast_context_add_include2(c, include, registrar); 05923 ast_unlock_contexts(); 05924 } 05925 return ret; 05926 }
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 6178 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().
06180 { 06181 struct ast_include *new_include; 06182 char *c; 06183 struct ast_include *i, *il = NULL; /* include, include_last */ 06184 int length; 06185 char *p; 06186 06187 length = sizeof(struct ast_include); 06188 length += 2 * (strlen(value) + 1); 06189 06190 /* allocate new include structure ... */ 06191 if (!(new_include = ast_calloc(1, length))) 06192 return -1; 06193 /* Fill in this structure. Use 'p' for assignments, as the fields 06194 * in the structure are 'const char *' 06195 */ 06196 p = new_include->stuff; 06197 new_include->name = p; 06198 strcpy(p, value); 06199 p += strlen(value) + 1; 06200 new_include->rname = p; 06201 strcpy(p, value); 06202 /* Strip off timing info, and process if it is there */ 06203 if ( (c = strchr(p, ',')) ) { 06204 *c++ = '\0'; 06205 new_include->hastime = ast_build_timing(&(new_include->timing), c); 06206 } 06207 new_include->next = NULL; 06208 new_include->registrar = registrar; 06209 06210 ast_wrlock_context(con); 06211 06212 /* ... go to last include and check if context is already included too... */ 06213 for (i = con->includes; i; i = i->next) { 06214 if (!strcasecmp(i->name, new_include->name)) { 06215 ast_free(new_include); 06216 ast_unlock_context(con); 06217 errno = EEXIST; 06218 return -1; 06219 } 06220 il = i; 06221 } 06222 06223 /* ... include new context into context list, unlock, return */ 06224 if (il) 06225 il->next = new_include; 06226 else 06227 con->includes = new_include; 06228 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 06229 06230 ast_unlock_context(con); 06231 06232 return 0; 06233 }
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 6240 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
06241 { 06242 int ret = -1; 06243 struct ast_context *c = find_context_locked(context); 06244 06245 if (c) { /* found, add switch to this context */ 06246 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 06247 ast_unlock_contexts(); 06248 } 06249 return ret; 06250 }
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 6259 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().
06261 { 06262 struct ast_sw *new_sw; 06263 struct ast_sw *i; 06264 int length; 06265 char *p; 06266 06267 length = sizeof(struct ast_sw); 06268 length += strlen(value) + 1; 06269 if (data) 06270 length += strlen(data); 06271 length++; 06272 06273 /* allocate new sw structure ... */ 06274 if (!(new_sw = ast_calloc(1, length))) 06275 return -1; 06276 /* ... fill in this structure ... */ 06277 p = new_sw->stuff; 06278 new_sw->name = p; 06279 strcpy(new_sw->name, value); 06280 p += strlen(value) + 1; 06281 new_sw->data = p; 06282 if (data) { 06283 strcpy(new_sw->data, data); 06284 p += strlen(data) + 1; 06285 } else { 06286 strcpy(new_sw->data, ""); 06287 p++; 06288 } 06289 new_sw->eval = eval; 06290 new_sw->registrar = registrar; 06291 06292 /* ... try to lock this context ... */ 06293 ast_wrlock_context(con); 06294 06295 /* ... go to last sw and check if context is already swd too... */ 06296 AST_LIST_TRAVERSE(&con->alts, i, list) { 06297 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 06298 ast_free(new_sw); 06299 ast_unlock_context(con); 06300 errno = EEXIST; 06301 return -1; 06302 } 06303 } 06304 06305 /* ... sw new context into context list, unlock, return */ 06306 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 06307 06308 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 06309 06310 ast_unlock_context(con); 06311 06312 return 0; 06313 }
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 7537 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(), sla_destroy(), and unload_module().
07538 { 07539 ast_wrlock_contexts(); 07540 __ast_context_destroy(contexts, contexts_table, con,registrar); 07541 ast_unlock_contexts(); 07542 }
struct ast_context* ast_context_find | ( | const char * | name | ) |
Find a context.
name | name of the context to find |
Definition at line 2001 of file pbx.c.
References 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(), do_parking_thread(), isexten_function_read(), park_exec(), register_exten(), register_peer_exten(), unload_module(), and unregister_exten().
02002 { 02003 struct ast_context *tmp = NULL; 02004 struct fake_context item; 02005 strncpy(item.name,name,256); 02006 ast_rdlock_contexts(); 02007 if( contexts_table ) { 02008 tmp = ast_hashtab_lookup(contexts_table,&item); 02009 } else { 02010 while ( (tmp = ast_walk_contexts(tmp)) ) { 02011 if (!name || !strcasecmp(name, tmp->name)) 02012 break; 02013 } 02014 } 02015 ast_unlock_contexts(); 02016 return tmp; 02017 }
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 5575 of file pbx.c.
References ast_calloc, 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 context_merge(), do_parking_thread(), load_module(), lua_register_switches(), park_call_full(), pbx_load_config(), pbx_load_users(), reload_config(), and set_config().
05576 { 05577 struct ast_context *tmp, **local_contexts; 05578 struct fake_context search; 05579 int length = sizeof(struct ast_context) + strlen(name) + 1; 05580 05581 if (!contexts_table) { 05582 contexts_table = ast_hashtab_create(17, 05583 ast_hashtab_compare_contexts, 05584 ast_hashtab_resize_java, 05585 ast_hashtab_newsize_java, 05586 ast_hashtab_hash_contexts, 05587 0); 05588 } 05589 05590 strncpy(search.name,name,sizeof(search.name)); 05591 if (!extcontexts) { 05592 ast_rdlock_contexts(); 05593 local_contexts = &contexts; 05594 tmp = ast_hashtab_lookup(contexts_table, &search); 05595 ast_unlock_contexts(); 05596 if (tmp) { 05597 tmp->refcount++; 05598 return tmp; 05599 } 05600 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 05601 local_contexts = extcontexts; 05602 tmp = ast_hashtab_lookup(exttable, &search); 05603 if (tmp) { 05604 tmp->refcount++; 05605 return tmp; 05606 } 05607 } 05608 05609 if ((tmp = ast_calloc(1, length))) { 05610 ast_rwlock_init(&tmp->lock); 05611 ast_mutex_init(&tmp->macrolock); 05612 strcpy(tmp->name, name); 05613 tmp->root = NULL; 05614 tmp->root_table = NULL; 05615 tmp->registrar = ast_strdup(registrar); 05616 tmp->includes = NULL; 05617 tmp->ignorepats = NULL; 05618 tmp->refcount = 1; 05619 } else { 05620 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 05621 return NULL; 05622 } 05623 05624 if (!extcontexts) { 05625 ast_wrlock_contexts(); 05626 tmp->next = *local_contexts; 05627 *local_contexts = tmp; 05628 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 05629 ast_unlock_contexts(); 05630 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 05631 ast_verb(3, "Registered extension context '%s' (%p) in table %p; registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 05632 } else { 05633 tmp->next = *local_contexts; 05634 if (exttable) 05635 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 05636 05637 *local_contexts = tmp; 05638 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 05639 ast_verb(3, "Registered extension context '%s' (%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 05640 } 05641 return tmp; 05642 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 4385 of file pbx.c.
References 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().
04386 { 04387 struct ast_context *c = NULL; 04388 int ret = -1; 04389 struct fake_context item; 04390 04391 ast_rdlock_contexts(); 04392 04393 strncpy(item.name,context,256); 04394 c = ast_hashtab_lookup(contexts_table,&item); 04395 if (c) 04396 ret = 0; 04397 04398 04399 #ifdef NOTNOW 04400 04401 while ((c = ast_walk_contexts(c))) { 04402 if (!strcmp(ast_get_context_name(c), context)) { 04403 ret = 0; 04404 break; 04405 } 04406 } 04407 04408 #endif 04409 ast_unlock_contexts(); 04410 04411 /* if we found context, lock macrolock */ 04412 if (ret == 0) 04413 ret = ast_mutex_lock(&c->macrolock); 04414 04415 return ret; 04416 }
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 4192 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), unregister_exten(), and UnregisterExtension().
04193 { 04194 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 04195 }
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 4219 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by do_parking_thread(), park_exec(), and unload_module().
04220 { 04221 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 04222 }
int ast_context_remove_extension_callerid | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | callerid, | |||
int | matchcid, | |||
const char * | registrar | |||
) |
Definition at line 4197 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().
04198 { 04199 int ret = -1; /* default error return */ 04200 struct ast_context *c = find_context_locked(context); 04201 04202 if (c) { /* ... remove extension ... */ 04203 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcid, registrar, 1); 04204 ast_unlock_contexts(); 04205 } 04206 return ret; 04207 }
int ast_context_remove_extension_callerid2 | ( | struct ast_context * | con, | |
const char * | extension, | |||
int | priority, | |||
const char * | callerid, | |||
int | matchcid, | |||
const char * | registrar, | |||
int | already_locked | |||
) |
Definition at line 4224 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().
04225 { 04226 struct ast_exten *exten, *prev_exten = NULL; 04227 struct ast_exten *peer; 04228 struct ast_exten ex, *exten2, *exten3; 04229 char dummy_name[1024]; 04230 struct ast_exten *previous_peer = NULL; 04231 struct ast_exten *next_peer = NULL; 04232 int found = 0; 04233 04234 if (!already_locked) 04235 ast_wrlock_context(con); 04236 04237 /* Handle this is in the new world */ 04238 04239 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 04240 * peers, not just those matching the callerid. */ 04241 #ifdef NEED_DEBUG 04242 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcid ? "/" : "", matchcid ? callerid : "", registrar); 04243 #endif 04244 #ifdef CONTEXT_DEBUG 04245 check_contexts(__FILE__, __LINE__); 04246 #endif 04247 /* find this particular extension */ 04248 ex.exten = dummy_name; 04249 ex.matchcid = matchcid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 04250 ex.cidmatch = callerid; 04251 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 04252 exten = ast_hashtab_lookup(con->root_table, &ex); 04253 if (exten) { 04254 if (priority == 0) { 04255 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 04256 if (!exten2) 04257 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); 04258 if (con->pattern_tree) { 04259 04260 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 04261 04262 if (x->exten) { /* this test for safety purposes */ 04263 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 04264 x->exten = 0; /* get rid of what will become a bad pointer */ 04265 } else { 04266 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 04267 } 04268 } 04269 } else { 04270 ex.priority = priority; 04271 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 04272 if (exten2) { 04273 04274 if (exten2->label) { /* if this exten has a label, remove that, too */ 04275 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 04276 if (!exten3) 04277 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); 04278 } 04279 04280 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 04281 if (!exten3) 04282 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); 04283 if (exten2 == exten && exten2->peer) { 04284 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 04285 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 04286 } 04287 if (ast_hashtab_size(exten->peer_table) == 0) { 04288 /* well, if the last priority of an exten is to be removed, 04289 then, the extension is removed, too! */ 04290 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 04291 if (!exten3) 04292 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 04293 if (con->pattern_tree) { 04294 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 04295 if (x->exten) { /* this test for safety purposes */ 04296 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 04297 x->exten = 0; /* get rid of what will become a bad pointer */ 04298 } 04299 } 04300 } 04301 } else { 04302 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 04303 priority, exten->exten, con->name); 04304 } 04305 } 04306 } else { 04307 /* hmmm? this exten is not in this pattern tree? */ 04308 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 04309 extension, con->name); 04310 } 04311 #ifdef NEED_DEBUG 04312 if (con->pattern_tree) { 04313 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 04314 log_match_char_tree(con->pattern_tree, " "); 04315 } 04316 #endif 04317 04318 /* scan the extension list to find first matching extension-registrar */ 04319 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 04320 if (!strcmp(exten->exten, extension) && 04321 (!registrar || !strcmp(exten->registrar, registrar)) && 04322 (!matchcid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 04323 break; 04324 } 04325 if (!exten) { 04326 /* we can't find right extension */ 04327 if (!already_locked) 04328 ast_unlock_context(con); 04329 return -1; 04330 } 04331 04332 /* scan the priority list to remove extension with exten->priority == priority */ 04333 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 04334 peer && !strcmp(peer->exten, extension) && (!matchcid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(peer->cidmatch) && !strcmp(peer->cidmatch,callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(peer->cidmatch))); 04335 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 04336 if ((priority == 0 || peer->priority == priority) && 04337 (!callerid || !matchcid || (matchcid && !strcmp(peer->cidmatch, callerid))) && 04338 (!registrar || !strcmp(peer->registrar, registrar) )) { 04339 found = 1; 04340 04341 /* we are first priority extension? */ 04342 if (!previous_peer) { 04343 /* 04344 * We are first in the priority chain, so must update the extension chain. 04345 * The next node is either the next priority or the next extension 04346 */ 04347 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 04348 if (peer->peer) { 04349 /* move the peer_table and peer_label_table down to the next peer, if 04350 it is there */ 04351 peer->peer->peer_table = peer->peer_table; 04352 peer->peer->peer_label_table = peer->peer_label_table; 04353 peer->peer_table = NULL; 04354 peer->peer_label_table = NULL; 04355 } 04356 if (!prev_exten) { /* change the root... */ 04357 con->root = next_node; 04358 } else { 04359 prev_exten->next = next_node; /* unlink */ 04360 } 04361 if (peer->peer) { /* update the new head of the pri list */ 04362 peer->peer->next = peer->next; 04363 } 04364 } else { /* easy, we are not first priority in extension */ 04365 previous_peer->peer = peer->peer; 04366 } 04367 04368 /* now, free whole priority extension */ 04369 destroy_exten(peer); 04370 } else { 04371 previous_peer = peer; 04372 } 04373 } 04374 if (!already_locked) 04375 ast_unlock_context(con); 04376 return found ? 0 : -1; 04377 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 6319 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
06320 { 06321 int ret = -1; 06322 struct ast_context *c = find_context_locked(context); 06323 06324 if (c) { 06325 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 06326 ast_unlock_contexts(); 06327 } 06328 return ret; 06329 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 6331 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().
06332 { 06333 struct ast_ignorepat *ip, *ipl = NULL; 06334 06335 ast_wrlock_context(con); 06336 06337 for (ip = con->ignorepats; ip; ip = ip->next) { 06338 if (!strcmp(ip->pattern, ignorepat) && 06339 (!registrar || (registrar == ip->registrar))) { 06340 if (ipl) { 06341 ipl->next = ip->next; 06342 ast_free(ip); 06343 } else { 06344 con->ignorepats = ip->next; 06345 ast_free(ip); 06346 } 06347 ast_unlock_context(con); 06348 return 0; 06349 } 06350 ipl = ip; 06351 } 06352 06353 ast_unlock_context(con); 06354 errno = EINVAL; 06355 return -1; 06356 }
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 4084 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
04085 { 04086 int ret = -1; 04087 struct ast_context *c = find_context_locked(context); 04088 04089 if (c) { 04090 /* found, remove include from this context ... */ 04091 ret = ast_context_remove_include2(c, include, registrar); 04092 ast_unlock_contexts(); 04093 } 04094 return ret; 04095 }
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 4106 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().
04107 { 04108 struct ast_include *i, *pi = NULL; 04109 int ret = -1; 04110 04111 ast_wrlock_context(con); 04112 04113 /* find our include */ 04114 for (i = con->includes; i; pi = i, i = i->next) { 04115 if (!strcmp(i->name, include) && 04116 (!registrar || !strcmp(i->registrar, registrar))) { 04117 /* remove from list */ 04118 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 04119 if (pi) 04120 pi->next = i->next; 04121 else 04122 con->includes = i->next; 04123 /* free include and return */ 04124 ast_free(i); 04125 ret = 0; 04126 break; 04127 } 04128 } 04129 04130 ast_unlock_context(con); 04131 04132 return ret; 04133 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 4140 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
04141 { 04142 int ret = -1; /* default error return */ 04143 struct ast_context *c = find_context_locked(context); 04144 04145 if (c) { 04146 /* remove switch from this context ... */ 04147 ret = ast_context_remove_switch2(c, sw, data, registrar); 04148 ast_unlock_contexts(); 04149 } 04150 return ret; 04151 }
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 4161 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().
04162 { 04163 struct ast_sw *i; 04164 int ret = -1; 04165 04166 ast_wrlock_context(con); 04167 04168 /* walk switches */ 04169 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 04170 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 04171 (!registrar || !strcmp(i->registrar, registrar))) { 04172 /* found, remove from list */ 04173 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 04174 AST_LIST_REMOVE_CURRENT(list); 04175 ast_free(i); /* free switch and return */ 04176 ret = 0; 04177 break; 04178 } 04179 } 04180 AST_LIST_TRAVERSE_SAFE_END; 04181 04182 ast_unlock_context(con); 04183 04184 return ret; 04185 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 4423 of file pbx.c.
References 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().
04424 { 04425 struct ast_context *c = NULL; 04426 int ret = -1; 04427 struct fake_context item; 04428 04429 ast_rdlock_contexts(); 04430 04431 strncpy(item.name, context, 256); 04432 c = ast_hashtab_lookup(contexts_table,&item); 04433 if (c) 04434 ret = 0; 04435 #ifdef NOTNOW 04436 04437 while ((c = ast_walk_contexts(c))) { 04438 if (!strcmp(ast_get_context_name(c), context)) { 04439 ret = 0; 04440 break; 04441 } 04442 } 04443 04444 #endif 04445 ast_unlock_contexts(); 04446 04447 /* if we found context, unlock macrolock */ 04448 if (ret == 0) 04449 ret = ast_mutex_unlock(&c->macrolock); 04450 04451 return ret; 04452 }
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 8587 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().
08588 { 08589 struct ast_include *inc = NULL; 08590 int res = 0; 08591 08592 while ( (inc = ast_walk_context_includes(con, inc)) ) { 08593 if (ast_context_find(inc->rname)) 08594 continue; 08595 08596 res = -1; 08597 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 08598 ast_get_context_name(con), inc->rname); 08599 break; 08600 } 08601 08602 return res; 08603 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) |
Definition at line 2685 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(), store_curl(), and update_curl().
02686 { 02687 struct ast_custom_function *acf = NULL; 02688 02689 AST_RWLIST_RDLOCK(&acf_root); 02690 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 02691 if (!strcmp(name, acf->name)) 02692 break; 02693 } 02694 AST_RWLIST_UNLOCK(&acf_root); 02695 02696 return acf; 02697 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 2699 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 reload(), and unload_module().
02700 { 02701 struct ast_custom_function *cur; 02702 02703 if (!acf) 02704 return -1; 02705 02706 AST_RWLIST_WRLOCK(&acf_root); 02707 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) 02708 ast_verb(2, "Unregistered custom function %s\n", cur->name); 02709 AST_RWLIST_UNLOCK(&acf_root); 02710 02711 return cur ? 0 : -1; 02712 }
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 3589 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_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(), process_ast_dsp(), readexten_exec(), register_peer_exten(), skinny_ss(), socket_process(), ss_thread(), and waitstream_core().
03590 { 03591 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 03592 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6447 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().
06448 { 06449 if (!chan) 06450 return -1; 06451 06452 ast_channel_lock(chan); 06453 06454 if (!ast_strlen_zero(context)) 06455 ast_copy_string(chan->context, context, sizeof(chan->context)); 06456 if (!ast_strlen_zero(exten)) 06457 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06458 if (priority > -1) { 06459 chan->priority = priority; 06460 /* see flag description in channel.h for explanation */ 06461 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 06462 chan->priority--; 06463 } 06464 06465 ast_channel_unlock(chan); 06466 06467 return 0; 06468 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 1978 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().
01979 { 01980 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 01981 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 01982 return extension_match_core(pattern, data, needmore); 01983 }
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 1780 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
01781 { 01782 return ext_cmp(a, b); 01783 }
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 1973 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().
01974 { 01975 return extension_match_core(pattern, data, E_MATCH); 01976 }
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 3266 of file pbx.c.
References ast_extension_state2(), and ast_hint_extension().
Referenced by action_extensionstate(), extstate_read(), and handle_request_subscribe().
03267 { 03268 struct ast_exten *e; 03269 03270 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */ 03271 if (!e) 03272 return -1; /* No hint, return -1 */ 03273 03274 return ast_extension_state2(e); /* Check all devices in the hint */ 03275 }
static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
Check state of extension by using hints.
Definition at line 3176 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_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, inuse, and strsep().
Referenced by ast_add_hint_nolock(), ast_extension_state(), and handle_statechange().
03177 { 03178 char hint[AST_MAX_EXTENSION]; 03179 char *cur, *rest; 03180 int allunavailable = 1, allbusy = 1, allfree = 1; 03181 int busy = 0, inuse = 0, ring = 0, onhold = 0; 03182 03183 if (!e) 03184 return -1; 03185 03186 ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint)); 03187 03188 rest = hint; /* One or more devices separated with a & character */ 03189 while ( (cur = strsep(&rest, "&")) ) { 03190 int res = ast_device_state(cur); 03191 switch (res) { 03192 case AST_DEVICE_NOT_INUSE: 03193 allunavailable = 0; 03194 allbusy = 0; 03195 break; 03196 case AST_DEVICE_INUSE: 03197 inuse = 1; 03198 allunavailable = 0; 03199 allfree = 0; 03200 break; 03201 case AST_DEVICE_RINGING: 03202 ring = 1; 03203 allunavailable = 0; 03204 allfree = 0; 03205 break; 03206 case AST_DEVICE_RINGINUSE: 03207 inuse = 1; 03208 ring = 1; 03209 allunavailable = 0; 03210 allfree = 0; 03211 break; 03212 case AST_DEVICE_ONHOLD: 03213 allunavailable = 0; 03214 allfree = 0; 03215 onhold = 1; 03216 break; 03217 case AST_DEVICE_BUSY: 03218 allunavailable = 0; 03219 allfree = 0; 03220 busy = 1; 03221 inuse = 1; 03222 break; 03223 case AST_DEVICE_UNAVAILABLE: 03224 case AST_DEVICE_INVALID: 03225 allbusy = 0; 03226 allfree = 0; 03227 break; 03228 default: 03229 allunavailable = 0; 03230 allbusy = 0; 03231 allfree = 0; 03232 } 03233 } 03234 03235 if (allfree) 03236 return AST_EXTENSION_NOT_INUSE; 03237 if ((inuse || onhold) && ring) 03238 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 03239 if (allbusy) 03240 return AST_EXTENSION_BUSY; 03241 if (inuse) 03242 return AST_EXTENSION_INUSE; 03243 if (ring) 03244 return AST_EXTENSION_RINGING; 03245 if (onhold) 03246 return AST_EXTENSION_ONHOLD; 03247 if (allunavailable) 03248 return AST_EXTENSION_UNAVAILABLE; 03249 03250 return AST_EXTENSION_NOT_INUSE; 03251 }
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 3254 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().
03255 { 03256 int i; 03257 03258 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 03259 if (extension_states[i].extension_state == extension_state) 03260 return extension_states[i].text; 03261 } 03262 return "Unknown"; 03263 }
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 3364 of file pbx.c.
References ast_calloc, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_state_cb::callback, ast_state_cb::data, ast_state_cb::next, and statecbs.
Referenced by __init_manager(), and handle_request_subscribe().
03366 { 03367 struct ast_hint *hint; 03368 struct ast_state_cb *cblist; 03369 struct ast_exten *e; 03370 03371 /* If there's no context and extension: add callback to statecbs list */ 03372 if (!context && !exten) { 03373 AST_RWLIST_WRLOCK(&hints); 03374 03375 for (cblist = statecbs; cblist; cblist = cblist->next) { 03376 if (cblist->callback == callback) { 03377 cblist->data = data; 03378 AST_RWLIST_UNLOCK(&hints); 03379 return 0; 03380 } 03381 } 03382 03383 /* Now insert the callback */ 03384 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 03385 AST_RWLIST_UNLOCK(&hints); 03386 return -1; 03387 } 03388 cblist->id = 0; 03389 cblist->callback = callback; 03390 cblist->data = data; 03391 03392 cblist->next = statecbs; 03393 statecbs = cblist; 03394 03395 AST_RWLIST_UNLOCK(&hints); 03396 return 0; 03397 } 03398 03399 if (!context || !exten) 03400 return -1; 03401 03402 /* This callback type is for only one hint, so get the hint */ 03403 e = ast_hint_extension(NULL, context, exten); 03404 if (!e) { 03405 return -1; 03406 } 03407 03408 /* Find the hint in the list of hints */ 03409 AST_RWLIST_WRLOCK(&hints); 03410 03411 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03412 if (hint->exten == e) 03413 break; 03414 } 03415 03416 if (!hint) { 03417 /* We have no hint, sorry */ 03418 AST_RWLIST_UNLOCK(&hints); 03419 return -1; 03420 } 03421 03422 /* Now insert the callback in the callback list */ 03423 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 03424 AST_RWLIST_UNLOCK(&hints); 03425 return -1; 03426 } 03427 cblist->id = stateid++; /* Unique ID for this callback */ 03428 cblist->callback = callback; /* Pointer to callback routine */ 03429 cblist->data = data; /* Data for the callback */ 03430 03431 cblist->next = hint->callbacks; 03432 hint->callbacks = cblist; 03433 03434 AST_RWLIST_UNLOCK(&hints); 03435 return cblist->id; 03436 }
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 3439 of file pbx.c.
References ast_free, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_hint::callbacks, ast_hint::list, ast_state_cb::next, and statecbs.
Referenced by __sip_destroy(), handle_request_subscribe(), and skinny_unregister().
03440 { 03441 struct ast_state_cb **p_cur = NULL; /* address of pointer to us */ 03442 int ret = -1; 03443 03444 if (!id && !callback) 03445 return -1; 03446 03447 AST_RWLIST_WRLOCK(&hints); 03448 03449 if (!id) { /* id == 0 is a callback without extension */ 03450 for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) { 03451 if ((*p_cur)->callback == callback) 03452 break; 03453 } 03454 } else { /* callback with extension, find the callback based on ID */ 03455 struct ast_hint *hint; 03456 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03457 for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) { 03458 if ((*p_cur)->id == id) 03459 break; 03460 } 03461 if (*p_cur) /* found in the inner loop */ 03462 break; 03463 } 03464 } 03465 if (p_cur && *p_cur) { 03466 struct ast_state_cb *cur = *p_cur; 03467 *p_cur = cur->next; 03468 ast_free(cur); 03469 ret = 0; 03470 } 03471 AST_RWLIST_UNLOCK(&hints); 03472 return ret; 03473 }
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 3594 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().
03595 { 03596 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 03597 }
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 3599 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
03600 { 03601 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 03602 }
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 2772 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(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
02773 { 02774 char *copy = ast_strdupa(function); 02775 char *args = func_args(copy); 02776 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 02777 02778 if (acfptr == NULL) 02779 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 02780 else if (!acfptr->read) 02781 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 02782 else { 02783 int res; 02784 struct ast_module_user *u = NULL; 02785 if (acfptr->mod) 02786 u = __ast_module_user_add(acfptr->mod, chan); 02787 res = acfptr->read(chan, copy, args, workspace, len); 02788 if (acfptr->mod && u) 02789 __ast_module_user_remove(acfptr->mod, u); 02790 return res; 02791 } 02792 return -1; 02793 }
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 2795 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().
02796 { 02797 char *copy = ast_strdupa(function); 02798 char *args = func_args(copy); 02799 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 02800 02801 if (acfptr == NULL) 02802 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 02803 else if (!acfptr->write) 02804 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 02805 else { 02806 int res; 02807 struct ast_module_user *u = NULL; 02808 if (acfptr->mod) 02809 u = __ast_module_user_add(acfptr->mod, chan); 02810 res = acfptr->write(chan, copy, args, value); 02811 if (acfptr->mod && u) 02812 __ast_module_user_remove(acfptr->mod, u); 02813 return res; 02814 } 02815 02816 return -1; 02817 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 8439 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(), and show_dialplan_helper().
08440 { 08441 return con ? con->name : NULL; 08442 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 8477 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), and show_dialplan_helper().
08478 { 08479 return c ? c->registrar : NULL; 08480 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 8507 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().
08508 { 08509 return e ? e->app : NULL; 08510 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 8512 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().
08513 { 08514 return e ? e->data : NULL; 08515 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 8502 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
08503 { 08504 return e ? e->cidmatch : NULL; 08505 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) |
Definition at line 8444 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 8454 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 8497 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
08498 { 08499 return e ? e->matchcid : 0; 08500 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 8449 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 8469 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 8482 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
08483 { 08484 return e ? e->registrar : NULL; 08485 }
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 3572 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().
03573 { 03574 struct ast_exten *e = ast_hint_extension(c, context, exten); 03575 03576 if (e) { 03577 if (hint) 03578 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 03579 if (name) { 03580 const char *tmp = ast_get_extension_app_data(e); 03581 if (tmp) 03582 ast_copy_string(name, tmp, namesize); 03583 } 03584 return -1; 03585 } 03586 return 0; 03587 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 8464 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().
08465 { 08466 return ip ? ip->pattern : NULL; 08467 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 8492 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().
08493 { 08494 return ip ? ip->registrar : NULL; 08495 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 8459 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().
08460 { 08461 return inc ? inc->name : NULL; 08462 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 8487 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().
08488 { 08489 return i ? i->registrar : NULL; 08490 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 8522 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().
08523 { 08524 return sw ? sw->data : NULL; 08525 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 8527 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
08528 { 08529 return sw->eval; 08530 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 8517 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().
08518 { 08519 return sw ? sw->name : NULL; 08520 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 8532 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().
08533 { 08534 return sw ? sw->registrar : NULL; 08535 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8625 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(), select_entry(), and valid_exit().
08626 { 08627 return __ast_goto_if_exists(chan, context, exten, priority, 0); 08628 }
int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
const void * | ah_b | |||
) |
Definition at line 363 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
00364 { 00365 const struct ast_context *ac = ah_a; 00366 const struct ast_context *bc = ah_b; 00367 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 00368 return 1; 00369 /* assume context names are registered in a string table! */ 00370 return strcmp(ac->name, bc->name); 00371 }
unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 406 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().
00407 { 00408 const struct ast_context *ac = obj; 00409 return ast_hashtab_hash_string(ac->name); 00410 }
static struct ast_exten* ast_hint_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) | [static] |
Find hint for given extension in context.
Definition at line 3163 of file pbx.c.
References ast_rdlock_contexts(), ast_unlock_contexts(), E_MATCH, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.
Referenced by ast_extension_state(), and ast_get_hint().
03164 { 03165 struct ast_exten *e; 03166 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 03167 03168 ast_rdlock_contexts(); 03169 e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 03170 ast_unlock_contexts(); 03171 03172 return e; 03173 }
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 6412 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().
06413 { 06414 struct ast_context *con = ast_context_find(context); 06415 if (con) { 06416 struct ast_ignorepat *pat; 06417 for (pat = con->ignorepats; pat; pat = pat->next) { 06418 if (ast_extension_match(pat->pattern, pattern)) 06419 return 1; 06420 } 06421 } 06422 06423 return 0; 06424 }
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 3609 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(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), readexten_exec(), skinny_ss(), and ss_thread().
03610 { 03611 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 03612 }
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 5774 of file pbx.c.
References __ast_internal_context_destroy(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), 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_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), ast_wrlock_contexts_version(), ast_state_cb::callback, ast_hint::callbacks, store_hint::callbacks, store_hint::context, context_merge(), contexts, contexts_table, ast_state_cb::data, E_MATCH, store_hint::exten, ast_hint::exten, ast_exten::exten, store_hint::laststate, ast_hint::laststate, store_hint::list, LOG_WARNING, ast_context::name, ast_state_cb::next, 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().
05775 { 05776 double ft; 05777 struct ast_context *tmp, *oldcontextslist; 05778 struct ast_hashtab *oldtable; 05779 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 05780 struct store_hint *this; 05781 struct ast_hint *hint; 05782 struct ast_exten *exten; 05783 int length; 05784 struct ast_state_cb *thiscb, *prevcb; 05785 struct ast_hashtab_iter *iter; 05786 05787 /* it is very important that this function hold the hint list lock _and_ the conlock 05788 during its operation; not only do we need to ensure that the list of contexts 05789 and extensions does not change, but also that no hint callbacks (watchers) are 05790 added or removed during the merge/delete process 05791 05792 in addition, the locks _must_ be taken in this order, because there are already 05793 other code paths that use this order 05794 */ 05795 05796 struct timeval begintime, writelocktime, endlocktime, enddeltime; 05797 int wrlock_ver; 05798 05799 begintime = ast_tvnow(); 05800 ast_rdlock_contexts(); 05801 iter = ast_hashtab_start_traversal(contexts_table); 05802 while ((tmp=ast_hashtab_next(iter))) { 05803 context_merge(extcontexts, exttable, tmp, registrar); 05804 } 05805 ast_hashtab_end_traversal(iter); 05806 wrlock_ver = ast_wrlock_contexts_version(); 05807 05808 ast_unlock_contexts(); /* this feels real retarded, but you must do 05809 what you must do If this isn't done, the following 05810 wrlock is a guraranteed deadlock */ 05811 ast_wrlock_contexts(); 05812 if (ast_wrlock_contexts_version() > wrlock_ver+1) { 05813 ast_log(LOG_WARNING,"==================!!!!!!!!!!!!!!!Something changed the contexts in the middle of merging contexts!\n"); 05814 } 05815 05816 AST_RWLIST_WRLOCK(&hints); 05817 writelocktime = ast_tvnow(); 05818 05819 /* preserve all watchers for hints associated with this registrar */ 05820 AST_RWLIST_TRAVERSE(&hints, hint, list) { 05821 if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) { 05822 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 05823 if (!(this = ast_calloc(1, length))) 05824 continue; 05825 this->callbacks = hint->callbacks; 05826 hint->callbacks = NULL; 05827 this->laststate = hint->laststate; 05828 this->context = this->data; 05829 strcpy(this->data, hint->exten->parent->name); 05830 this->exten = this->data + strlen(this->context) + 1; 05831 strcpy(this->exten, hint->exten->exten); 05832 AST_LIST_INSERT_HEAD(&store, this, list); 05833 } 05834 } 05835 05836 /* save the old table and list */ 05837 oldtable = contexts_table; 05838 oldcontextslist = contexts; 05839 05840 /* move in the new table and list */ 05841 contexts_table = exttable; 05842 contexts = *extcontexts; 05843 05844 /* restore the watchers for hints that can be found; notify those that 05845 cannot be restored 05846 */ 05847 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 05848 struct pbx_find_info q = { .stacklen = 0 }; 05849 exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH); 05850 /* Find the hint in the list of hints */ 05851 AST_RWLIST_TRAVERSE(&hints, hint, list) { 05852 if (hint->exten == exten) 05853 break; 05854 } 05855 if (!exten || !hint) { 05856 /* this hint has been removed, notify the watchers */ 05857 prevcb = NULL; 05858 thiscb = this->callbacks; 05859 while (thiscb) { 05860 prevcb = thiscb; 05861 thiscb = thiscb->next; 05862 prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data); 05863 ast_free(prevcb); 05864 } 05865 } else { 05866 thiscb = this->callbacks; 05867 while (thiscb->next) 05868 thiscb = thiscb->next; 05869 thiscb->next = hint->callbacks; 05870 hint->callbacks = this->callbacks; 05871 hint->laststate = this->laststate; 05872 } 05873 ast_free(this); 05874 } 05875 05876 AST_RWLIST_UNLOCK(&hints); 05877 ast_unlock_contexts(); 05878 endlocktime = ast_tvnow(); 05879 05880 /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk 05881 is now freely using the new stuff instead */ 05882 05883 ast_hashtab_destroy(oldtable, NULL); 05884 05885 for (tmp = oldcontextslist; tmp; ) { 05886 struct ast_context *next; /* next starting point */ 05887 next = tmp->next; 05888 __ast_internal_context_destroy(tmp); 05889 tmp = next; 05890 } 05891 enddeltime = ast_tvnow(); 05892 05893 ft = ast_tvdiff_us(writelocktime, begintime); 05894 ft /= 1000000.0; 05895 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 05896 05897 ft = ast_tvdiff_us(endlocktime, writelocktime); 05898 ft /= 1000000.0; 05899 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 05900 05901 ft = ast_tvdiff_us(enddeltime, endlocktime); 05902 ft /= 1000000.0; 05903 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 05904 05905 ft = ast_tvdiff_us(enddeltime, begintime); 05906 ft /= 1000000.0; 05907 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 05908 return; 05909 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
This function will handle locking the channel as needed.
Definition at line 8688 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().
08689 { 08690 return pbx_parseable_goto(chan, goto_string, 0); 08691 }
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 7228 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().
07229 { 07230 struct ast_channel *chan; 07231 struct app_tmp *tmp; 07232 int res = -1, cdr_res = -1; 07233 struct outgoing_helper oh; 07234 07235 memset(&oh, 0, sizeof(oh)); 07236 oh.vars = vars; 07237 oh.account = account; 07238 07239 if (locked_channel) 07240 *locked_channel = NULL; 07241 if (ast_strlen_zero(app)) { 07242 res = -1; 07243 goto outgoing_app_cleanup; 07244 } 07245 if (sync) { 07246 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07247 if (chan) { 07248 ast_set_variables(chan, vars); 07249 if (account) 07250 ast_cdr_setaccount(chan, account); 07251 if (chan->_state == AST_STATE_UP) { 07252 res = 0; 07253 ast_verb(4, "Channel %s was answered.\n", chan->name); 07254 tmp = ast_calloc(1, sizeof(*tmp)); 07255 if (!tmp) 07256 res = -1; 07257 else { 07258 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 07259 if (appdata) 07260 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 07261 tmp->chan = chan; 07262 if (sync > 1) { 07263 if (locked_channel) 07264 ast_channel_unlock(chan); 07265 ast_pbx_run_app(tmp); 07266 } else { 07267 if (locked_channel) 07268 ast_channel_lock(chan); 07269 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 07270 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 07271 ast_free(tmp); 07272 if (locked_channel) 07273 ast_channel_unlock(chan); 07274 ast_hangup(chan); 07275 res = -1; 07276 } else { 07277 if (locked_channel) 07278 *locked_channel = chan; 07279 } 07280 } 07281 } 07282 } else { 07283 ast_verb(4, "Channel %s was never answered.\n", chan->name); 07284 if (chan->cdr) { /* update the cdr */ 07285 /* here we update the status of the call, which sould be busy. 07286 * if that fails then we set the status to failed */ 07287 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 07288 ast_cdr_failed(chan->cdr); 07289 } 07290 ast_hangup(chan); 07291 } 07292 } 07293 07294 if (res < 0) { /* the call failed for some reason */ 07295 if (*reason == 0) { /* if the call failed (not busy or no answer) 07296 * update the cdr with the failed message */ 07297 cdr_res = ast_pbx_outgoing_cdr_failed(); 07298 if (cdr_res != 0) { 07299 res = cdr_res; 07300 goto outgoing_app_cleanup; 07301 } 07302 } 07303 } 07304 07305 } else { 07306 struct async_stat *as; 07307 if (!(as = ast_calloc(1, sizeof(*as)))) { 07308 res = -1; 07309 goto outgoing_app_cleanup; 07310 } 07311 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07312 if (!chan) { 07313 ast_free(as); 07314 res = -1; 07315 goto outgoing_app_cleanup; 07316 } 07317 as->chan = chan; 07318 ast_copy_string(as->app, app, sizeof(as->app)); 07319 if (appdata) 07320 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 07321 as->timeout = timeout; 07322 ast_set_variables(chan, vars); 07323 if (account) 07324 ast_cdr_setaccount(chan, account); 07325 /* Start a new thread, and get something handling this channel. */ 07326 if (locked_channel) 07327 ast_channel_lock(chan); 07328 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 07329 ast_log(LOG_WARNING, "Failed to start async wait\n"); 07330 ast_free(as); 07331 if (locked_channel) 07332 ast_channel_unlock(chan); 07333 ast_hangup(chan); 07334 res = -1; 07335 goto outgoing_app_cleanup; 07336 } else { 07337 if (locked_channel) 07338 *locked_channel = chan; 07339 } 07340 res = 0; 07341 } 07342 outgoing_app_cleanup: 07343 ast_variables_destroy(vars); 07344 return res; 07345 }
static int ast_pbx_outgoing_cdr_failed | ( | void | ) | [static] |
Function to post an empty cdr after a spool call fails.
Definition at line 7036 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().
07037 { 07038 /* allocate a channel */ 07039 struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", ""); 07040 07041 if (!chan) 07042 return -1; /* failure */ 07043 07044 if (!chan->cdr) { 07045 /* allocation of the cdr failed */ 07046 ast_channel_free(chan); /* free the channel */ 07047 return -1; /* return failure */ 07048 } 07049 07050 /* allocation of the cdr was successful */ 07051 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 07052 ast_cdr_start(chan->cdr); /* record the start and stop time */ 07053 ast_cdr_end(chan->cdr); 07054 ast_cdr_failed(chan->cdr); /* set the status to failed */ 07055 ast_cdr_detach(chan->cdr); /* post and free the record */ 07056 chan->cdr = NULL; 07057 ast_channel_free(chan); /* free the channel */ 07058 07059 return 0; /* success */ 07060 }
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 7062 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().
07063 { 07064 struct ast_channel *chan; 07065 struct async_stat *as; 07066 int res = -1, cdr_res = -1; 07067 struct outgoing_helper oh; 07068 07069 if (sync) { 07070 oh.context = context; 07071 oh.exten = exten; 07072 oh.priority = priority; 07073 oh.cid_num = cid_num; 07074 oh.cid_name = cid_name; 07075 oh.account = account; 07076 oh.vars = vars; 07077 oh.parent_channel = NULL; 07078 07079 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07080 if (channel) { 07081 *channel = chan; 07082 if (chan) 07083 ast_channel_lock(chan); 07084 } 07085 if (chan) { 07086 if (chan->_state == AST_STATE_UP) { 07087 res = 0; 07088 ast_verb(4, "Channel %s was answered.\n", chan->name); 07089 07090 if (sync > 1) { 07091 if (channel) 07092 ast_channel_unlock(chan); 07093 if (ast_pbx_run(chan)) { 07094 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 07095 if (channel) 07096 *channel = NULL; 07097 ast_hangup(chan); 07098 chan = NULL; 07099 res = -1; 07100 } 07101 } else { 07102 if (ast_pbx_start(chan)) { 07103 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 07104 if (channel) { 07105 *channel = NULL; 07106 ast_channel_unlock(chan); 07107 } 07108 ast_hangup(chan); 07109 res = -1; 07110 } 07111 chan = NULL; 07112 } 07113 } else { 07114 ast_verb(4, "Channel %s was never answered.\n", chan->name); 07115 07116 if (chan->cdr) { /* update the cdr */ 07117 /* here we update the status of the call, which sould be busy. 07118 * if that fails then we set the status to failed */ 07119 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 07120 ast_cdr_failed(chan->cdr); 07121 } 07122 07123 if (channel) { 07124 *channel = NULL; 07125 ast_channel_unlock(chan); 07126 } 07127 ast_hangup(chan); 07128 chan = NULL; 07129 } 07130 } 07131 07132 if (res < 0) { /* the call failed for some reason */ 07133 if (*reason == 0) { /* if the call failed (not busy or no answer) 07134 * update the cdr with the failed message */ 07135 cdr_res = ast_pbx_outgoing_cdr_failed(); 07136 if (cdr_res != 0) { 07137 res = cdr_res; 07138 goto outgoing_exten_cleanup; 07139 } 07140 } 07141 07142 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 07143 /* check if "failed" exists */ 07144 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 07145 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed"); 07146 if (chan) { 07147 char failed_reason[4] = ""; 07148 if (!ast_strlen_zero(context)) 07149 ast_copy_string(chan->context, context, sizeof(chan->context)); 07150 set_ext_pri(chan, "failed", 1); 07151 ast_set_variables(chan, vars); 07152 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 07153 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 07154 if (account) 07155 ast_cdr_setaccount(chan, account); 07156 if (ast_pbx_run(chan)) { 07157 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 07158 ast_hangup(chan); 07159 } 07160 chan = NULL; 07161 } 07162 } 07163 } 07164 } else { 07165 if (!(as = ast_calloc(1, sizeof(*as)))) { 07166 res = -1; 07167 goto outgoing_exten_cleanup; 07168 } 07169 chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name); 07170 if (channel) { 07171 *channel = chan; 07172 if (chan) 07173 ast_channel_lock(chan); 07174 } 07175 if (!chan) { 07176 ast_free(as); 07177 res = -1; 07178 goto outgoing_exten_cleanup; 07179 } 07180 as->chan = chan; 07181 ast_copy_string(as->context, context, sizeof(as->context)); 07182 set_ext_pri(as->chan, exten, priority); 07183 as->timeout = timeout; 07184 ast_set_variables(chan, vars); 07185 if (account) 07186 ast_cdr_setaccount(chan, account); 07187 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 07188 ast_log(LOG_WARNING, "Failed to start async wait\n"); 07189 ast_free(as); 07190 if (channel) { 07191 *channel = NULL; 07192 ast_channel_unlock(chan); 07193 } 07194 ast_hangup(chan); 07195 res = -1; 07196 goto outgoing_exten_cleanup; 07197 } 07198 res = 0; 07199 } 07200 outgoing_exten_cleanup: 07201 ast_variables_destroy(vars); 07202 return res; 07203 }
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 4021 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().
04022 { 04023 return ast_pbx_run_args(c, NULL); 04024 }
static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 7213 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().
07214 { 07215 struct app_tmp *tmp = data; 07216 struct ast_app *app; 07217 app = pbx_findapp(tmp->app); 07218 if (app) { 07219 ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 07220 pbx_exec(tmp->chan, app, tmp->data); 07221 } else 07222 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 07223 ast_hangup(tmp->chan); 07224 ast_free(tmp); 07225 return NULL; 07226 }
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 4006 of file pbx.c.
References __ast_pbx_run(), AST_PBX_CALL_LIMIT, AST_PBX_SUCCESS, decrease_call_count(), and increase_call_count().
Referenced by ast_pbx_run(), dial_exec_full(), and handle_gosub().
04007 { 04008 enum ast_pbx_result res = AST_PBX_SUCCESS; 04009 04010 if (increase_call_count(c)) { 04011 return AST_PBX_CALL_LIMIT; 04012 } 04013 04014 res = __ast_pbx_run(c, args); 04015 04016 decrease_call_count(); 04017 04018 return res; 04019 }
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 3984 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(), do_parking_thread(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), rpt_call(), sip_new(), skinny_new(), unistim_new(), and usbradio_new().
03985 { 03986 pthread_t t; 03987 03988 if (!c) { 03989 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 03990 return AST_PBX_FAILED; 03991 } 03992 03993 if (increase_call_count(c)) 03994 return AST_PBX_CALL_LIMIT; 03995 03996 /* Start a new thread, and get something handling this channel. */ 03997 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 03998 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 03999 decrease_call_count(); 04000 return AST_PBX_FAILED; 04001 } 04002 04003 return AST_PBX_SUCCESS; 04004 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 4031 of file pbx.c.
Referenced by handle_chanlist(), and handle_showcalls().
04032 { 04033 return totalcalls; 04034 }
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 8426 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(), and show_dialplan_helper().
08427 { 08428 return ast_rwlock_rdlock(&con->lock); 08429 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 8408 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_dialplan_helper(), and unreference_cached_app().
08409 { 08410 return ast_rwlock_rdlock(&conlock); 08411 }
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 4455 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().
04456 { 04457 struct ast_app *tmp, *cur = NULL; 04458 char tmps[80]; 04459 int length, res; 04460 04461 AST_RWLIST_WRLOCK(&apps); 04462 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 04463 if (!(res = strcasecmp(app, tmp->name))) { 04464 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 04465 AST_RWLIST_UNLOCK(&apps); 04466 return -1; 04467 } else if (res < 0) 04468 break; 04469 } 04470 04471 length = sizeof(*tmp) + strlen(app) + 1; 04472 04473 if (!(tmp = ast_calloc(1, length))) { 04474 AST_RWLIST_UNLOCK(&apps); 04475 return -1; 04476 } 04477 04478 strcpy(tmp->name, app); 04479 tmp->execute = execute; 04480 tmp->synopsis = synopsis; 04481 tmp->description = description; 04482 tmp->module = mod; 04483 04484 /* Store in alphabetical order */ 04485 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 04486 if (strcasecmp(tmp->name, cur->name) < 0) { 04487 AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list); 04488 break; 04489 } 04490 } 04491 AST_RWLIST_TRAVERSE_SAFE_END; 04492 if (!cur) 04493 AST_RWLIST_INSERT_TAIL(&apps, tmp, list); 04494 04495 ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 04496 04497 AST_RWLIST_UNLOCK(&apps); 04498 04499 return 0; 04500 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
Definition at line 4506 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().
04507 { 04508 struct ast_switch *tmp; 04509 04510 AST_RWLIST_WRLOCK(&switches); 04511 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 04512 if (!strcasecmp(tmp->name, sw->name)) { 04513 AST_RWLIST_UNLOCK(&switches); 04514 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 04515 return -1; 04516 } 04517 } 04518 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 04519 AST_RWLIST_UNLOCK(&switches); 04520 04521 return 0; 04522 }
static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
Remove hint from extension.
Definition at line 3537 of file pbx.c.
References AST_EXTENSION_DEACTIVATED, ast_free, 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_exten::exten, ast_hint::exten, ast_context::name, ast_state_cb::next, and ast_exten::parent.
Referenced by destroy_exten().
03538 { 03539 /* Cleanup the Notifys if hint is removed */ 03540 struct ast_hint *hint; 03541 struct ast_state_cb *cblist, *cbprev; 03542 int res = -1; 03543 03544 if (!e) 03545 return -1; 03546 03547 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) { 03548 if (hint->exten == e) { 03549 cbprev = NULL; 03550 cblist = hint->callbacks; 03551 while (cblist) { 03552 /* Notify with -1 and remove all callbacks */ 03553 cbprev = cblist; 03554 cblist = cblist->next; 03555 cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data); 03556 ast_free(cbprev); 03557 } 03558 hint->callbacks = NULL; 03559 AST_RWLIST_REMOVE_CURRENT(list); 03560 ast_free(hint); 03561 res = 0; 03562 break; 03563 } 03564 } 03565 AST_RWLIST_TRAVERSE_SAFE_END; 03566 03567 return res; 03568 }
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 3614 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().
03615 { 03616 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 03617 }
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 8431 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(), and show_dialplan_helper().
08432 { 08433 return ast_rwlock_unlock(&con->lock); 08434 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 8413 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_dialplan_helper(), and unreference_cached_app().
08414 { 08415 return ast_rwlock_unlock(&conlock); 08416 }
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 5555 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().
05556 { 05557 struct ast_app *tmp; 05558 05559 AST_RWLIST_WRLOCK(&apps); 05560 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 05561 if (!strcasecmp(app, tmp->name)) { 05562 unreference_cached_app(tmp); 05563 AST_RWLIST_REMOVE_CURRENT(list); 05564 ast_verb(2, "Unregistered application '%s'\n", tmp->name); 05565 ast_free(tmp); 05566 break; 05567 } 05568 } 05569 AST_RWLIST_TRAVERSE_SAFE_END; 05570 AST_RWLIST_UNLOCK(&apps); 05571 05572 return tmp ? 0 : -1; 05573 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 4524 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().
04525 { 04526 AST_RWLIST_WRLOCK(&switches); 04527 AST_RWLIST_REMOVE(&switches, sw, list); 04528 AST_RWLIST_UNLOCK(&switches); 04529 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) |
Definition at line 8545 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().
08547 { 08548 if (!exten) 08549 return con ? con->root : NULL; 08550 else 08551 return exten->next; 08552 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) |
Definition at line 8578 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().
08580 { 08581 if (!ip) 08582 return con ? con->ignorepats : NULL; 08583 else 08584 return ip->next; 08585 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) |
Definition at line 8569 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().
08571 { 08572 if (!inc) 08573 return con ? con->includes : NULL; 08574 else 08575 return inc->next; 08576 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) |
Definition at line 8554 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().
08556 { 08557 if (!sw) 08558 return con ? AST_LIST_FIRST(&con->alts) : NULL; 08559 else 08560 return AST_LIST_NEXT(sw, list); 08561 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) |
Definition at line 8540 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_dialplan_helper(), and unreference_cached_app().
struct ast_exten* ast_walk_extension_priorities | ( | struct ast_exten * | exten, | |
struct ast_exten * | priority | |||
) |
Definition at line 8563 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 8421 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().
08422 { 08423 return ast_rwlock_wrlock(&con->lock); 08424 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 8400 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().
08401 { 08402 int res = ast_rwlock_wrlock(&conlock); 08403 if (!res) 08404 ast_atomic_fetchadd_int(&conlock_wrlock_version, 1); 08405 return res; 08406 }
int ast_wrlock_contexts_version | ( | void | ) |
Definition at line 8392 of file pbx.c.
Referenced by ast_merge_contexts_and_delete().
08393 { 08394 return conlock_wrlock_version; 08395 }
static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 6975 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().
06976 { 06977 struct async_stat *as = data; 06978 struct ast_channel *chan = as->chan; 06979 int timeout = as->timeout; 06980 int res; 06981 struct ast_frame *f; 06982 struct ast_app *app; 06983 06984 while (timeout && (chan->_state != AST_STATE_UP)) { 06985 res = ast_waitfor(chan, timeout); 06986 if (res < 1) 06987 break; 06988 if (timeout > -1) 06989 timeout = res; 06990 f = ast_read(chan); 06991 if (!f) 06992 break; 06993 if (f->frametype == AST_FRAME_CONTROL) { 06994 if ((f->subclass == AST_CONTROL_BUSY) || 06995 (f->subclass == AST_CONTROL_CONGESTION) ) { 06996 ast_frfree(f); 06997 break; 06998 } 06999 } 07000 ast_frfree(f); 07001 } 07002 if (chan->_state == AST_STATE_UP) { 07003 if (!ast_strlen_zero(as->app)) { 07004 app = pbx_findapp(as->app); 07005 if (app) { 07006 ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 07007 pbx_exec(chan, app, as->appdata); 07008 } else 07009 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 07010 } else { 07011 if (!ast_strlen_zero(as->context)) 07012 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 07013 if (!ast_strlen_zero(as->exten)) 07014 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 07015 if (as->priority > 0) 07016 chan->priority = as->priority; 07017 /* Run the PBX */ 07018 if (ast_pbx_run(chan)) { 07019 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 07020 } else { 07021 /* PBX will have taken care of this */ 07022 chan = NULL; 07023 } 07024 } 07025 } 07026 ast_free(as); 07027 if (chan) 07028 ast_hangup(chan); 07029 return NULL; 07030 }
static void cli_match_char_tree | ( | struct match_char * | node, | |
char * | prefix, | |||
int | fd | |||
) | [static] |
Definition at line 1126 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_dialplan_helper().
01127 { 01128 char extenstr[40]; 01129 struct ast_str *my_prefix = ast_str_alloca(1024); 01130 01131 extenstr[0] = '\0'; 01132 01133 if (node && node->exten && node->exten) 01134 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01135 01136 if (strlen(node->x) > 1) { 01137 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01138 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01139 node->exten ? node->exten->exten : "", extenstr); 01140 } else { 01141 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01142 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01143 node->exten ? node->exten->exten : "", extenstr); 01144 } 01145 01146 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01147 01148 if (node->next_char) 01149 cli_match_char_tree(node->next_char, my_prefix->str, fd); 01150 01151 if (node->alt_char) 01152 cli_match_char_tree(node->alt_char, prefix, fd); 01153 }
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 3633 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::dtimeout, and ast_channel::pbx.
03634 { 03635 int digit; 03636 03637 buf[pos] = '\0'; /* make sure it is properly terminated */ 03638 while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) { 03639 /* As long as we're willing to wait, and as long as it's not defined, 03640 keep reading digits until we can't possibly get a right answer anymore. */ 03641 digit = ast_waitfordigit(c, waittime * 1000); 03642 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 03643 c->_softhangup = 0; 03644 } else { 03645 if (!digit) /* No entry */ 03646 break; 03647 if (digit < 0) /* Error, maybe a hangup */ 03648 return -1; 03649 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 03650 buf[pos++] = digit; 03651 buf[pos] = '\0'; 03652 } 03653 waittime = c->pbx->dtimeout; 03654 } 03655 } 03656 return 0; 03657 }
static int compare_char | ( | const void * | a, | |
const void * | b | |||
) | [static] |
Definition at line 350 of file pbx.c.
Referenced by add_exten_to_pattern_tree().
00351 { 00352 const char *ac = a; 00353 const char *bc = b; 00354 if ((*ac) < (*bc)) 00355 return -1; 00356 else if ((*ac) == (*bc)) 00357 return 0; 00358 else 00359 return 1; 00360 }
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 4683 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().
04684 { 04685 struct ast_hint *hint; 04686 char *ret = NULL; 04687 int which = 0; 04688 int wordlen; 04689 04690 if (pos != 3) 04691 return NULL; 04692 04693 wordlen = strlen(word); 04694 04695 AST_RWLIST_RDLOCK(&hints); 04696 /* walk through all hints */ 04697 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04698 if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) { 04699 ret = ast_strdup(ast_get_extension_name(hint->exten)); 04700 break; 04701 } 04702 } 04703 AST_RWLIST_UNLOCK(&hints); 04704 04705 return ret; 04706 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 4878 of file pbx.c.
References ast_get_context_name(), ast_rdlock_contexts(), ast_strdup, ast_unlock_contexts(), and ast_walk_contexts().
Referenced by handle_show_dialplan().
04880 { 04881 struct ast_context *c = NULL; 04882 char *ret = NULL; 04883 int which = 0; 04884 int wordlen; 04885 04886 /* we are do completion of [exten@]context on second position only */ 04887 if (pos != 2) 04888 return NULL; 04889 04890 ast_rdlock_contexts(); 04891 04892 wordlen = strlen(word); 04893 04894 /* walk through all contexts and return the n-th match */ 04895 while ( (c = ast_walk_contexts(c)) ) { 04896 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 04897 ret = ast_strdup(ast_get_context_name(c)); 04898 break; 04899 } 04900 } 04901 04902 ast_unlock_contexts(); 04903 04904 return ret; 04905 }
static void context_merge | ( | struct ast_context ** | extcontexts, | |
struct ast_hashtab * | exttable, | |||
struct ast_context * | context, | |||
const char * | registrar | |||
) | [static] |
Definition at line 5690 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, first, ast_exten::label, LOG_ERROR, ast_exten::peer_table, ast_exten::priority, and ast_exten::registrar.
Referenced by ast_merge_contexts_and_delete().
05691 { 05692 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */ 05693 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item; 05694 struct ast_hashtab_iter *exten_iter; 05695 struct ast_hashtab_iter *prio_iter; 05696 int insert_count = 0; 05697 int first = 1; 05698 05699 /* We'll traverse all the extensions/prios, and see which are not registrar'd with 05700 the current registrar, and copy them to the new context. If the new context does not 05701 exist, we'll create it "on demand". If no items are in this context to copy, then we'll 05702 only create the empty matching context if the old one meets the criteria */ 05703 05704 if (context->root_table) { 05705 exten_iter = ast_hashtab_start_traversal(context->root_table); 05706 while ((exten_item=ast_hashtab_next(exten_iter))) { 05707 if (new) { 05708 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item); 05709 } else { 05710 new_exten_item = NULL; 05711 } 05712 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 05713 while ((prio_item=ast_hashtab_next(prio_iter))) { 05714 int res1; 05715 char *dupdstr; 05716 05717 if (new_exten_item) { 05718 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item); 05719 } else { 05720 new_prio_item = NULL; 05721 } 05722 if (strcmp(prio_item->registrar,registrar) == 0) { 05723 continue; 05724 } 05725 /* make sure the new context exists, so we have somewhere to stick this exten/prio */ 05726 if (!new) { 05727 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 */ 05728 } 05729 05730 /* copy in the includes, switches, and ignorepats */ 05731 if (first) { /* but, only need to do this once */ 05732 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 05733 first = 0; 05734 } 05735 05736 if (!new) { 05737 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name); 05738 return; /* no sense continuing. */ 05739 } 05740 /* we will not replace existing entries in the new context with stuff from the old context. 05741 but, if this is because of some sort of registrar conflict, we ought to say something... */ 05742 05743 dupdstr = ast_strdup(prio_item->data); 05744 05745 res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 05746 prio_item->cidmatch, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar); 05747 if (!res1 && new_exten_item && new_prio_item){ 05748 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n", 05749 context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar); 05750 } else { 05751 /* 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, 05752 and no double frees take place, either! */ 05753 insert_count++; 05754 } 05755 } 05756 ast_hashtab_end_traversal(prio_iter); 05757 } 05758 ast_hashtab_end_traversal(exten_iter); 05759 } 05760 05761 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 || 05762 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) { 05763 /* we could have given it the registrar of the other module who incremented the refcount, 05764 but that's not available, so we give it the registrar we know about */ 05765 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar); 05766 05767 /* copy in the includes, switches, and ignorepats */ 05768 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 05769 } 05770 }
static void context_merge_incls_swits_igps_other_registrars | ( | struct ast_context * | new, | |
struct ast_context * | old, | |||
const char * | registrar | |||
) | [static] |
Definition at line 5657 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().
05658 { 05659 struct ast_include *i; 05660 struct ast_ignorepat *ip; 05661 struct ast_sw *sw; 05662 05663 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); 05664 /* copy in the includes, switches, and ignorepats */ 05665 /* walk through includes */ 05666 for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) { 05667 if (strcmp(ast_get_include_registrar(i), registrar) == 0) 05668 continue; /* not mine */ 05669 ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i)); 05670 } 05671 05672 /* walk through switches */ 05673 for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) { 05674 if (strcmp(ast_get_switch_registrar(sw), registrar) == 0) 05675 continue; /* not mine */ 05676 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)); 05677 } 05678 05679 /* walk thru ignorepats ... */ 05680 for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) { 05681 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) 05682 continue; /* not mine */ 05683 ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip)); 05684 } 05685 }
static void create_match_char_tree | ( | struct ast_context * | con | ) | [static] |
Definition at line 1589 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().
01590 { 01591 struct ast_hashtab_iter *t1; 01592 struct ast_exten *e1; 01593 #ifdef NEED_DEBUG 01594 int biggest_bucket, resizes, numobjs, numbucks; 01595 01596 ast_log(LOG_DEBUG,"Creating Extension Trie for context %s\n", con->name); 01597 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks); 01598 ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n", 01599 numobjs, numbucks, biggest_bucket, resizes); 01600 #endif 01601 t1 = ast_hashtab_start_traversal(con->root_table); 01602 while( (e1 = ast_hashtab_next(t1)) ) { 01603 if (e1->exten) 01604 add_exten_to_pattern_tree(con, e1, 0); 01605 else 01606 ast_log(LOG_ERROR,"Attempt to create extension with no extension name.\n"); 01607 } 01608 ast_hashtab_end_traversal(t1); 01609 }
static void decrease_call_count | ( | void | ) | [static] |
Definition at line 3942 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), and maxcalllock.
Referenced by ast_pbx_run_args(), ast_pbx_start(), and pbx_thread().
03943 { 03944 ast_mutex_lock(&maxcalllock); 03945 if (countcalls > 0) 03946 countcalls--; 03947 ast_mutex_unlock(&maxcalllock); 03948 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 3950 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().
03951 { 03952 if (e->priority == PRIORITY_HINT) 03953 ast_remove_hint(e); 03954 03955 if (e->peer_table) 03956 ast_hashtab_destroy(e->peer_table,0); 03957 if (e->peer_label_table) 03958 ast_hashtab_destroy(e->peer_label_table, 0); 03959 if (e->datad) 03960 e->datad(e->data); 03961 ast_free(e); 03962 }
static void destroy_pattern_tree | ( | struct match_char * | pattern_tree | ) | [static] |
Definition at line 1611 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().
01612 { 01613 /* destroy all the alternates */ 01614 if (pattern_tree->alt_char) { 01615 destroy_pattern_tree(pattern_tree->alt_char); 01616 pattern_tree->alt_char = 0; 01617 } 01618 /* destroy all the nexts */ 01619 if (pattern_tree->next_char) { 01620 destroy_pattern_tree(pattern_tree->next_char); 01621 pattern_tree->next_char = 0; 01622 } 01623 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */ 01624 if (pattern_tree->x) 01625 free(pattern_tree->x); 01626 free(pattern_tree); 01627 }
static void device_state_cb | ( | const struct ast_event * | event, | |
void * | unused | |||
) | [static] |
Definition at line 8343 of file pbx.c.
References ast_event_get_ie_str(), AST_EVENT_IE_DEVICE, ast_log(), ast_strlen_zero(), LOG_ERROR, and statechange_queue().
Referenced by load_module(), and load_pbx().
08344 { 08345 const char *device; 08346 08347 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 08348 if (ast_strlen_zero(device)) { 08349 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n"); 08350 return; 08351 } 08352 08353 statechange_queue(device); 08354 }
static void* device_state_thread | ( | void * | data | ) | [static] |
Definition at line 3339 of file pbx.c.
References ast_cond_wait(), ast_free, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), statechange::dev, device_state, statechange::entry, and handle_statechange().
Referenced by load_module(), and load_pbx().
03340 { 03341 struct statechange *sc; 03342 03343 while (!device_state.stop) { 03344 ast_mutex_lock(&device_state.lock); 03345 while (!(sc = AST_LIST_REMOVE_HEAD(&device_state.state_change_q, entry))) { 03346 ast_cond_wait(&device_state.cond, &device_state.lock); 03347 /* Check to see if we were woken up to see the request to stop */ 03348 if (device_state.stop) { 03349 ast_mutex_unlock(&device_state.lock); 03350 return NULL; 03351 } 03352 } 03353 ast_mutex_unlock(&device_state.lock); 03354 03355 handle_statechange(sc->dev); 03356 03357 ast_free(sc); 03358 } 03359 03360 return NULL; 03361 }
static void exception_store_free | ( | void * | data | ) | [static] |
Definition at line 2486 of file pbx.c.
References ast_free, and ast_string_field_free_memory.
02487 { 02488 struct pbx_exception *exception = data; 02489 ast_string_field_free_memory(exception); 02490 ast_free(exception); 02491 }
static int ext_cmp | ( | const char * | a, | |
const char * | b | |||
) | [static] |
the full routine to compare extensions in rules.
Definition at line 1754 of file pbx.c.
References ext_cmp1().
Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().
01755 { 01756 /* make sure non-patterns come first. 01757 * If a is not a pattern, it either comes first or 01758 * we use strcmp to compare the strings. 01759 */ 01760 int ret = 0; 01761 01762 if (a[0] != '_') 01763 return (b[0] == '_') ? -1 : strcmp(a, b); 01764 01765 /* Now we know a is a pattern; if b is not, a comes first */ 01766 if (b[0] != '_') 01767 return 1; 01768 #if 0 /* old mode for ext matching */ 01769 return strcmp(a, b); 01770 #endif 01771 /* ok we need full pattern sorting routine */ 01772 while (!ret && a && b) 01773 ret = ext_cmp1(&a) - ext_cmp1(&b); 01774 if (ret == 0) 01775 return 0; 01776 else 01777 return (ret > 0) ? 1 : -1; 01778 }
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 1683 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ext_cmp().
01684 { 01685 uint32_t chars[8]; 01686 int c, cmin = 0xff, count = 0; 01687 const char *end; 01688 01689 /* load, sign extend and advance pointer until we find 01690 * a valid character. 01691 */ 01692 c = *(*p)++; 01693 01694 /* always return unless we have a set of chars */ 01695 switch (toupper(c)) { 01696 default: /* ordinary character */ 01697 return 0x0000 | (c & 0xff); 01698 01699 case 'N': /* 2..9 */ 01700 return 0x0800 | '2' ; 01701 01702 case 'X': /* 0..9 */ 01703 return 0x0A00 | '0'; 01704 01705 case 'Z': /* 1..9 */ 01706 return 0x0900 | '1'; 01707 01708 case '.': /* wildcard */ 01709 return 0x10000; 01710 01711 case '!': /* earlymatch */ 01712 return 0x20000; /* less specific than NULL */ 01713 01714 case '\0': /* empty string */ 01715 *p = NULL; 01716 return 0x30000; 01717 01718 case '[': /* pattern */ 01719 break; 01720 } 01721 /* locate end of set */ 01722 end = strchr(*p, ']'); 01723 01724 if (end == NULL) { 01725 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 01726 return 0x40000; /* XXX make this entry go last... */ 01727 } 01728 01729 memset(chars, '\0', sizeof(chars)); /* clear all chars in the set */ 01730 for (; *p < end ; (*p)++) { 01731 unsigned char c1, c2; /* first-last char in range */ 01732 c1 = (unsigned char)((*p)[0]); 01733 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 01734 c2 = (unsigned char)((*p)[2]); 01735 *p += 2; /* skip a total of 3 chars */ 01736 } else /* individual character */ 01737 c2 = c1; 01738 if (c1 < cmin) 01739 cmin = c1; 01740 for (; c1 <= c2; c1++) { 01741 uint32_t mask = 1 << (c1 % 32); 01742 if ( (chars[ c1 / 32 ] & mask) == 0) 01743 count += 0x100; 01744 chars[ c1 / 32 ] |= mask; 01745 } 01746 } 01747 (*p)++; 01748 return count == 0 ? 0x30000 : (count | cmin); 01749 }
static int ext_strncpy | ( | char * | dst, | |
const char * | src, | |||
int | len | |||
) | [static] |
copy a string skipping whitespace
Definition at line 6537 of file pbx.c.
Referenced by ast_add_extension2_lockopt().
06538 { 06539 int count = 0; 06540 06541 while (*src && (count < len - 1)) { 06542 switch (*src) { 06543 case ' ': 06544 /* otherwise exten => [a-b],1,... doesn't work */ 06545 /* case '-': */ 06546 /* Ignore */ 06547 break; 06548 default: 06549 *dst = *src; 06550 dst++; 06551 } 06552 src++; 06553 count++; 06554 } 06555 *dst = '\0'; 06556 06557 return count; 06558 }
static int extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 1961 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().
01962 { 01963 int i; 01964 static int prof_id = -2; /* marker for 'unallocated' id */ 01965 if (prof_id == -2) 01966 prof_id = ast_add_profile("ext_match", 0); 01967 ast_mark(prof_id, 1); 01968 i = _extension_match_core(pattern, data, mode); 01969 ast_mark(prof_id, 0); 01970 return i; 01971 }
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 4055 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().
04056 { 04057 struct ast_context *c = NULL; 04058 struct fake_context item; 04059 04060 ast_copy_string(item.name, context, sizeof(item.name)); 04061 04062 ast_rdlock_contexts(); 04063 c = ast_hashtab_lookup(contexts_table,&item); 04064 04065 #ifdef NOTNOW 04066 04067 while ( (c = ast_walk_contexts(c)) ) { 04068 if (!strcmp(ast_get_context_name(c), context)) 04069 return c; 04070 } 04071 #endif 04072 if (!c) 04073 ast_unlock_contexts(); 04074 04075 return c; 04076 }
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 2755 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), and ast_func_write().
02756 { 02757 char *args = strchr(function, '('); 02758 02759 if (!args) 02760 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n"); 02761 else { 02762 char *p; 02763 *args++ = '\0'; 02764 if ((p = strrchr(args, ')')) ) 02765 *p = '\0'; 02766 else 02767 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n"); 02768 } 02769 return args; 02770 }
static struct ast_exten * get_canmatch_exten | ( | struct match_char * | node | ) | [static] |
Definition at line 1155 of file pbx.c.
References ast_log(), ast_exten::exten, match_char::exten, LOG_NOTICE, and match_char::next_char.
01156 { 01157 /* find the exten at the end of the rope */ 01158 struct match_char *node2 = node; 01159 01160 for (node2 = node; node2; node2 = node2->next_char) { 01161 if (node2->exten) { 01162 #ifdef NEED_DEBUG_HERE 01163 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten); 01164 #endif 01165 return node2->exten; 01166 } 01167 } 01168 #ifdef NEED_DEBUG_HERE 01169 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x); 01170 #endif 01171 return 0; 01172 }
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 5950 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and s.
Referenced by ast_build_timing().
05951 { 05952 int s, e; /* start and ending position */ 05953 unsigned int mask = 0; 05954 05955 /* Check for whole range */ 05956 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 05957 s = 0; 05958 e = max - 1; 05959 } else { 05960 /* Get start and ending position */ 05961 char *c = strchr(src, '-'); 05962 if (c) 05963 *c++ = '\0'; 05964 /* Find the start */ 05965 s = lookup_name(src, names, max); 05966 if (!s) { 05967 ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src); 05968 return 0; 05969 } 05970 s--; 05971 if (c) { /* find end of range */ 05972 e = lookup_name(c, names, max); 05973 if (!e) { 05974 ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c); 05975 return 0; 05976 } 05977 e--; 05978 } else 05979 e = s; 05980 } 05981 /* Fill the mask. Remember that ranges are cyclic */ 05982 mask = 1 << e; /* initialize with last element */ 05983 while (s != e) { 05984 if (s >= max) { 05985 s = 0; 05986 mask |= (1 << s); 05987 } else { 05988 mask |= (1 << s); 05989 s++; 05990 } 05991 } 05992 return mask; 05993 }
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 5996 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_timing::minmask.
Referenced by ast_build_timing().
05997 { 05998 char *e; 05999 int x; 06000 int s1, s2; 06001 int e1, e2; 06002 /* int cth, ctm; */ 06003 06004 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 06005 memset(i->minmask, 0, sizeof(i->minmask)); 06006 06007 /* 2-minutes per bit, since the mask has only 32 bits :( */ 06008 /* Star is all times */ 06009 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 06010 for (x = 0; x < 24; x++) 06011 i->minmask[x] = 0x3fffffff; /* 30 bits */ 06012 return; 06013 } 06014 /* Otherwise expect a range */ 06015 e = strchr(times, '-'); 06016 if (!e) { 06017 ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n"); 06018 return; 06019 } 06020 *e++ = '\0'; 06021 /* XXX why skip non digits ? */ 06022 while (*e && !isdigit(*e)) 06023 e++; 06024 if (!*e) { 06025 ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n"); 06026 return; 06027 } 06028 if (sscanf(times, "%d:%d", &s1, &s2) != 2) { 06029 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times); 06030 return; 06031 } 06032 if (sscanf(e, "%d:%d", &e1, &e2) != 2) { 06033 ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e); 06034 return; 06035 } 06036 /* XXX this needs to be optimized */ 06037 #if 1 06038 s1 = s1 * 30 + s2/2; 06039 if ((s1 < 0) || (s1 >= 24*30)) { 06040 ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times); 06041 return; 06042 } 06043 e1 = e1 * 30 + e2/2; 06044 if ((e1 < 0) || (e1 >= 24*30)) { 06045 ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e); 06046 return; 06047 } 06048 /* Go through the time and enable each appropriate bit */ 06049 for (x=s1;x != e1;x = (x + 1) % (24 * 30)) { 06050 i->minmask[x/30] |= (1 << (x % 30)); 06051 } 06052 /* Do the last one */ 06053 i->minmask[x/30] |= (1 << (x % 30)); 06054 #else 06055 for (cth = 0; cth < 24; cth++) { 06056 /* Initialize masks to blank */ 06057 i->minmask[cth] = 0; 06058 for (ctm = 0; ctm < 30; ctm++) { 06059 if ( 06060 /* First hour with more than one hour */ 06061 (((cth == s1) && (ctm >= s2)) && 06062 ((cth < e1))) 06063 /* Only one hour */ 06064 || (((cth == s1) && (ctm >= s2)) && 06065 ((cth == e1) && (ctm <= e2))) 06066 /* In between first and last hours (more than 2 hours) */ 06067 || ((cth > s1) && 06068 (cth < e1)) 06069 /* Last hour with more than one hour */ 06070 || ((cth > s1) && 06071 ((cth == e1) && (ctm <= e2))) 06072 ) 06073 i->minmask[cth] |= (1 << (ctm / 2)); 06074 } 06075 } 06076 #endif 06077 /* All done */ 06078 return; 06079 }
static char* handle_set_chanvar | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5423 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.
05424 { 05425 struct ast_channel *chan; 05426 const char *chan_name, *var_name, *var_value; 05427 05428 switch (cmd) { 05429 case CLI_INIT: 05430 e->command = "core set chanvar"; 05431 e->usage = 05432 "Usage: core set chanvar <channel> <varname> <value>\n" 05433 " Set channel variable <varname> to <value>\n"; 05434 return NULL; 05435 case CLI_GENERATE: 05436 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 05437 } 05438 05439 if (a->argc != e->args + 3) 05440 return CLI_SHOWUSAGE; 05441 05442 chan_name = a->argv[e->args]; 05443 var_name = a->argv[e->args + 1]; 05444 var_value = a->argv[e->args + 2]; 05445 05446 if (!(chan = ast_get_channel_by_name_locked(chan_name))) { 05447 ast_cli(a->fd, "Channel '%s' not found\n", chan_name); 05448 return CLI_FAILURE; 05449 } 05450 05451 pbx_builtin_setvar_helper(chan, var_name, var_value); 05452 05453 ast_channel_unlock(chan); 05454 05455 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", 05456 var_name, var_value, chan_name); 05457 05458 return CLI_SUCCESS; 05459 }
static char* handle_set_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5461 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.
05462 { 05463 int oldval = 0; 05464 05465 switch (cmd) { 05466 case CLI_INIT: 05467 e->command = "dialplan set extenpatternmatchnew true"; 05468 e->usage = 05469 "Usage: dialplan set extenpatternmatchnew true|false\n" 05470 " Use the NEW extension pattern matching algorithm, true or false.\n"; 05471 return NULL; 05472 case CLI_GENERATE: 05473 return NULL; 05474 } 05475 05476 if (a->argc != 4) 05477 return CLI_SHOWUSAGE; 05478 05479 oldval = pbx_set_extenpatternmatchnew(1); 05480 05481 if (oldval) 05482 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n"); 05483 else 05484 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n"); 05485 05486 return CLI_SUCCESS; 05487 }
static char* handle_set_global | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5401 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.
05402 { 05403 switch (cmd) { 05404 case CLI_INIT: 05405 e->command = "core set global"; 05406 e->usage = 05407 "Usage: core set global <name> <value>\n" 05408 " Set global dialplan variable <name> to <value>\n"; 05409 return NULL; 05410 case CLI_GENERATE: 05411 return NULL; 05412 } 05413 05414 if (a->argc != e->args + 2) 05415 return CLI_SHOWUSAGE; 05416 05417 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]); 05418 ast_cli(a->fd, "\n -- Global variable %s set to %s\n", a->argv[3], a->argv[4]); 05419 05420 return CLI_SUCCESS; 05421 }
static char* handle_show_application | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4538 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.
04539 { 04540 struct ast_app *aa; 04541 int app, no_registered_app = 1; 04542 char *ret = NULL; 04543 int which = 0; 04544 int wordlen; 04545 04546 switch (cmd) { 04547 case CLI_INIT: 04548 e->command = "core show application"; 04549 e->usage = 04550 "Usage: core show application <application> [<application> [<application> [...]]]\n" 04551 " Describes a particular application.\n"; 04552 return NULL; 04553 case CLI_GENERATE: 04554 /* 04555 * There is a possibility to show informations about more than one 04556 * application at one time. You can type 'show application Dial Echo' and 04557 * you will see informations about these two applications ... 04558 */ 04559 wordlen = strlen(a->word); 04560 /* return the n-th [partial] matching entry */ 04561 AST_RWLIST_RDLOCK(&apps); 04562 AST_RWLIST_TRAVERSE(&apps, aa, list) { 04563 if (!strncasecmp(a->word, aa->name, wordlen) && ++which > a->n) { 04564 ret = ast_strdup(aa->name); 04565 break; 04566 } 04567 } 04568 AST_RWLIST_UNLOCK(&apps); 04569 04570 return ret; 04571 } 04572 04573 if (a->argc < 4) 04574 return CLI_SHOWUSAGE; 04575 04576 /* ... go through all applications ... */ 04577 AST_RWLIST_RDLOCK(&apps); 04578 AST_RWLIST_TRAVERSE(&apps, aa, list) { 04579 /* ... compare this application name with all arguments given 04580 * to 'show application' command ... */ 04581 for (app = 3; app < a->argc; app++) { 04582 if (!strcasecmp(aa->name, a->argv[app])) { 04583 /* Maximum number of characters added by terminal coloring is 22 */ 04584 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 04585 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 04586 int synopsis_size, description_size; 04587 04588 no_registered_app = 0; 04589 04590 if (aa->synopsis) 04591 synopsis_size = strlen(aa->synopsis) + 23; 04592 else 04593 synopsis_size = strlen("Not available") + 23; 04594 synopsis = alloca(synopsis_size); 04595 04596 if (aa->description) 04597 description_size = strlen(aa->description) + 23; 04598 else 04599 description_size = strlen("Not available") + 23; 04600 description = alloca(description_size); 04601 04602 if (synopsis && description) { 04603 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", aa->name); 04604 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 04605 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 04606 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 04607 term_color(synopsis, 04608 aa->synopsis ? aa->synopsis : "Not available", 04609 COLOR_CYAN, 0, synopsis_size); 04610 term_color(description, 04611 aa->description ? aa->description : "Not available", 04612 COLOR_CYAN, 0, description_size); 04613 04614 ast_cli(a->fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description); 04615 } else { 04616 /* ... one of our applications, show info ...*/ 04617 ast_cli(a->fd,"\n -= Info about application '%s' =- \n\n" 04618 "[Synopsis]\n %s\n\n" 04619 "[Description]\n%s\n", 04620 aa->name, 04621 aa->synopsis ? aa->synopsis : "Not available", 04622 aa->description ? aa->description : "Not available"); 04623 } 04624 } 04625 } 04626 } 04627 AST_RWLIST_UNLOCK(&apps); 04628 04629 /* we found at least one app? no? */ 04630 if (no_registered_app) { 04631 ast_cli(a->fd, "Your application(s) is (are) not registered\n"); 04632 return CLI_FAILURE; 04633 } 04634 04635 return CLI_SUCCESS; 04636 }
static char* handle_show_applications | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4792 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.
04793 { 04794 struct ast_app *aa; 04795 int like = 0, describing = 0; 04796 int total_match = 0; /* Number of matches in like clause */ 04797 int total_apps = 0; /* Number of apps registered */ 04798 static char* choices[] = { "like", "describing", NULL }; 04799 04800 switch (cmd) { 04801 case CLI_INIT: 04802 e->command = "core show applications [like|describing]"; 04803 e->usage = 04804 "Usage: core show applications [{like|describing} <text>]\n" 04805 " List applications which are currently available.\n" 04806 " If 'like', <text> will be a substring of the app name\n" 04807 " If 'describing', <text> will be a substring of the description\n"; 04808 return NULL; 04809 case CLI_GENERATE: 04810 return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n); 04811 } 04812 04813 AST_RWLIST_RDLOCK(&apps); 04814 04815 if (AST_RWLIST_EMPTY(&apps)) { 04816 ast_cli(a->fd, "There are no registered applications\n"); 04817 AST_RWLIST_UNLOCK(&apps); 04818 return CLI_SUCCESS; 04819 } 04820 04821 /* core list applications like <keyword> */ 04822 if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) { 04823 like = 1; 04824 } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) { 04825 describing = 1; 04826 } 04827 04828 /* core list applications describing <keyword1> [<keyword2>] [...] */ 04829 if ((!like) && (!describing)) { 04830 ast_cli(a->fd, " -= Registered Asterisk Applications =-\n"); 04831 } else { 04832 ast_cli(a->fd, " -= Matching Asterisk Applications =-\n"); 04833 } 04834 04835 AST_RWLIST_TRAVERSE(&apps, aa, list) { 04836 int printapp = 0; 04837 total_apps++; 04838 if (like) { 04839 if (strcasestr(aa->name, a->argv[4])) { 04840 printapp = 1; 04841 total_match++; 04842 } 04843 } else if (describing) { 04844 if (aa->description) { 04845 /* Match all words on command line */ 04846 int i; 04847 printapp = 1; 04848 for (i = 4; i < a->argc; i++) { 04849 if (!strcasestr(aa->description, a->argv[i])) { 04850 printapp = 0; 04851 } else { 04852 total_match++; 04853 } 04854 } 04855 } 04856 } else { 04857 printapp = 1; 04858 } 04859 04860 if (printapp) { 04861 ast_cli(a->fd," %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>"); 04862 } 04863 } 04864 if ((!like) && (!describing)) { 04865 ast_cli(a->fd, " -= %d Applications Registered =-\n",total_apps); 04866 } else { 04867 ast_cli(a->fd, " -= %d Applications Matching =-\n",total_match); 04868 } 04869 04870 AST_RWLIST_UNLOCK(&apps); 04871 04872 return CLI_SUCCESS; 04873 }
static char* handle_show_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5097 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(), 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.
05098 { 05099 char *exten = NULL, *context = NULL; 05100 /* Variables used for different counters */ 05101 struct dialplan_counters counters; 05102 const char *incstack[AST_PBX_MAX_STACK]; 05103 05104 switch (cmd) { 05105 case CLI_INIT: 05106 e->command = "dialplan show"; 05107 e->usage = 05108 "Usage: dialplan show [[exten@]context]\n" 05109 " Show dialplan\n"; 05110 return NULL; 05111 case CLI_GENERATE: 05112 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 05113 } 05114 05115 memset(&counters, 0, sizeof(counters)); 05116 05117 if (a->argc != 2 && a->argc != 3) 05118 return CLI_SHOWUSAGE; 05119 05120 /* we obtain [exten@]context? if yes, split them ... */ 05121 if (a->argc == 3) { 05122 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 05123 context = ast_strdupa(a->argv[2]); 05124 exten = strsep(&context, "@"); 05125 /* change empty strings to NULL */ 05126 if (ast_strlen_zero(exten)) 05127 exten = NULL; 05128 } else { /* no '@' char, only context given */ 05129 context = a->argv[2]; 05130 } 05131 if (ast_strlen_zero(context)) 05132 context = NULL; 05133 } 05134 /* else Show complete dial plan, context and exten are NULL */ 05135 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 05136 05137 /* check for input failure and throw some error messages */ 05138 if (context && !counters.context_existence) { 05139 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 05140 return CLI_FAILURE; 05141 } 05142 05143 if (exten && !counters.extension_existence) { 05144 if (context) 05145 ast_cli(a->fd, "There is no existence of %s@%s extension\n", 05146 exten, context); 05147 else 05148 ast_cli(a->fd, 05149 "There is no existence of '%s' extension in all contexts\n", 05150 exten); 05151 return CLI_FAILURE; 05152 } 05153 05154 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n", 05155 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 05156 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 05157 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 05158 05159 /* everything ok */ 05160 return CLI_SUCCESS; 05161 }
static char* handle_show_function | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2604 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.
02605 { 02606 struct ast_custom_function *acf; 02607 /* Maximum number of characters added by terminal coloring is 22 */ 02608 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40]; 02609 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL; 02610 char stxtitle[40], *syntax = NULL; 02611 int synopsis_size, description_size, syntax_size; 02612 char *ret = NULL; 02613 int which = 0; 02614 int wordlen; 02615 02616 switch (cmd) { 02617 case CLI_INIT: 02618 e->command = "core show function"; 02619 e->usage = 02620 "Usage: core show function <function>\n" 02621 " Describe a particular dialplan function.\n"; 02622 return NULL; 02623 case CLI_GENERATE: 02624 wordlen = strlen(a->word); 02625 /* case-insensitive for convenience in this 'complete' function */ 02626 AST_RWLIST_RDLOCK(&acf_root); 02627 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 02628 if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) { 02629 ret = ast_strdup(acf->name); 02630 break; 02631 } 02632 } 02633 AST_RWLIST_UNLOCK(&acf_root); 02634 02635 return ret; 02636 } 02637 02638 if (a->argc < 4) 02639 return CLI_SHOWUSAGE; 02640 02641 if (!(acf = ast_custom_function_find(a->argv[3]))) { 02642 ast_cli(a->fd, "No function by that name registered.\n"); 02643 return CLI_FAILURE; 02644 02645 } 02646 02647 if (acf->synopsis) 02648 synopsis_size = strlen(acf->synopsis) + 23; 02649 else 02650 synopsis_size = strlen("Not available") + 23; 02651 synopsis = alloca(synopsis_size); 02652 02653 if (acf->desc) 02654 description_size = strlen(acf->desc) + 23; 02655 else 02656 description_size = strlen("Not available") + 23; 02657 description = alloca(description_size); 02658 02659 if (acf->syntax) 02660 syntax_size = strlen(acf->syntax) + 23; 02661 else 02662 syntax_size = strlen("Not available") + 23; 02663 syntax = alloca(syntax_size); 02664 02665 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name); 02666 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22); 02667 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 02668 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 02669 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 02670 term_color(syntax, 02671 acf->syntax ? acf->syntax : "Not available", 02672 COLOR_CYAN, 0, syntax_size); 02673 term_color(synopsis, 02674 acf->synopsis ? acf->synopsis : "Not available", 02675 COLOR_CYAN, 0, synopsis_size); 02676 term_color(description, 02677 acf->desc ? acf->desc : "Not available", 02678 COLOR_CYAN, 0, description_size); 02679 02680 ast_cli(a->fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description); 02681 02682 return CLI_SUCCESS; 02683 }
static char* handle_show_functions | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2565 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.
02566 { 02567 struct ast_custom_function *acf; 02568 int count_acf = 0; 02569 int like = 0; 02570 02571 switch (cmd) { 02572 case CLI_INIT: 02573 e->command = "core show functions [like]"; 02574 e->usage = 02575 "Usage: core show functions [like <text>]\n" 02576 " List builtin functions, optionally only those matching a given string\n"; 02577 return NULL; 02578 case CLI_GENERATE: 02579 return NULL; 02580 } 02581 02582 if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) { 02583 like = 1; 02584 } else if (a->argc != 3) { 02585 return CLI_SHOWUSAGE; 02586 } 02587 02588 ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 02589 02590 AST_RWLIST_RDLOCK(&acf_root); 02591 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 02592 if (!like || strstr(acf->name, a->argv[4])) { 02593 count_acf++; 02594 ast_cli(a->fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis); 02595 } 02596 } 02597 AST_RWLIST_UNLOCK(&acf_root); 02598 02599 ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 02600 02601 return CLI_SUCCESS; 02602 }
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 5374 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.
05375 { 05376 int i = 0; 05377 struct ast_var_t *newvariable; 05378 05379 switch (cmd) { 05380 case CLI_INIT: 05381 e->command = "core show globals"; 05382 e->usage = 05383 "Usage: core show globals\n" 05384 " List current global dialplan variables and their values\n"; 05385 return NULL; 05386 case CLI_GENERATE: 05387 return NULL; 05388 } 05389 05390 ast_rwlock_rdlock(&globalslock); 05391 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 05392 i++; 05393 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 05394 } 05395 ast_rwlock_unlock(&globalslock); 05396 ast_cli(a->fd, "\n -- %d variables\n", i); 05397 05398 return CLI_SUCCESS; 05399 }
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 4709 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_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_hint::exten, ast_cli_args::fd, ast_hint::laststate, ast_cli_args::line, ast_cli_args::n, ast_state_cb::next, num, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
04710 { 04711 struct ast_hint *hint; 04712 int watchers; 04713 int num = 0, extenlen; 04714 struct ast_state_cb *watcher; 04715 04716 switch (cmd) { 04717 case CLI_INIT: 04718 e->command = "core show hint"; 04719 e->usage = 04720 "Usage: core show hint <exten>\n" 04721 " List registered hint\n"; 04722 return NULL; 04723 case CLI_GENERATE: 04724 return complete_core_show_hint(a->line, a->word, a->pos, a->n); 04725 } 04726 04727 if (a->argc < 4) 04728 return CLI_SHOWUSAGE; 04729 04730 AST_RWLIST_RDLOCK(&hints); 04731 if (AST_RWLIST_EMPTY(&hints)) { 04732 ast_cli(a->fd, "There are no registered dialplan hints\n"); 04733 AST_RWLIST_UNLOCK(&hints); 04734 return CLI_SUCCESS; 04735 } 04736 extenlen = strlen(a->argv[3]); 04737 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04738 if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) { 04739 watchers = 0; 04740 for (watcher = hint->callbacks; watcher; watcher = watcher->next) 04741 watchers++; 04742 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 04743 ast_get_extension_name(hint->exten), 04744 ast_get_context_name(ast_get_extension_context(hint->exten)), 04745 ast_get_extension_app(hint->exten), 04746 ast_extension_state2str(hint->laststate), watchers); 04747 num++; 04748 } 04749 } 04750 AST_RWLIST_UNLOCK(&hints); 04751 if (!num) 04752 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]); 04753 else 04754 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]); 04755 return CLI_SUCCESS; 04756 }
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 4639 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_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_hint::exten, ast_cli_args::fd, ast_hint::laststate, ast_state_cb::next, num, and ast_cli_entry::usage.
04640 { 04641 struct ast_hint *hint; 04642 int num = 0; 04643 int watchers; 04644 struct ast_state_cb *watcher; 04645 04646 switch (cmd) { 04647 case CLI_INIT: 04648 e->command = "core show hints"; 04649 e->usage = 04650 "Usage: core show hints\n" 04651 " List registered hints\n"; 04652 return NULL; 04653 case CLI_GENERATE: 04654 return NULL; 04655 } 04656 04657 AST_RWLIST_RDLOCK(&hints); 04658 if (AST_RWLIST_EMPTY(&hints)) { 04659 ast_cli(a->fd, "There are no registered dialplan hints\n"); 04660 AST_RWLIST_UNLOCK(&hints); 04661 return CLI_SUCCESS; 04662 } 04663 /* ... we have hints ... */ 04664 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 04665 AST_RWLIST_TRAVERSE(&hints, hint, list) { 04666 watchers = 0; 04667 for (watcher = hint->callbacks; watcher; watcher = watcher->next) 04668 watchers++; 04669 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 04670 ast_get_extension_name(hint->exten), 04671 ast_get_context_name(ast_get_extension_context(hint->exten)), 04672 ast_get_extension_app(hint->exten), 04673 ast_extension_state2str(hint->laststate), watchers); 04674 num++; 04675 } 04676 ast_cli(a->fd, "----------------\n"); 04677 ast_cli(a->fd, "- %d hints registered\n", num); 04678 AST_RWLIST_UNLOCK(&hints); 04679 return CLI_SUCCESS; 04680 }
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 4760 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.
04761 { 04762 struct ast_switch *sw; 04763 04764 switch (cmd) { 04765 case CLI_INIT: 04766 e->command = "core show switches"; 04767 e->usage = 04768 "Usage: core show switches\n" 04769 " List registered switches\n"; 04770 return NULL; 04771 case CLI_GENERATE: 04772 return NULL; 04773 } 04774 04775 AST_RWLIST_RDLOCK(&switches); 04776 04777 if (AST_RWLIST_EMPTY(&switches)) { 04778 AST_RWLIST_UNLOCK(&switches); 04779 ast_cli(a->fd, "There are no registered alternative switches\n"); 04780 return CLI_SUCCESS; 04781 } 04782 04783 ast_cli(a->fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 04784 AST_RWLIST_TRAVERSE(&switches, sw, list) 04785 ast_cli(a->fd, "%s: %s\n", sw->name, sw->description); 04786 04787 AST_RWLIST_UNLOCK(&switches); 04788 04789 return CLI_SUCCESS; 04790 }
static void handle_statechange | ( | const char * | device | ) | [static] |
Definition at line 3277 of file pbx.c.
References ast_copy_string(), ast_extension_state2(), ast_get_extension_app(), 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, ast_exten::exten, ast_hint::exten, ast_hint::laststate, ast_hint::list, ast_context::name, ast_state_cb::next, ast_exten::parent, parse(), statecbs, and strsep().
Referenced by device_state_thread().
03278 { 03279 struct ast_hint *hint; 03280 03281 ast_rdlock_contexts(); 03282 AST_RWLIST_RDLOCK(&hints); 03283 03284 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03285 struct ast_state_cb *cblist; 03286 char buf[AST_MAX_EXTENSION]; 03287 char *parse = buf; 03288 char *cur; 03289 int state; 03290 03291 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf)); 03292 while ( (cur = strsep(&parse, "&")) ) { 03293 if (!strcasecmp(cur, device)) 03294 break; 03295 } 03296 if (!cur) 03297 continue; 03298 03299 /* Get device state for this hint */ 03300 state = ast_extension_state2(hint->exten); 03301 03302 if ((state == -1) || (state == hint->laststate)) 03303 continue; 03304 03305 /* Device state changed since last check - notify the watchers */ 03306 03307 /* For general callbacks */ 03308 for (cblist = statecbs; cblist; cblist = cblist->next) 03309 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 03310 03311 /* For extension callbacks */ 03312 for (cblist = hint->callbacks; cblist; cblist = cblist->next) 03313 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 03314 03315 hint->laststate = state; /* record we saw the change */ 03316 } 03317 03318 AST_RWLIST_UNLOCK(&hints); 03319 ast_unlock_contexts(); 03320 }
static char* handle_unset_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5489 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.
05490 { 05491 int oldval = 0; 05492 05493 switch (cmd) { 05494 case CLI_INIT: 05495 e->command = "dialplan set extenpatternmatchnew false"; 05496 e->usage = 05497 "Usage: dialplan set extenpatternmatchnew true|false\n" 05498 " Use the NEW extension pattern matching algorithm, true or false.\n"; 05499 return NULL; 05500 case CLI_GENERATE: 05501 return NULL; 05502 } 05503 05504 if (a->argc != 4) 05505 return CLI_SHOWUSAGE; 05506 05507 oldval = pbx_set_extenpatternmatchnew(0); 05508 05509 if (!oldval) 05510 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n"); 05511 else 05512 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n"); 05513 05514 return CLI_SUCCESS; 05515 }
static int hashtab_compare_exten_labels | ( | const void * | ah_a, | |
const void * | ah_b | |||
) | [static] |
static int hashtab_compare_exten_numbers | ( | const void * | ah_a, | |
const void * | ah_b | |||
) | [static] |
Definition at line 392 of file pbx.c.
References ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
00393 { 00394 const struct ast_exten *ac = ah_a; 00395 const struct ast_exten *bc = ah_b; 00396 return ac->priority != bc->priority; 00397 }
static int hashtab_compare_extens | ( | const void * | ha_a, | |
const void * | ah_b | |||
) | [static] |
Definition at line 373 of file pbx.c.
References ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
00374 { 00375 const struct ast_exten *ac = ah_a; 00376 const struct ast_exten *bc = ah_b; 00377 int x = strcmp(ac->exten, bc->exten); 00378 if (x) { /* if exten names are diff, then return */ 00379 return x; 00380 } 00381 00382 /* but if they are the same, do the cidmatch values match? */ 00383 if (ac->matchcid && bc->matchcid) { 00384 return strcmp(ac->cidmatch,bc->cidmatch); 00385 } else if (!ac->matchcid && !bc->matchcid) { 00386 return 0; /* if there's no matchcid on either side, then this is a match */ 00387 } else { 00388 return 1; /* if there's matchcid on one but not the other, they are different */ 00389 } 00390 }
static unsigned int hashtab_hash_extens | ( | const void * | obj | ) | [static] |
Definition at line 412 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().
00413 { 00414 const struct ast_exten *ac = obj; 00415 unsigned int x = ast_hashtab_hash_string(ac->exten); 00416 unsigned int y = 0; 00417 if (ac->matchcid) 00418 y = ast_hashtab_hash_string(ac->cidmatch); 00419 return x+y; 00420 }
static unsigned int hashtab_hash_labels | ( | const void * | obj | ) | [static] |
Definition at line 428 of file pbx.c.
References ast_hashtab_hash_string(), ast_exten::label, and S_OR.
Referenced by ast_add_extension2_lockopt().
00429 { 00430 const struct ast_exten *ac = obj; 00431 return ast_hashtab_hash_string(S_OR(ac->label, "")); 00432 }
static unsigned int hashtab_hash_priority | ( | const void * | obj | ) | [static] |
Definition at line 422 of file pbx.c.
References ast_hashtab_hash_int(), and ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
00423 { 00424 const struct ast_exten *ac = obj; 00425 return ast_hashtab_hash_int(ac->priority); 00426 }
static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 994 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
Referenced by pbx_find_extension().
00995 { 00996 if (!i->hastime) 00997 return 1; 00998 00999 return ast_check_timing(&(i->timing)); 01000 }
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 3895 of file pbx.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), getloadavg(), LOG_WARNING, maxcalllock, ast_channel::name, option_maxcalls, option_maxload, and option_minmemfree.
Referenced by ast_pbx_run_args(), and ast_pbx_start().
03896 { 03897 int failed = 0; 03898 double curloadavg; 03899 #if defined(HAVE_SYSINFO) 03900 long curfreemem; 03901 struct sysinfo sys_info; 03902 #endif 03903 03904 ast_mutex_lock(&maxcalllock); 03905 if (option_maxcalls) { 03906 if (countcalls >= option_maxcalls) { 03907 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 03908 failed = -1; 03909 } 03910 } 03911 if (option_maxload) { 03912 getloadavg(&curloadavg, 1); 03913 if (curloadavg >= option_maxload) { 03914 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 03915 failed = -1; 03916 } 03917 } 03918 #if defined(HAVE_SYSINFO) 03919 if (option_minmemfree) { 03920 if (!sysinfo(&sys_info)) { 03921 /* make sure that the free system memory is above the configured low watermark 03922 * convert the amount of freeram from mem_units to MB */ 03923 curfreemem = sys_info.freeram / sys_info.mem_unit; 03924 curfreemem /= 1024*1024; 03925 if (curfreemem < option_minmemfree) { 03926 ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree); 03927 failed = -1; 03928 } 03929 } 03930 } 03931 #endif 03932 03933 if (!failed) { 03934 countcalls++; 03935 totalcalls++; 03936 } 03937 ast_mutex_unlock(&maxcalllock); 03938 03939 return failed; 03940 }
static void insert_in_next_chars_alt_char_list | ( | struct match_char ** | parent_ptr, | |
struct match_char * | node | |||
) | [static] |
Definition at line 1392 of file pbx.c.
References match_char::alt_char, and match_char::specificity.
Referenced by add_pattern_node().
01393 { 01394 struct match_char *curr, *lcurr; 01395 01396 /* insert node into the tree at "current", so the alt_char list from current is 01397 sorted in increasing value as you go to the leaves */ 01398 if (!(*parent_ptr)) { 01399 *parent_ptr = node; 01400 } else { 01401 if ((*parent_ptr)->specificity > node->specificity){ 01402 /* insert at head */ 01403 node->alt_char = (*parent_ptr); 01404 *parent_ptr = node; 01405 } else { 01406 lcurr = *parent_ptr; 01407 for (curr=(*parent_ptr)->alt_char; curr; curr = curr->alt_char) { 01408 if (curr->specificity > node->specificity) { 01409 node->alt_char = curr; 01410 lcurr->alt_char = node; 01411 break; 01412 } 01413 lcurr = curr; 01414 } 01415 if (!curr) 01416 { 01417 lcurr->alt_char = node; 01418 } 01419 } 01420 } 01421 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 8356 of file pbx.c.
References __ast_custom_function_register(), ast_cli_register_multiple(), ast_cond_init(), AST_EVENT_DEVICE_STATE, AST_EVENT_IE_END, ast_event_subscribe(), ast_log(), ast_manager_register2(), ast_mutex_init(), ast_pthread_create, ast_register_application2(), ast_verb, builtins, device_state, device_state_cb(), device_state_sub, device_state_thread(), EVENT_FLAG_CONFIG, EVENT_FLAG_REPORTING, exception_function, LOG_ERROR, manager_show_dialplan(), and pbx_cli.
Referenced by main().
08357 { 08358 int x; 08359 08360 /* Initialize the PBX */ 08361 ast_verb(1, "Asterisk PBX Core Initializing\n"); 08362 ast_verb(1, "Registering builtin applications:\n"); 08363 08364 ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry)); 08365 __ast_custom_function_register(&exception_function, NULL); 08366 08367 /* Register builtin applications */ 08368 for (x = 0; x < sizeof(builtins) / sizeof(struct pbx_builtin); x++) { 08369 ast_verb(1, "[%s]\n", builtins[x].name); 08370 if (ast_register_application2(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description, NULL)) { 08371 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 08372 return -1; 08373 } 08374 } 08375 08376 /* Register manager application */ 08377 ast_manager_register2("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan, "List dialplan", mandescr_show_dialplan); 08378 08379 ast_mutex_init(&device_state.lock); 08380 ast_cond_init(&device_state.cond, NULL); 08381 ast_pthread_create(&device_state.thread, NULL, device_state_thread, NULL); 08382 08383 if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, NULL, 08384 AST_EVENT_IE_END))) { 08385 return -1; 08386 } 08387 08388 return 0; 08389 }
void log_match_char_tree | ( | struct match_char * | node, | |
char * | prefix | |||
) |
Definition at line 1097 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().
01098 { 01099 char extenstr[40]; 01100 struct ast_str *my_prefix = ast_str_alloca(1024); 01101 01102 extenstr[0] = '\0'; 01103 01104 if (node && node->exten && node->exten) 01105 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01106 01107 if (strlen(node->x) > 1) { 01108 ast_debug(1, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', 01109 node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"", 01110 node->exten ? node->exten->exten : "", extenstr); 01111 } else { 01112 ast_debug(1, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', 01113 node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"", 01114 node->exten ? node->exten->exten : "", extenstr); 01115 } 01116 01117 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01118 01119 if (node->next_char) 01120 log_match_char_tree(node->next_char, my_prefix->str); 01121 01122 if (node->alt_char) 01123 log_match_char_tree(node->alt_char, prefix); 01124 }
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 5932 of file pbx.c.
Referenced by get_range().
05933 { 05934 int i; 05935 05936 if (names) { 05937 for (i = 0; names[i]; i++) { 05938 if (!strcasecmp(s, names[i])) 05939 return i+1; 05940 } 05941 } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) { 05942 return i; 05943 } 05944 return 0; /* error return */ 05945 }
static void manager_dpsendack | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Send ack once.
Definition at line 5164 of file pbx.c.
References astman_send_listack(), and s.
Referenced by manager_show_dialplan_helper().
05165 { 05166 astman_send_listack(s, m, "DialPlan list will follow", "start"); 05167 }
static int manager_show_dialplan | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager listing of dial plan.
Definition at line 5310 of file pbx.c.
References ast_strlen_zero(), astman_get_header(), astman_send_error(), context, EVENT_FLAG_CONFIG, exten, manager_event, manager_show_dialplan_helper(), and s.
Referenced by load_pbx().
05311 { 05312 const char *exten, *context; 05313 const char *id = astman_get_header(m, "ActionID"); 05314 char idtext[256]; 05315 int res; 05316 05317 /* Variables used for different counters */ 05318 struct dialplan_counters counters; 05319 05320 if (!ast_strlen_zero(id)) 05321 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 05322 else 05323 idtext[0] = '\0'; 05324 05325 memset(&counters, 0, sizeof(counters)); 05326 05327 exten = astman_get_header(m, "Extension"); 05328 context = astman_get_header(m, "Context"); 05329 05330 res = manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL); 05331 05332 if (context && !counters.context_existence) { 05333 char errorbuf[BUFSIZ]; 05334 05335 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context); 05336 astman_send_error(s, m, errorbuf); 05337 return 0; 05338 } 05339 if (exten && !counters.extension_existence) { 05340 char errorbuf[BUFSIZ]; 05341 05342 if (context) 05343 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context); 05344 else 05345 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten); 05346 astman_send_error(s, m, errorbuf); 05347 return 0; 05348 } 05349 05350 manager_event(EVENT_FLAG_CONFIG, "ShowDialPlanComplete", 05351 "EventList: Complete\r\n" 05352 "ListItems: %d\r\n" 05353 "ListExtensions: %d\r\n" 05354 "ListPriorities: %d\r\n" 05355 "ListContexts: %d\r\n" 05356 "%s" 05357 "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext); 05358 05359 /* everything ok */ 05360 return 0; 05361 }
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 5173 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().
05177 { 05178 struct ast_context *c; 05179 int res = 0, old_total_exten = dpc->total_exten; 05180 05181 if (ast_strlen_zero(exten)) 05182 exten = NULL; 05183 if (ast_strlen_zero(context)) 05184 context = NULL; 05185 05186 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten); 05187 05188 /* try to lock contexts */ 05189 if (ast_rdlock_contexts()) { 05190 astman_send_error(s, m, "Failed to lock contexts"); 05191 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n"); 05192 return -1; 05193 } 05194 05195 c = NULL; /* walk all contexts ... */ 05196 while ( (c = ast_walk_contexts(c)) ) { 05197 struct ast_exten *e; 05198 struct ast_include *i; 05199 struct ast_ignorepat *ip; 05200 05201 if (context && strcmp(ast_get_context_name(c), context) != 0) 05202 continue; /* not the name we want */ 05203 05204 dpc->context_existence = 1; 05205 05206 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c)); 05207 05208 if (ast_rdlock_context(c)) { /* failed to lock */ 05209 ast_debug(3, "manager_show_dialplan: Failed to lock context\n"); 05210 continue; 05211 } 05212 05213 /* XXX note- an empty context is not printed */ 05214 e = NULL; /* walk extensions in context */ 05215 while ( (e = ast_walk_context_extensions(c, e)) ) { 05216 struct ast_exten *p; 05217 05218 /* looking for extension? is this our extension? */ 05219 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) { 05220 /* not the one we are looking for, continue */ 05221 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e)); 05222 continue; 05223 } 05224 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e)); 05225 05226 dpc->extension_existence = 1; 05227 05228 /* may we print context info? */ 05229 dpc->total_context++; 05230 dpc->total_exten++; 05231 05232 p = NULL; /* walk next extension peers */ 05233 while ( (p = ast_walk_extension_priorities(e, p)) ) { 05234 int prio = ast_get_extension_priority(p); 05235 05236 dpc->total_prio++; 05237 if (!dpc->total_items++) 05238 manager_dpsendack(s, m); 05239 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 05240 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) ); 05241 05242 /* XXX maybe make this conditional, if p != e ? */ 05243 if (ast_get_extension_label(p)) 05244 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p)); 05245 05246 if (prio == PRIORITY_HINT) { 05247 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p)); 05248 } else { 05249 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)); 05250 } 05251 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e)); 05252 } 05253 } 05254 05255 i = NULL; /* walk included and write info ... */ 05256 while ( (i = ast_walk_context_includes(c, i)) ) { 05257 if (exten) { 05258 /* Check all includes for the requested extension */ 05259 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i); 05260 } else { 05261 if (!dpc->total_items++) 05262 manager_dpsendack(s, m); 05263 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 05264 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)); 05265 astman_append(s, "\r\n"); 05266 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i)); 05267 } 05268 } 05269 05270 ip = NULL; /* walk ignore patterns and write info ... */ 05271 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 05272 const char *ipname = ast_get_ignorepat_name(ip); 05273 char ignorepat[AST_MAX_EXTENSION]; 05274 05275 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 05276 if (!exten || ast_extension_match(ignorepat, exten)) { 05277 if (!dpc->total_items++) 05278 manager_dpsendack(s, m); 05279 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 05280 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip)); 05281 astman_append(s, "\r\n"); 05282 } 05283 } 05284 if (!rinclude) { 05285 struct ast_sw *sw = NULL; 05286 while ( (sw = ast_walk_context_switches(c, sw)) ) { 05287 if (!dpc->total_items++) 05288 manager_dpsendack(s, m); 05289 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 05290 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)); 05291 astman_append(s, "\r\n"); 05292 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw)); 05293 } 05294 } 05295 05296 ast_unlock_context(c); 05297 } 05298 ast_unlock_contexts(); 05299 05300 if (dpc->total_exten == old_total_exten) { 05301 ast_debug(3, "manager_show_dialplan: Found nothing new\n"); 05302 /* Nothing new under the sun */ 05303 return -1; 05304 } else { 05305 return res; 05306 } 05307 }
static int matchcid | ( | const char * | cidpattern, | |
const char * | callerid | |||
) | [static] |
Definition at line 2025 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
02026 { 02027 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 02028 failing to get a number should count as a match, otherwise not */ 02029 02030 if (ast_strlen_zero(callerid)) 02031 return ast_strlen_zero(cidpattern) ? 1 : 0; 02032 02033 return ast_extension_match(cidpattern, callerid); 02034 }
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 1227 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().
01228 { 01229 struct match_char *p; /* note minimal stack storage requirements */ 01230 struct ast_exten pattern = { .label = label }; 01231 #ifdef DEBUG_THIS 01232 if (tree) 01233 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action)); 01234 else 01235 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action)); 01236 #endif 01237 for (p=tree; p; p=p->alt_char) { 01238 if (p->x[0] == 'N') { 01239 if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) { 01240 #define NEW_MATCHER_CHK_MATCH \ 01241 if (p->exten && !(*(str+1))) { /* if a shorter pattern matches along the way, might as well report it */ \ 01242 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \ 01243 update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted, p); \ 01244 if (!p->deleted) { \ 01245 if (action == E_FINDLABEL) { \ 01246 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \ 01247 ast_debug(4, "Found label in preferred extension\n"); \ 01248 return; \ 01249 } \ 01250 } else { \ 01251 ast_debug(4,"returning an exact match-- first found-- %s\n", p->exten->exten); \ 01252 return; /* the first match, by definition, will be the best, because of the sorted tree */ \ 01253 } \ 01254 } \ 01255 } \ 01256 } 01257 01258 #define NEW_MATCHER_RECURSE \ 01259 if (p->next_char && ( *(str+1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \ 01260 || p->next_char->x[0] == '!')) { \ 01261 if (*(str+1) || p->next_char->x[0] == '!') { \ 01262 new_find_extension(str+1, score, p->next_char, length+1, spec+p->specificity, callerid, label, action); \ 01263 if (score->exten) { \ 01264 ast_debug(4,"returning an exact match-- %s\n", score->exten->exten); \ 01265 return; /* the first match is all we need */ \ 01266 } \ 01267 } else { \ 01268 new_find_extension("/", score, p->next_char, length+1, spec+p->specificity, callerid, label, action); \ 01269 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \ 01270 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \ 01271 "NULL"); \ 01272 return; /* the first match is all we need */ \ 01273 } \ 01274 } \ 01275 } else if (p->next_char && !*(str+1)) { \ 01276 score->canmatch = 1; \ 01277 score->canmatch_exten = get_canmatch_exten(p); \ 01278 if (action == E_CANMATCH || action == E_MATCHMORE) { \ 01279 ast_debug(4,"returning a canmatch/matchmore--- str=%s\n", str); \ 01280 return; \ 01281 } \ 01282 } 01283 01284 NEW_MATCHER_CHK_MATCH; 01285 NEW_MATCHER_RECURSE; 01286 } 01287 } else if (p->x[0] == 'Z') { 01288 if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) { 01289 NEW_MATCHER_CHK_MATCH; 01290 NEW_MATCHER_RECURSE; 01291 } 01292 } else if (p->x[0] == 'X') { 01293 if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) { 01294 NEW_MATCHER_CHK_MATCH; 01295 NEW_MATCHER_RECURSE; 01296 } 01297 } else if (p->x[0] == '.' && p->x[1] == 0) { 01298 /* how many chars will the . match against? */ 01299 int i = 0; 01300 const char *str2 = str; 01301 while (*str2 && *str2 != '/') { 01302 str2++; 01303 i++; 01304 } 01305 if (p->exten && *str2 != '/') { 01306 update_scoreboard(score, length+i, spec+(i*p->specificity), p->exten, '.', callerid, p->deleted, p); 01307 if (score->exten) { 01308 ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten); 01309 return; /* the first match is all we need */ 01310 } 01311 } 01312 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01313 new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid, label, action); 01314 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01315 ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL"); 01316 return; /* the first match is all we need */ 01317 } 01318 } 01319 } else if (p->x[0] == '!' && p->x[1] == 0) { 01320 /* how many chars will the . match against? */ 01321 int i = 1; 01322 const char *str2 = str; 01323 while (*str2 && *str2 != '/') { 01324 str2++; 01325 i++; 01326 } 01327 if (p->exten && *str2 != '/') { 01328 update_scoreboard(score, length+1, spec+(p->specificity*i), p->exten, '!', callerid, p->deleted, p); 01329 if (score->exten) { 01330 ast_debug(4,"return because scoreboard has a '!' match--- %s\n", score->exten->exten); 01331 return; /* the first match is all we need */ 01332 } 01333 } 01334 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01335 new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid, label, action); 01336 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01337 ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01338 return; /* the first match is all we need */ 01339 } 01340 } 01341 } else if (p->x[0] == '/' && p->x[1] == 0) { 01342 /* the pattern in the tree includes the cid match! */ 01343 if (p->next_char && callerid && *callerid) { 01344 new_find_extension(callerid, score, p->next_char, length+1, spec, callerid, label, action); 01345 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01346 ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01347 return; /* the first match is all we need */ 01348 } 01349 } 01350 } else if (strchr(p->x, *str)) { 01351 ast_debug(4, "Nothing strange about this match\n"); 01352 NEW_MATCHER_CHK_MATCH; 01353 NEW_MATCHER_RECURSE; 01354 } 01355 } 01356 ast_debug(4,"return at end of func\n"); 01357 }
static int parse_variable_name | ( | char * | var, | |
int * | offset, | |||
int * | length, | |||
int * | isfunc | |||
) | [static] |
extract offset:length from variable name.
Definition at line 2298 of file pbx.c.
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
02299 { 02300 int parens = 0; 02301 02302 *offset = 0; 02303 *length = INT_MAX; 02304 *isfunc = 0; 02305 for (; *var; var++) { 02306 if (*var == '(') { 02307 (*isfunc)++; 02308 parens++; 02309 } else if (*var == ')') { 02310 parens--; 02311 } else if (*var == ':' && parens == 0) { 02312 *var++ = '\0'; 02313 sscanf(var, "%d:%d", offset, length); 02314 return 1; /* offset:length valid */ 02315 } 02316 } 02317 return 0; 02318 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 8244 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().
08245 { 08246 struct ast_var_t *vardata; 08247 08248 ast_rwlock_wrlock(&globalslock); 08249 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 08250 ast_var_delete(vardata); 08251 ast_rwlock_unlock(&globalslock); 08252 }
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 8014 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_var_name(), ast_var_value(), chan, globals, and globalslock.
Referenced by _macro_exec(), _while_exec(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), array(), ast_bridge_call(), ast_call_forward(), ast_eivr_getvariable(), ast_feature_interpret(), ast_monitor_stop(), 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(), 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_call_full(), 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_suggested_sip_codec(), and update_bridge_vars().
08015 { 08016 struct ast_var_t *variables; 08017 const char *ret = NULL; 08018 int i; 08019 struct varshead *places[2] = { NULL, &globals }; 08020 08021 if (!name) 08022 return NULL; 08023 08024 if (chan) { 08025 ast_channel_lock(chan); 08026 places[0] = &chan->varshead; 08027 } 08028 08029 for (i = 0; i < 2; i++) { 08030 if (!places[i]) 08031 continue; 08032 if (places[i] == &globals) 08033 ast_rwlock_rdlock(&globalslock); 08034 AST_LIST_TRAVERSE(places[i], variables, entries) { 08035 if (!strcmp(name, ast_var_name(variables))) { 08036 ret = ast_var_value(variables); 08037 break; 08038 } 08039 } 08040 if (places[i] == &globals) 08041 ast_rwlock_unlock(&globalslock); 08042 if (ret) 08043 break; 08044 } 08045 08046 if (chan) 08047 ast_channel_unlock(chan); 08048 08049 return ret; 08050 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 8264 of file pbx.c.
References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), chan, LOG_WARNING, pbx_builtin_goto(), pbx_checkcondition(), and strsep().
08265 { 08266 char *condition, *branch1, *branch2, *branch; 08267 char *stringp; 08268 08269 if (ast_strlen_zero(data)) { 08270 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 08271 return 0; 08272 } 08273 08274 stringp = ast_strdupa(data); 08275 condition = strsep(&stringp,"?"); 08276 branch1 = strsep(&stringp,":"); 08277 branch2 = strsep(&stringp,""); 08278 branch = pbx_checkcondition(condition) ? branch1 : branch2; 08279 08280 if (ast_strlen_zero(branch)) { 08281 ast_debug(1, "Not taking any branch\n"); 08282 return 0; 08283 } 08284 08285 return pbx_builtin_goto(chan, branch); 08286 }
int pbx_builtin_importvar | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 8202 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.
08203 { 08204 char *name; 08205 char *value; 08206 char *channel; 08207 char tmp[VAR_BUF_SIZE]; 08208 static int deprecation_warning = 0; 08209 08210 if (ast_strlen_zero(data)) { 08211 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 08212 return 0; 08213 } 08214 tmp[0] = 0; 08215 if (!deprecation_warning) { 08216 ast_log(LOG_WARNING, "ImportVar is deprecated. Please use Set(varname=${IMPORT(channel,variable)}) instead.\n"); 08217 deprecation_warning = 1; 08218 } 08219 08220 value = ast_strdupa(data); 08221 name = strsep(&value,"="); 08222 channel = strsep(&value,","); 08223 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 08224 struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel); 08225 if (chan2) { 08226 char *s = alloca(strlen(value) + 4); 08227 if (s) { 08228 sprintf(s, "${%s}", value); 08229 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 08230 } 08231 ast_channel_unlock(chan2); 08232 } 08233 pbx_builtin_setvar_helper(chan, name, tmp); 08234 } 08235 08236 return(0); 08237 }
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 8052 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().
08053 { 08054 struct ast_var_t *newvariable; 08055 struct varshead *headp; 08056 08057 if (name[strlen(name)-1] == ')') { 08058 char *function = ast_strdupa(name); 08059 08060 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 08061 ast_func_write(chan, function, value); 08062 return; 08063 } 08064 08065 if (chan) { 08066 ast_channel_lock(chan); 08067 headp = &chan->varshead; 08068 } else { 08069 ast_rwlock_wrlock(&globalslock); 08070 headp = &globals; 08071 } 08072 08073 if (value) { 08074 if (headp == &globals) 08075 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 08076 newvariable = ast_var_assign(name, value); 08077 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 08078 } 08079 08080 if (chan) 08081 ast_channel_unlock(chan); 08082 else 08083 ast_rwlock_unlock(&globalslock); 08084 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
void * | vreason | |||
) |
Definition at line 2498 of file pbx.c.
References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_alloc(), ast_channel_datastore_find(), ast_channel_datastore_free(), ast_free, ast_string_field_init, ast_string_field_set, chan, context, 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().
02499 { 02500 const char *reason = vreason; 02501 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 02502 struct pbx_exception *exception = NULL; 02503 02504 if (!ds) { 02505 ds = ast_channel_datastore_alloc(&exception_store_info, NULL); 02506 if (!ds) 02507 return -1; 02508 exception = ast_calloc(1, sizeof(struct pbx_exception)); 02509 if (!exception) { 02510 ast_channel_datastore_free(ds); 02511 return -1; 02512 } 02513 if (ast_string_field_init(exception, 128)) { 02514 ast_free(exception); 02515 ast_channel_datastore_free(ds); 02516 return -1; 02517 } 02518 ds->data = exception; 02519 ast_channel_datastore_add(chan, ds); 02520 } else 02521 exception = ds->data; 02522 02523 ast_string_field_set(exception, reason, reason); 02524 ast_string_field_set(exception, context, chan->context); 02525 ast_string_field_set(exception, exten, chan->exten); 02526 exception->priority = chan->priority; 02527 set_ext_pri(chan, "e", 0); 02528 return 0; 02529 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 8325 of file pbx.c.
References ast_say_character_str(), chan, and ast_channel::language.
08326 { 08327 int res = 0; 08328 08329 if (data) 08330 res = ast_say_character_str(chan, data, "", chan->language); 08331 return res; 08332 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 8316 of file pbx.c.
References ast_say_digit_str(), chan, and ast_channel::language.
08317 { 08318 int res = 0; 08319 08320 if (data) 08321 res = ast_say_digit_str(chan, data, "", chan->language); 08322 return res; 08323 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 8288 of file pbx.c.
References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), chan, ast_channel::language, LOG_WARNING, and strsep().
08289 { 08290 char tmp[256]; 08291 char *number = tmp; 08292 char *options; 08293 08294 if (ast_strlen_zero(data)) { 08295 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 08296 return -1; 08297 } 08298 ast_copy_string(tmp, data, sizeof(tmp)); 08299 strsep(&number, ","); 08300 options = strsep(&number, ","); 08301 if (options) { 08302 if ( strcasecmp(options, "f") && strcasecmp(options, "m") && 08303 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 08304 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 08305 return -1; 08306 } 08307 } 08308 08309 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 08310 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 08311 } 08312 08313 return 0; 08314 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | , | |
void * | ||||
) | [static] |
Definition at line 8334 of file pbx.c.
References ast_say_phonetic_str(), chan, and ast_channel::language.
08335 { 08336 int res = 0; 08337 08338 if (data) 08339 res = ast_say_phonetic_str(chan, data, "", chan->language); 08340 return res; 08341 }
int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
struct ast_str ** | buf | |||
) |
Definition at line 7982 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_showchan(), and vars2manager().
07983 { 07984 struct ast_var_t *variables; 07985 const char *var, *val; 07986 int total = 0; 07987 07988 if (!chan) 07989 return 0; 07990 07991 (*buf)->used = 0; 07992 (*buf)->str[0] = '\0'; 07993 07994 ast_channel_lock(chan); 07995 07996 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 07997 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 07998 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 07999 ) { 08000 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 08001 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 08002 break; 08003 } else 08004 total++; 08005 } else 08006 break; 08007 } 08008 08009 ast_channel_unlock(chan); 08010 08011 return total; 08012 }
int pbx_builtin_setvar | ( | struct ast_channel * | , | |
void * | ||||
) |
Definition at line 8143 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().
08144 { 08145 char *name, *value, *mydata; 08146 08147 if (ast_compat_app_set) { 08148 return pbx_builtin_setvar_multiple(chan, data); 08149 } 08150 08151 if (ast_strlen_zero(data)) { 08152 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 08153 return 0; 08154 } 08155 08156 mydata = ast_strdupa(data); 08157 name = strsep(&mydata, "="); 08158 value = mydata; 08159 if (strchr(name, ' ')) 08160 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 08161 08162 pbx_builtin_setvar_helper(chan, name, value); 08163 return(0); 08164 }
void pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Definition at line 8086 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_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_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), 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_parking_thread(), 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(), 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(), 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(), privacy_exec(), process_ast_dsp(), read_exec(), readexten_exec(), readfile_exec(), record_exec(), return_exec(), rotate_file(), 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().
08087 { 08088 struct ast_var_t *newvariable; 08089 struct varshead *headp; 08090 const char *nametail = name; 08091 08092 if (name[strlen(name) - 1] == ')') { 08093 char *function = ast_strdupa(name); 08094 08095 ast_func_write(chan, function, value); 08096 return; 08097 } 08098 08099 if (chan) { 08100 ast_channel_lock(chan); 08101 headp = &chan->varshead; 08102 } else { 08103 ast_rwlock_wrlock(&globalslock); 08104 headp = &globals; 08105 } 08106 08107 /* For comparison purposes, we have to strip leading underscores */ 08108 if (*nametail == '_') { 08109 nametail++; 08110 if (*nametail == '_') 08111 nametail++; 08112 } 08113 08114 AST_LIST_TRAVERSE (headp, newvariable, entries) { 08115 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) { 08116 /* there is already such a variable, delete it */ 08117 AST_LIST_REMOVE(headp, newvariable, entries); 08118 ast_var_delete(newvariable); 08119 break; 08120 } 08121 } 08122 08123 if (value) { 08124 if (headp == &globals) 08125 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 08126 newvariable = ast_var_assign(name, value); 08127 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 08128 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 08129 "Channel: %s\r\n" 08130 "Variable: %s\r\n" 08131 "Value: %s\r\n" 08132 "Uniqueid: %s\r\n", 08133 chan ? chan->name : "none", name, value, 08134 chan ? chan->uniqueid : "none"); 08135 } 08136 08137 if (chan) 08138 ast_channel_unlock(chan); 08139 else 08140 ast_rwlock_unlock(&globalslock); 08141 }
int pbx_builtin_setvar_multiple | ( | struct ast_channel * | , | |
void * | ||||
) |
Definition at line 8166 of file pbx.c.
References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), chan, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::name, pbx_builtin_setvar_helper(), and ast_channel::priority.
Referenced by pbx_builtin_setvar(), queue_function_var(), and set_queue_variables().
08167 { 08168 char *data; 08169 int x; 08170 AST_DECLARE_APP_ARGS(args, 08171 AST_APP_ARG(pair)[24]; 08172 ); 08173 AST_DECLARE_APP_ARGS(pair, 08174 AST_APP_ARG(name); 08175 AST_APP_ARG(value); 08176 ); 08177 08178 if (ast_strlen_zero(vdata)) { 08179 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 08180 return 0; 08181 } 08182 08183 data = ast_strdupa(vdata); 08184 AST_STANDARD_APP_ARGS(args, data); 08185 08186 for (x = 0; x < args.argc; x++) { 08187 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 08188 if (pair.argc == 2) { 08189 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 08190 if (strchr(pair.name, ' ')) 08191 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); 08192 } else if (!chan) { 08193 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 08194 } else { 08195 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 08196 } 08197 } 08198 08199 return 0; 08200 }
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 8254 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().
08255 { 08256 if (ast_strlen_zero(condition)) /* NULL or empty strings are false */ 08257 return 0; 08258 else if (*condition >= '0' && *condition <= '9') /* Numbers are evaluated for truth */ 08259 return atoi(condition); 08260 else /* Strings are true */ 08261 return 1; 08262 }
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 925 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(), and tryexec_exec().
00928 { 00929 int res; 00930 struct ast_module_user *u = NULL; 00931 const char *saved_c_appl; 00932 const char *saved_c_data; 00933 00934 if (c->cdr && !ast_check_hangup(c)) 00935 ast_cdr_setapp(c->cdr, app->name, data); 00936 00937 /* save channel values */ 00938 saved_c_appl= c->appl; 00939 saved_c_data= c->data; 00940 00941 c->appl = app->name; 00942 c->data = data; 00943 if (app->module) 00944 u = __ast_module_user_add(app->module, c); 00945 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 00946 strchr(data, '|') && !strchr(data, ',')) { 00947 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 00948 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 00949 app->name, (char *) data); 00950 } 00951 res = app->execute(c, S_OR(data, "")); 00952 if (app->module && u) 00953 __ast_module_user_remove(app->module, u); 00954 /* restore channel values */ 00955 c->appl = saved_c_appl; 00956 c->data = saved_c_data; 00957 return res; 00958 }
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 3056 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().
03059 { 03060 struct ast_exten *e; 03061 struct ast_app *app; 03062 int res; 03063 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 03064 char passdata[EXT_DATA_SIZE]; 03065 03066 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 03067 03068 ast_rdlock_contexts(); 03069 if (found) 03070 *found = 0; 03071 03072 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 03073 if (e) { 03074 if (found) 03075 *found = 1; 03076 if (matching_action) { 03077 ast_unlock_contexts(); 03078 return -1; /* success, we found it */ 03079 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 03080 res = e->priority; 03081 ast_unlock_contexts(); 03082 return res; /* the priority we were looking for */ 03083 } else { /* spawn */ 03084 if (!e->cached_app) 03085 e->cached_app = pbx_findapp(e->app); 03086 app = e->cached_app; 03087 ast_unlock_contexts(); 03088 if (!app) { 03089 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 03090 return -1; 03091 } 03092 if (c->context != context) 03093 ast_copy_string(c->context, context, sizeof(c->context)); 03094 if (c->exten != exten) 03095 ast_copy_string(c->exten, exten, sizeof(c->exten)); 03096 c->priority = priority; 03097 pbx_substitute_variables(passdata, sizeof(passdata), c, e); 03098 #ifdef CHANNEL_TRACE 03099 ast_channel_trace_update(c); 03100 #endif 03101 ast_debug(1, "Launching '%s'\n", app->name); 03102 if (VERBOSITY_ATLEAST(3)) { 03103 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 03104 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 03105 exten, context, priority, 03106 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 03107 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 03108 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 03109 "in new stack"); 03110 } 03111 manager_event(EVENT_FLAG_DIALPLAN, "Newexten", 03112 "Channel: %s\r\n" 03113 "Context: %s\r\n" 03114 "Extension: %s\r\n" 03115 "Priority: %d\r\n" 03116 "Application: %s\r\n" 03117 "AppData: %s\r\n" 03118 "Uniqueid: %s\r\n", 03119 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 03120 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 03121 } 03122 } else if (q.swo) { /* not found here, but in another switch */ 03123 if (found) 03124 *found = 1; 03125 ast_unlock_contexts(); 03126 if (matching_action) { 03127 return -1; 03128 } else { 03129 if (!q.swo->exec) { 03130 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 03131 res = -1; 03132 } 03133 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 03134 } 03135 } else { /* not found anywhere, see what happened */ 03136 ast_unlock_contexts(); 03137 switch (q.status) { 03138 case STATUS_NO_CONTEXT: 03139 if (!matching_action && !combined_find_spawn) 03140 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context); 03141 break; 03142 case STATUS_NO_EXTENSION: 03143 if (!matching_action && !combined_find_spawn) 03144 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context); 03145 break; 03146 case STATUS_NO_PRIORITY: 03147 if (!matching_action && !combined_find_spawn) 03148 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context); 03149 break; 03150 case STATUS_NO_LABEL: 03151 if (context && !combined_find_spawn) 03152 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context); 03153 break; 03154 default: 03155 ast_debug(1, "Shouldn't happen!\n"); 03156 } 03157 03158 return (matching_action) ? 0 : -1; 03159 } 03160 }
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 2036 of file pbx.c.
References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_thread_get(), 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, 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, 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, switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().
Referenced by ast_hint_extension(), ast_merge_contexts_and_delete(), pbx_extension_helper(), pbx_find_extension(), and register_peer_exten().
02040 { 02041 int x, res; 02042 struct ast_context *tmp = NULL; 02043 struct ast_exten *e = NULL, *eroot = NULL; 02044 struct ast_include *i = NULL; 02045 struct ast_sw *sw = NULL; 02046 struct ast_exten pattern = {NULL, }; 02047 struct scoreboard score = {0, }; 02048 struct ast_str *tmpdata = NULL; 02049 02050 pattern.label = label; 02051 pattern.priority = priority; 02052 #ifdef NEED_DEBUG_HERE 02053 ast_log(LOG_NOTICE,"Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int)action); 02054 #endif 02055 /* Initialize status if appropriate */ 02056 if (q->stacklen == 0) { 02057 q->status = STATUS_NO_CONTEXT; 02058 q->swo = NULL; 02059 q->data = NULL; 02060 q->foundcontext = NULL; 02061 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02062 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02063 return NULL; 02064 } 02065 02066 /* Check first to see if we've already been checked */ 02067 for (x = 0; x < q->stacklen; x++) { 02068 if (!strcasecmp(q->incstack[x], context)) 02069 return NULL; 02070 } 02071 02072 if (bypass) /* bypass means we only look there */ 02073 tmp = bypass; 02074 else { /* look in contexts */ 02075 struct fake_context item; 02076 strncpy(item.name,context,256); 02077 tmp = ast_hashtab_lookup(contexts_table,&item); 02078 #ifdef NOTNOW 02079 tmp = NULL; 02080 while ((tmp = ast_walk_contexts(tmp)) ) { 02081 if (!strcmp(tmp->name, context)) 02082 break; 02083 } 02084 #endif 02085 if (!tmp) 02086 return NULL; 02087 02088 } 02089 02090 if (q->status < STATUS_NO_EXTENSION) 02091 q->status = STATUS_NO_EXTENSION; 02092 02093 /* Do a search for matching extension */ 02094 02095 eroot = NULL; 02096 score.total_specificity = 0; 02097 score.exten = 0; 02098 score.total_length = 0; 02099 if (!tmp->pattern_tree && tmp->root_table) 02100 { 02101 create_match_char_tree(tmp); 02102 #ifdef NEED_DEBUG 02103 ast_log(LOG_DEBUG,"Tree Created in context %s:\n", context); 02104 log_match_char_tree(tmp->pattern_tree," "); 02105 #endif 02106 } 02107 #ifdef NEED_DEBUG 02108 ast_log(LOG_NOTICE,"The Trie we are searching in:\n"); 02109 log_match_char_tree(tmp->pattern_tree, ":: "); 02110 #endif 02111 02112 if (extenpatternmatchnew) { 02113 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02114 eroot = score.exten; 02115 02116 if (score.last_char == '!' && action == E_MATCHMORE) { 02117 /* We match an extension ending in '!'. 02118 * The decision in this case is final and is NULL (no match). 02119 */ 02120 #ifdef NEED_DEBUG_HERE 02121 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02122 #endif 02123 return NULL; 02124 } 02125 02126 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02127 q->status = STATUS_SUCCESS; 02128 #ifdef NEED_DEBUG_HERE 02129 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02130 #endif 02131 return score.canmatch_exten; 02132 } 02133 02134 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02135 if (score.node) { 02136 struct ast_exten *z = trie_find_next_match(score.node); 02137 if (z) { 02138 #ifdef NEED_DEBUG_HERE 02139 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02140 #endif 02141 } else { 02142 if (score.canmatch_exten) { 02143 #ifdef NEED_DEBUG_HERE 02144 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02145 #endif 02146 return score.canmatch_exten; 02147 } else { 02148 #ifdef NEED_DEBUG_HERE 02149 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02150 #endif 02151 } 02152 } 02153 return z; 02154 } 02155 #ifdef NEED_DEBUG_HERE 02156 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02157 #endif 02158 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02159 } 02160 02161 if (eroot) { 02162 /* found entry, now look for the right priority */ 02163 if (q->status < STATUS_NO_PRIORITY) 02164 q->status = STATUS_NO_PRIORITY; 02165 e = NULL; 02166 if (action == E_FINDLABEL && label ) { 02167 if (q->status < STATUS_NO_LABEL) 02168 q->status = STATUS_NO_LABEL; 02169 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02170 } else { 02171 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02172 } 02173 if (e) { /* found a valid match */ 02174 q->status = STATUS_SUCCESS; 02175 q->foundcontext = context; 02176 #ifdef NEED_DEBUG_HERE 02177 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 02178 #endif 02179 return e; 02180 } 02181 } 02182 } else { /* the old/current default exten pattern match algorithm */ 02183 02184 /* scan the list trying to match extension and CID */ 02185 eroot = NULL; 02186 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 02187 int match = extension_match_core(eroot->exten, exten, action); 02188 /* 0 on fail, 1 on match, 2 on earlymatch */ 02189 02190 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 02191 continue; /* keep trying */ 02192 if (match == 2 && action == E_MATCHMORE) { 02193 /* We match an extension ending in '!'. 02194 * The decision in this case is final and is NULL (no match). 02195 */ 02196 return NULL; 02197 } 02198 /* found entry, now look for the right priority */ 02199 if (q->status < STATUS_NO_PRIORITY) 02200 q->status = STATUS_NO_PRIORITY; 02201 e = NULL; 02202 if (action == E_FINDLABEL && label ) { 02203 if (q->status < STATUS_NO_LABEL) 02204 q->status = STATUS_NO_LABEL; 02205 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02206 } else { 02207 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02208 } 02209 #ifdef NOTNOW 02210 while ( (e = ast_walk_extension_priorities(eroot, e)) ) { 02211 /* Match label or priority */ 02212 if (action == E_FINDLABEL) { 02213 if (q->status < STATUS_NO_LABEL) 02214 q->status = STATUS_NO_LABEL; 02215 if (label && e->label && !strcmp(label, e->label)) 02216 break; /* found it */ 02217 } else if (e->priority == priority) { 02218 break; /* found it */ 02219 } /* else keep searching */ 02220 } 02221 #endif 02222 if (e) { /* found a valid match */ 02223 q->status = STATUS_SUCCESS; 02224 q->foundcontext = context; 02225 return e; 02226 } 02227 } 02228 } 02229 02230 02231 /* Check alternative switches */ 02232 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 02233 struct ast_switch *asw = pbx_findswitch(sw->name); 02234 ast_switch_f *aswf = NULL; 02235 char *datap; 02236 02237 if (!asw) { 02238 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 02239 continue; 02240 } 02241 /* Substitute variables now */ 02242 02243 if (sw->eval) { 02244 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02245 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 02246 continue; 02247 } 02248 pbx_substitute_variables_helper(chan, sw->data, tmpdata->str, tmpdata->len); 02249 } 02250 02251 /* equivalent of extension_match_core() at the switch level */ 02252 if (action == E_CANMATCH) 02253 aswf = asw->canmatch; 02254 else if (action == E_MATCHMORE) 02255 aswf = asw->matchmore; 02256 else /* action == E_MATCH */ 02257 aswf = asw->exists; 02258 datap = sw->eval ? tmpdata->str : sw->data; 02259 if (!aswf) 02260 res = 0; 02261 else { 02262 if (chan) 02263 ast_autoservice_start(chan); 02264 res = aswf(chan, context, exten, priority, callerid, datap); 02265 if (chan) 02266 ast_autoservice_stop(chan); 02267 } 02268 if (res) { /* Got a match */ 02269 q->swo = asw; 02270 q->data = datap; 02271 q->foundcontext = context; 02272 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02273 return NULL; 02274 } 02275 } 02276 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 02277 /* Now try any includes we have in this context */ 02278 for (i = tmp->includes; i; i = i->next) { 02279 if (include_valid(i)) { 02280 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 02281 #ifdef NEED_DEBUG_HERE 02282 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 02283 #endif 02284 return e; 02285 } 02286 if (q->swo) 02287 return NULL; 02288 } 02289 } 02290 return NULL; 02291 }
struct ast_app* pbx_findapp | ( | const char * | app | ) |
Look up an application.
app | name of the app |
Definition at line 966 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(), and tryexec_exec().
00967 { 00968 struct ast_app *tmp; 00969 00970 AST_RWLIST_RDLOCK(&apps); 00971 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 00972 if (!strcasecmp(tmp->name, app)) 00973 break; 00974 } 00975 AST_RWLIST_UNLOCK(&apps); 00976 00977 return tmp; 00978 }
static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static] |
Definition at line 980 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().
00981 { 00982 struct ast_switch *asw; 00983 00984 AST_RWLIST_RDLOCK(&switches); 00985 AST_RWLIST_TRAVERSE(&switches, asw, list) { 00986 if (!strcasecmp(asw->name, sw)) 00987 break; 00988 } 00989 AST_RWLIST_UNLOCK(&switches); 00990 00991 return asw; 00992 }
static int pbx_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string, | |||
int | async | |||
) | [static] |
Definition at line 8635 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().
08636 { 08637 char *exten, *pri, *context; 08638 char *stringp; 08639 int ipri; 08640 int mode = 0; 08641 08642 if (ast_strlen_zero(goto_string)) { 08643 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n"); 08644 return -1; 08645 } 08646 stringp = ast_strdupa(goto_string); 08647 context = strsep(&stringp, ","); /* guaranteed non-null */ 08648 exten = strsep(&stringp, ","); 08649 pri = strsep(&stringp, ","); 08650 if (!exten) { /* Only a priority in this one */ 08651 pri = context; 08652 exten = NULL; 08653 context = NULL; 08654 } else if (!pri) { /* Only an extension and priority in this one */ 08655 pri = exten; 08656 exten = context; 08657 context = NULL; 08658 } 08659 if (*pri == '+') { 08660 mode = 1; 08661 pri++; 08662 } else if (*pri == '-') { 08663 mode = -1; 08664 pri++; 08665 } 08666 if (sscanf(pri, "%d", &ipri) != 1) { 08667 if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten, 08668 pri, chan->cid.cid_num)) < 1) { 08669 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 08670 return -1; 08671 } else 08672 mode = 0; 08673 } 08674 /* At this point we have a priority and maybe an extension and a context */ 08675 08676 if (mode) 08677 ipri = chan->priority + (ipri * mode); 08678 08679 if (async) 08680 ast_async_goto(chan, context, exten, ipri); 08681 else 08682 ast_explicit_goto(chan, context, exten, ipri); 08683 08684 return 0; 08685 08686 }
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 2373 of file pbx.c.
References ARRAY_LEN, ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_copy_string(), 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(), handle_getvariable(), lua_get_variable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
02374 { 02375 const char not_found = '\0'; 02376 char *tmpvar; 02377 const char *s; /* the result */ 02378 int offset, length; 02379 int i, need_substring; 02380 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 02381 02382 if (c) { 02383 ast_channel_lock(c); 02384 places[0] = &c->varshead; 02385 } 02386 /* 02387 * Make a copy of var because parse_variable_name() modifies the string. 02388 * Then if called directly, we might need to run substring() on the result; 02389 * remember this for later in 'need_substring', 'offset' and 'length' 02390 */ 02391 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 02392 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 02393 02394 /* 02395 * Look first into predefined variables, then into variable lists. 02396 * Variable 's' points to the result, according to the following rules: 02397 * s == ¬_found (set at the beginning) means that we did not find a 02398 * matching variable and need to look into more places. 02399 * If s != ¬_found, s is a valid result string as follows: 02400 * s = NULL if the variable does not have a value; 02401 * you typically do this when looking for an unset predefined variable. 02402 * s = workspace if the result has been assembled there; 02403 * typically done when the result is built e.g. with an snprintf(), 02404 * so we don't need to do an additional copy. 02405 * s != workspace in case we have a string, that needs to be copied 02406 * (the ast_copy_string is done once for all at the end). 02407 * Typically done when the result is already available in some string. 02408 */ 02409 s = ¬_found; /* default value */ 02410 if (c) { /* This group requires a valid channel */ 02411 /* Names with common parts are looked up a piece at a time using strncmp. */ 02412 if (!strncmp(var, "CALL", 4)) { 02413 if (!strncmp(var + 4, "ING", 3)) { 02414 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 02415 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres); 02416 s = workspace; 02417 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 02418 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2); 02419 s = workspace; 02420 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 02421 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton); 02422 s = workspace; 02423 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 02424 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns); 02425 s = workspace; 02426 } 02427 } 02428 } else if (!strcmp(var, "HINT")) { 02429 s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL; 02430 } else if (!strcmp(var, "HINTNAME")) { 02431 s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL; 02432 } else if (!strcmp(var, "EXTEN")) { 02433 s = c->exten; 02434 } else if (!strcmp(var, "CONTEXT")) { 02435 s = c->context; 02436 } else if (!strcmp(var, "PRIORITY")) { 02437 snprintf(workspace, workspacelen, "%d", c->priority); 02438 s = workspace; 02439 } else if (!strcmp(var, "CHANNEL")) { 02440 s = c->name; 02441 } else if (!strcmp(var, "UNIQUEID")) { 02442 s = c->uniqueid; 02443 } else if (!strcmp(var, "HANGUPCAUSE")) { 02444 snprintf(workspace, workspacelen, "%d", c->hangupcause); 02445 s = workspace; 02446 } 02447 } 02448 if (s == ¬_found) { /* look for more */ 02449 if (!strcmp(var, "EPOCH")) { 02450 snprintf(workspace, workspacelen, "%u",(int)time(NULL)); 02451 s = workspace; 02452 } else if (!strcmp(var, "SYSTEMNAME")) { 02453 s = ast_config_AST_SYSTEM_NAME; 02454 } 02455 } 02456 /* if not found, look into chanvars or global vars */ 02457 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 02458 struct ast_var_t *variables; 02459 if (!places[i]) 02460 continue; 02461 if (places[i] == &globals) 02462 ast_rwlock_rdlock(&globalslock); 02463 AST_LIST_TRAVERSE(places[i], variables, entries) { 02464 if (!strcasecmp(ast_var_name(variables), var)) { 02465 s = ast_var_value(variables); 02466 break; 02467 } 02468 } 02469 if (places[i] == &globals) 02470 ast_rwlock_unlock(&globalslock); 02471 } 02472 if (s == ¬_found || s == NULL) 02473 *ret = NULL; 02474 else { 02475 if (s != workspace) 02476 ast_copy_string(workspace, s, workspacelen); 02477 *ret = workspace; 02478 if (need_substring) 02479 *ret = substring(*ret, offset, length, workspace, workspacelen); 02480 } 02481 02482 if (c) 02483 ast_channel_unlock(c); 02484 }
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 4036 of file pbx.c.
Referenced by pbx_load_module().
04037 { 04038 int oldval = autofallthrough; 04039 autofallthrough = newval; 04040 return oldval; 04041 }
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 4043 of file pbx.c.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
04044 { 04045 int oldval = extenpatternmatchnew; 04046 extenpatternmatchnew = newval; 04047 return oldval; 04048 }
static void pbx_substitute_variables | ( | char * | passdata, | |
int | datalen, | |||
struct ast_channel * | c, | |||
struct ast_exten * | e | |||
) | [static] |
Definition at line 3021 of file pbx.c.
References ast_copy_string(), ast_exten::data, and pbx_substitute_variables_helper().
Referenced by pbx_extension_helper().
03022 { 03023 const char *tmp; 03024 03025 /* Nothing more to do */ 03026 if (!e->data) 03027 return; 03028 03029 /* No variables or expressions in e->data, so why scan it? */ 03030 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) { 03031 ast_copy_string(passdata, e->data, datalen); 03032 return; 03033 } 03034 03035 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1); 03036 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 3011 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(), config_curl(), custom_log(), cut_internal(), destroy_curl(), exec_exec(), function_eval(), function_fieldqty(), get_mapping_weight(), handle_cli_rpt_lstats(), 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(), rotate_file(), sendmail(), sendpage(), sqlite3_log(), store_curl(), substituted(), tryexec_exec(), and update_curl().
03012 { 03013 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count); 03014 }
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 2819 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().
02820 { 02821 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 02822 char *cp4; 02823 const char *tmp, *whereweare; 02824 int length, offset, offset2, isfunction; 02825 char *workspace = NULL; 02826 char *ltmp = NULL, *var = NULL; 02827 char *nextvar, *nextexp, *nextthing; 02828 char *vars, *vare; 02829 int pos, brackets, needsub, len; 02830 02831 *cp2 = 0; /* just in case nothing ends up there */ 02832 whereweare=tmp=cp1; 02833 while (!ast_strlen_zero(whereweare) && count) { 02834 /* Assume we're copying the whole remaining string */ 02835 pos = strlen(whereweare); 02836 nextvar = NULL; 02837 nextexp = NULL; 02838 nextthing = strchr(whereweare, '$'); 02839 if (nextthing) { 02840 switch (nextthing[1]) { 02841 case '{': 02842 nextvar = nextthing; 02843 pos = nextvar - whereweare; 02844 break; 02845 case '[': 02846 nextexp = nextthing; 02847 pos = nextexp - whereweare; 02848 break; 02849 default: 02850 pos = 1; 02851 } 02852 } 02853 02854 if (pos) { 02855 /* Can't copy more than 'count' bytes */ 02856 if (pos > count) 02857 pos = count; 02858 02859 /* Copy that many bytes */ 02860 memcpy(cp2, whereweare, pos); 02861 02862 count -= pos; 02863 cp2 += pos; 02864 whereweare += pos; 02865 *cp2 = 0; 02866 } 02867 02868 if (nextvar) { 02869 /* We have a variable. Find the start and end, and determine 02870 if we are going to have to recursively call ourselves on the 02871 contents */ 02872 vars = vare = nextvar + 2; 02873 brackets = 1; 02874 needsub = 0; 02875 02876 /* Find the end of it */ 02877 while (brackets && *vare) { 02878 if ((vare[0] == '$') && (vare[1] == '{')) { 02879 needsub++; 02880 } else if (vare[0] == '{') { 02881 brackets++; 02882 } else if (vare[0] == '}') { 02883 brackets--; 02884 } else if ((vare[0] == '$') && (vare[1] == '[')) 02885 needsub++; 02886 vare++; 02887 } 02888 if (brackets) 02889 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 02890 len = vare - vars - 1; 02891 02892 /* Skip totally over variable string */ 02893 whereweare += (len + 3); 02894 02895 if (!var) 02896 var = alloca(VAR_BUF_SIZE); 02897 02898 /* Store variable name (and truncate) */ 02899 ast_copy_string(var, vars, len + 1); 02900 02901 /* Substitute if necessary */ 02902 if (needsub) { 02903 if (!ltmp) 02904 ltmp = alloca(VAR_BUF_SIZE); 02905 02906 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 02907 vars = ltmp; 02908 } else { 02909 vars = var; 02910 } 02911 02912 if (!workspace) 02913 workspace = alloca(VAR_BUF_SIZE); 02914 02915 workspace[0] = '\0'; 02916 02917 parse_variable_name(vars, &offset, &offset2, &isfunction); 02918 if (isfunction) { 02919 /* Evaluate function */ 02920 if (c || !headp) 02921 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 02922 else { 02923 struct varshead old; 02924 struct ast_channel *c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars); 02925 if (c) { 02926 memcpy(&old, &c->varshead, sizeof(old)); 02927 memcpy(&c->varshead, headp, sizeof(c->varshead)); 02928 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 02929 /* Don't deallocate the varshead that was passed in */ 02930 memcpy(&c->varshead, &old, sizeof(c->varshead)); 02931 ast_channel_free(c); 02932 } else 02933 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 02934 } 02935 ast_debug(1, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 02936 } else { 02937 /* Retrieve variable value */ 02938 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 02939 } 02940 if (cp4) { 02941 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 02942 02943 length = strlen(cp4); 02944 if (length > count) 02945 length = count; 02946 memcpy(cp2, cp4, length); 02947 count -= length; 02948 cp2 += length; 02949 *cp2 = 0; 02950 } 02951 } else if (nextexp) { 02952 /* We have an expression. Find the start and end, and determine 02953 if we are going to have to recursively call ourselves on the 02954 contents */ 02955 vars = vare = nextexp + 2; 02956 brackets = 1; 02957 needsub = 0; 02958 02959 /* Find the end of it */ 02960 while (brackets && *vare) { 02961 if ((vare[0] == '$') && (vare[1] == '[')) { 02962 needsub++; 02963 brackets++; 02964 vare++; 02965 } else if (vare[0] == '[') { 02966 brackets++; 02967 } else if (vare[0] == ']') { 02968 brackets--; 02969 } else if ((vare[0] == '$') && (vare[1] == '{')) { 02970 needsub++; 02971 vare++; 02972 } 02973 vare++; 02974 } 02975 if (brackets) 02976 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 02977 len = vare - vars - 1; 02978 02979 /* Skip totally over expression */ 02980 whereweare += (len + 3); 02981 02982 if (!var) 02983 var = alloca(VAR_BUF_SIZE); 02984 02985 /* Store variable name (and truncate) */ 02986 ast_copy_string(var, vars, len + 1); 02987 02988 /* Substitute if necessary */ 02989 if (needsub) { 02990 if (!ltmp) 02991 ltmp = alloca(VAR_BUF_SIZE); 02992 02993 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); 02994 vars = ltmp; 02995 } else { 02996 vars = var; 02997 } 02998 02999 length = ast_expr(vars, cp2, count, c); 03000 03001 if (length) { 03002 ast_debug(1, "Expression result is '%s'\n", cp2); 03003 count -= length; 03004 cp2 += length; 03005 *cp2 = 0; 03006 } 03007 } 03008 } 03009 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 3016 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by ast_add_extension2_lockopt(), build_user_routes(), dundi_lookup_local(), loopback_subst(), phoneprov_callback(), and pp_each_user_exec().
03017 { 03018 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count); 03019 }
static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 3964 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
03965 { 03966 /* Oh joyeous kernel, we're a new thread, with nothing to do but 03967 answer this channel and get it going. 03968 */ 03969 /* NOTE: 03970 The launcher of this function _MUST_ increment 'countcalls' 03971 before invoking the function; it will be decremented when the 03972 PBX has finished running on the channel 03973 */ 03974 struct ast_channel *c = data; 03975 03976 __ast_pbx_run(c, NULL); 03977 decrease_call_count(); 03978 03979 pthread_exit(NULL); 03980 03981 return NULL; 03982 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 4918 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().
04919 { 04920 int prio = ast_get_extension_priority(e); 04921 if (prio == PRIORITY_HINT) { 04922 snprintf(buf, buflen, "hint: %s", 04923 ast_get_extension_app(e)); 04924 } else { 04925 snprintf(buf, buflen, "%d. %s(%s)", 04926 prio, ast_get_extension_app(e), 04927 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 04928 } 04929 }
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 3620 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().
03621 { 03622 ast_channel_lock(c); 03623 ast_copy_string(c->exten, exten, sizeof(c->exten)); 03624 c->priority = pri; 03625 ast_channel_unlock(c); 03626 }
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 4932 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, cli_match_char_tree(), dialplan_counters::context_existence, el, dialplan_counters::extension_existence, LOG_WARNING, ast_exten::matchcid, option_debug, ast_context::pattern_tree, print_ext(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.
Referenced by handle_show_dialplan().
04933 { 04934 struct ast_context *c = NULL; 04935 int res = 0, old_total_exten = dpc->total_exten; 04936 04937 ast_rdlock_contexts(); 04938 04939 /* walk all contexts ... */ 04940 while ( (c = ast_walk_contexts(c)) ) { 04941 struct ast_exten *e; 04942 struct ast_include *i; 04943 struct ast_ignorepat *ip; 04944 char buf[256], buf2[256]; 04945 int context_info_printed = 0; 04946 04947 if (context && strcmp(ast_get_context_name(c), context)) 04948 continue; /* skip this one, name doesn't match */ 04949 04950 dpc->context_existence = 1; 04951 04952 ast_rdlock_context(c); 04953 04954 /* are we looking for exten too? if yes, we print context 04955 * only if we find our extension. 04956 * Otherwise print context even if empty ? 04957 * XXX i am not sure how the rinclude is handled. 04958 * I think it ought to go inside. 04959 */ 04960 if (!exten) { 04961 dpc->total_context++; 04962 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 04963 ast_get_context_name(c), ast_get_context_registrar(c)); 04964 context_info_printed = 1; 04965 } 04966 04967 /* walk extensions ... */ 04968 e = NULL; 04969 while ( (e = ast_walk_context_extensions(c, e)) ) { 04970 struct ast_exten *p; 04971 04972 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 04973 continue; /* skip, extension match failed */ 04974 04975 dpc->extension_existence = 1; 04976 04977 /* may we print context info? */ 04978 if (!context_info_printed) { 04979 dpc->total_context++; 04980 if (rinclude) { /* TODO Print more info about rinclude */ 04981 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 04982 ast_get_context_name(c), ast_get_context_registrar(c)); 04983 } else { 04984 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 04985 ast_get_context_name(c), ast_get_context_registrar(c)); 04986 } 04987 context_info_printed = 1; 04988 } 04989 dpc->total_prio++; 04990 04991 /* write extension name and first peer */ 04992 if (e->matchcid) 04993 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch); 04994 else 04995 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 04996 04997 print_ext(e, buf2, sizeof(buf2)); 04998 04999 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 05000 ast_get_extension_registrar(e)); 05001 05002 dpc->total_exten++; 05003 /* walk next extension peers */ 05004 p = e; /* skip the first one, we already got it */ 05005 while ( (p = ast_walk_extension_priorities(e, p)) ) { 05006 const char *el = ast_get_extension_label(p); 05007 dpc->total_prio++; 05008 if (el) 05009 snprintf(buf, sizeof(buf), " [%s]", el); 05010 else 05011 buf[0] = '\0'; 05012 print_ext(p, buf2, sizeof(buf2)); 05013 05014 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 05015 ast_get_extension_registrar(p)); 05016 } 05017 } 05018 05019 /* walk included and write info ... */ 05020 i = NULL; 05021 while ( (i = ast_walk_context_includes(c, i)) ) { 05022 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 05023 if (exten) { 05024 /* Check all includes for the requested extension */ 05025 if (includecount >= AST_PBX_MAX_STACK) { 05026 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n"); 05027 } else { 05028 int dupe = 0; 05029 int x; 05030 for (x = 0; x < includecount; x++) { 05031 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 05032 dupe++; 05033 break; 05034 } 05035 } 05036 if (!dupe) { 05037 includes[includecount] = ast_get_include_name(i); 05038 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 05039 } else { 05040 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 05041 } 05042 } 05043 } else { 05044 ast_cli(fd, " Include => %-45s [%s]\n", 05045 buf, ast_get_include_registrar(i)); 05046 } 05047 } 05048 05049 /* walk ignore patterns and write info ... */ 05050 ip = NULL; 05051 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 05052 const char *ipname = ast_get_ignorepat_name(ip); 05053 char ignorepat[AST_MAX_EXTENSION]; 05054 snprintf(buf, sizeof(buf), "'%s'", ipname); 05055 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 05056 if (!exten || ast_extension_match(ignorepat, exten)) { 05057 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 05058 buf, ast_get_ignorepat_registrar(ip)); 05059 } 05060 } 05061 if (!rinclude) { 05062 struct ast_sw *sw = NULL; 05063 while ( (sw = ast_walk_context_switches(c, sw)) ) { 05064 snprintf(buf, sizeof(buf), "'%s/%s'", 05065 ast_get_switch_name(sw), 05066 ast_get_switch_data(sw)); 05067 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 05068 buf, ast_get_switch_registrar(sw)); 05069 } 05070 } 05071 05072 if (option_debug && c->pattern_tree) 05073 { 05074 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n"); 05075 05076 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n"); 05077 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n"); 05078 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n"); 05079 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n"); 05080 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n"); 05081 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n"); 05082 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n"); 05083 cli_match_char_tree(c->pattern_tree, " ", fd); 05084 } 05085 05086 ast_unlock_context(c); 05087 05088 /* if we print something in context, make an empty line */ 05089 if (context_info_printed) 05090 ast_cli(fd, "\n"); 05091 } 05092 ast_unlock_contexts(); 05093 05094 return (dpc->total_exten == old_total_exten) ? -1 : res; 05095 }
static int statechange_queue | ( | const char * | dev | ) | [static] |
Definition at line 3322 of file pbx.c.
References ast_calloc, ast_cond_signal(), AST_LIST_INSERT_TAIL, ast_mutex_lock(), ast_mutex_unlock(), device_state, and statechange::entry.
Referenced by device_state_cb().
03323 { 03324 struct statechange *sc; 03325 03326 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(dev) + 1))) 03327 return 0; 03328 03329 strcpy(sc->dev, dev); 03330 03331 ast_mutex_lock(&device_state.lock); 03332 AST_LIST_INSERT_TAIL(&device_state.state_change_q, sc, entry); 03333 ast_cond_signal(&device_state.cond); 03334 ast_mutex_unlock(&device_state.lock); 03335 03336 return 0; 03337 }
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 2331 of file pbx.c.
References ast_copy_string().
Referenced by pbx_retrieve_variable(), and pbx_substitute_variables_helper_full().
02332 { 02333 char *ret = workspace; 02334 int lr; /* length of the input string after the copy */ 02335 02336 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 02337 02338 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 02339 02340 /* Quick check if no need to do anything */ 02341 if (offset == 0 && length >= lr) /* take the whole string */ 02342 return ret; 02343 02344 if (offset < 0) { /* translate negative offset into positive ones */ 02345 offset = lr + offset; 02346 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 02347 offset = 0; 02348 } 02349 02350 /* too large offset result in empty string so we know what to return */ 02351 if (offset >= lr) 02352 return ret + lr; /* the final '\0' */ 02353 02354 ret += offset; /* move to the start position */ 02355 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 02356 ret[length] = '\0'; 02357 else if (length < 0) { 02358 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 02359 ret[lr + length - offset] = '\0'; 02360 else 02361 ret[0] = '\0'; 02362 } 02363 02364 return ret; 02365 }
static struct ast_exten* trie_find_next_match | ( | struct match_char * | node | ) | [static] |
Definition at line 1174 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().
01175 { 01176 struct match_char *m3; 01177 struct match_char *m4; 01178 struct ast_exten *e3; 01179 01180 if (node && node->x[0] == '.' && !node->x[1]) /* dot and ! will ALWAYS be next match in a matchmore */ 01181 return node->exten; 01182 01183 if (node && node->x[0] == '!' && !node->x[1]) 01184 return node->exten; 01185 01186 if (!node || !node->next_char) 01187 return NULL; 01188 01189 m3 = node->next_char; 01190 01191 if (m3->exten) 01192 return m3->exten; 01193 for(m4=m3->alt_char; m4; m4 = m4->alt_char) { 01194 if (m4->exten) 01195 return m4->exten; 01196 } 01197 for(m4=m3; m4; m4 = m4->alt_char) { 01198 e3 = trie_find_next_match(m3); 01199 if (e3) 01200 return e3; 01201 } 01202 return NULL; 01203 }
static void unreference_cached_app | ( | struct ast_app * | app | ) | [static] |
Definition at line 5536 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().
05537 { 05538 struct ast_context *context = NULL; 05539 struct ast_exten *eroot = NULL, *e = NULL; 05540 05541 ast_rdlock_contexts(); 05542 while ((context = ast_walk_contexts(context))) { 05543 while ((eroot = ast_walk_context_extensions(context, eroot))) { 05544 while ((e = ast_walk_extension_priorities(eroot, e))) { 05545 if (e->cached_app == app) 05546 e->cached_app = NULL; 05547 } 05548 } 05549 } 05550 ast_unlock_contexts(); 05551 05552 return; 05553 }
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 1081 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().
01082 { 01083 /* if this extension is marked as deleted, then skip this -- if it never shows 01084 on the scoreboard, it will never be found, nor will halt the traversal. */ 01085 if (deleted) 01086 return; 01087 board->total_specificity = spec; 01088 board->total_length = length; 01089 board->exten = exten; 01090 board->last_char = last; 01091 board->node = node; 01092 #ifdef NEED_DEBUG_HERE 01093 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec); 01094 #endif 01095 }
static void wait_for_hangup | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 7544 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().
07545 { 07546 int res; 07547 struct ast_frame *f; 07548 double waitsec; 07549 int waittime; 07550 07551 if (ast_strlen_zero(data) || (sscanf(data, "%lg", &waitsec) != 1) || (waitsec < 0)) 07552 waitsec = -1; 07553 if (waitsec > -1) { 07554 waittime = waitsec * 1000.0; 07555 ast_safe_sleep(chan, waittime); 07556 } else do { 07557 res = ast_waitfor(chan, -1); 07558 if (res < 0) 07559 return; 07560 f = ast_read(chan); 07561 if (f) 07562 ast_frfree(f); 07563 } while(f); 07564 }
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] |
ast_rwlock_t conlock = PTHREAD_RWLOCK_INITIALIZER [static] |
Lock for the ast_context list
Definition at line 727 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 724 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 725 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_locked(), and pbx_find_extension().
int countcalls [static] |
char* days[] [static] |
struct { ... } device_state [static] |
Data used by the device state thread.
Referenced by device_state_thread(), load_module(), load_pbx(), statechange_queue(), and unload_module().
struct ast_event_sub* device_state_sub [static] |
Subscription for device state change events.
Definition at line 442 of file pbx.c.
Referenced by load_module(), load_pbx(), and unload_module().
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 2493 of file pbx.c.
Referenced by acf_exception_read(), and pbx_builtin_raise_exception().
int extenpatternmatchnew = 0 [static] |
struct cfextension_states extension_states[] [static] |
Referenced by ast_extension_state2str().
struct statechange* first |
Definition at line 436 of file pbx.c.
Referenced by ast_add_extension2_lockopt(), 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 435 of file pbx.c.
Referenced by ast_add_extension2_lockopt(), handle_show_globals(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), pbx_builtin_setvar_helper(), and pbx_retrieve_variable().
struct statechange* last |
char mandescr_show_dialplan[] [static] |
ast_mutex_t maxcalllock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 444 of file pbx.c.
Referenced by decrease_call_count(), and increase_call_count().
char* months[] [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] |
struct { ... } state_change_q |
Queue of state changes
struct ast_state_cb* statecbs |
Definition at line 741 of file pbx.c.
Referenced by ast_extension_state_add(), ast_extension_state_del(), and handle_statechange().
unsigned int stop |
Set to 1 to stop the thread
Definition at line 276 of file pbx.c.
Referenced by controlplayback_exec(), handle_controlstreamfile(), and queue_exec().
struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT, .key_init = __init_switch_data , .custom_init = NULL , } [static] |
pthread_t thread |
The device state monitoring thread
Definition at line 278 of file pbx.c.
Referenced by __schedule_action(), __unload_module(), ast_bridge_call_thread_launch(), find_idle_thread(), handle_cli_iax2_show_threads(), handle_deferred_full_frames(), iax2_process_thread(), iax2_process_thread_cleanup(), insert_idle_thread(), launch_monitor_thread(), load_module(), socket_process(), socket_read(), start_network_thread(), and unload_module().
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 },} [static] |