#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/cel.h"
#include "asterisk/config.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/ast_expr.h"
#include "asterisk/linkedlists.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/devicestate.h"
#include "asterisk/event.h"
#include "asterisk/hashtab.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/xmldoc.h"
#include "asterisk/astobj2.h"
Go to the source code of this file.
Data Structures | |
struct | acf_root |
struct | app_tmp |
struct | apps |
struct | ast_app |
ast_app: A registered application More... | |
struct | ast_context |
ast_context: An extension context More... | |
struct | ast_exten |
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own linked list of extensions - one item per priority. More... | |
struct | ast_hint |
Structure for dial plan hints. More... | |
struct | ast_ignorepat |
ast_ignorepat: Ignore patterns in dial plan More... | |
struct | ast_include |
ast_include: include= support in extensions.conf More... | |
struct | ast_state_cb |
ast_state_cb: An extension state notify register item More... | |
struct | ast_sw |
ast_sw: Switch statement in extensions.conf More... | |
struct | async_stat |
struct | cfextension_states |
struct | dialplan_counters |
Counters for the show dialplan manager command. More... | |
struct | fake_context |
struct | match_char |
match_char: forms a syntax tree for quick matching of extension patterns More... | |
struct | pbx_builtin |
Declaration of builtin applications. More... | |
struct | pbx_exception |
struct | scoreboard |
struct | statechange |
struct | store_hint |
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_extensionstate_buf (void) |
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 int | acf_retrieve_docs (struct ast_custom_function *acf) |
static struct match_char * | add_exten_to_pattern_tree (struct ast_context *con, struct ast_exten *e1, int findonly) |
static 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 is_pattern) |
int | ast_active_calls (void) |
Retrieve the number of active calls. | |
int | ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
Add and extension to an extension context. | |
int | ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
Add an extension to an extension context, this time with an ast_context *. | |
static int | ast_add_extension2_lockopt (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, int lockconts, int lockhints) |
Does all the work of ast_add_extension2, but adds two args, to determine if context and hint locking should be done. In merge_and_delete, we need to do this without locking, as the locks are already held. | |
static int | ast_add_extension_nolock (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
static int | ast_add_hint (struct ast_exten *e) |
Add hint to hint list, check initial extension state. | |
int | ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
Set the channel to next execute the specified dialplan location. | |
int | ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority) |
Set the channel to next execute the specified dialplan location. | |
int | ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string) |
int | ast_build_timing (struct ast_timing *i, const char *info_in) |
Construct a timing bitmap, for use in time-based conditionals. | |
int | ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Looks for a valid matching extension. | |
static int | ast_change_hint (struct ast_exten *oe, struct ast_exten *ne) |
Change hint for an extension. | |
int | ast_check_timing (const struct ast_timing *i) |
Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified. | |
int | ast_check_timing2 (const struct ast_timing *i, const struct timeval tv) |
Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified. | |
char * | ast_complete_applications (const char *line, const char *word, int state) |
Command completion for the list of installed applications. | |
int | ast_context_add_ignorepat (const char *context, const char *value, const char *registrar) |
Add an ignorepat. | |
int | ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar) |
int | ast_context_add_include (const char *context, const char *include, const char *registrar) |
Add a context include. | |
int | ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar) |
Add a context include. | |
int | ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar) |
Add a switch. | |
int | ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar) |
Adds a switch (first param is a ast_context). | |
void | ast_context_destroy (struct ast_context *con, const char *registrar) |
Destroy a context (matches the specified context (or ANY context if NULL). | |
ast_context * | ast_context_find (const char *name) |
Find a context. | |
ast_context * | ast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar) |
Register a new context or find an existing one. | |
int | ast_context_lockmacro (const char *context) |
locks the macrolock in the given given context | |
int | ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar) |
Simply remove extension from context. | |
int | ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked) |
This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return. | |
int | ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar) |
int | ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked) |
int | ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
int | ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
int | ast_context_remove_include (const char *context, const char *include, const char *registrar) |
Remove a context include. | |
int | ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar) |
Removes an include by an ast_context structure. | |
int | ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar) |
Remove a switch. | |
int | ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar) |
This function locks given context, removes switch, unlock context and return. | |
int | ast_context_unlockmacro (const char *context) |
Unlocks the macrolock in the given context. | |
int | ast_context_verify_includes (struct ast_context *con) |
Verifies includes in an ast_contect structure. | |
ast_custom_function * | ast_custom_function_find (const char *name) |
int | ast_custom_function_unregister (struct ast_custom_function *acf) |
Unregister a custom function. | |
int | ast_destroy_timing (struct ast_timing *i) |
Deallocates memory structures associated with a timing bitmap. | |
enum ast_extension_states | ast_devstate_to_extenstate (enum ast_device_state devstate) |
Map devstate to an extension state. | |
int | ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Determine whether an extension exists. | |
int | ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_extension_close (const char *pattern, const char *data, int needmore) |
int | ast_extension_cmp (const char *a, const char *b) |
Determine if one extension should match before another. | |
int | ast_extension_match (const char *pattern, const char *data) |
Determine if a given extension matches a given pattern (in NXX format). | |
int | ast_extension_state (struct ast_channel *c, const char *context, const char *exten) |
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_read2 (struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen) |
executes a read operation on a function | |
int | ast_func_write (struct ast_channel *chan, const char *function, const char *value) |
executes a write operation on a function | |
const char * | ast_get_context_name (struct ast_context *con) |
const char * | ast_get_context_registrar (struct ast_context *c) |
const char * | ast_get_extension_app (struct ast_exten *e) |
void * | ast_get_extension_app_data (struct ast_exten *e) |
const char * | ast_get_extension_cidmatch (struct ast_exten *e) |
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) |
hashtable functions for contexts | |
unsigned int | ast_hashtab_hash_contexts (const void *obj) |
static struct ast_exten * | ast_hint_extension (struct ast_channel *c, const char *context, const char *exten) |
static struct ast_exten * | ast_hint_extension_nolock (struct ast_channel *c, const char *context, const char *exten) |
Find hint for given extension in context. | |
int | ast_ignore_pattern (const char *context, const char *pattern) |
Checks to see if a number should be ignored. | |
int | ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Looks to see if adding anything to this extension might match something. (exists ^ canmatch). | |
void | ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar) |
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added. | |
int | ast_parseable_goto (struct ast_channel *chan, const char *goto_string) |
int | ast_pbx_init (void) |
int | ast_pbx_outgoing_app (const char *type, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) |
static int | ast_pbx_outgoing_cdr_failed (void) |
Function to post an empty cdr after a spool call fails. | |
int | ast_pbx_outgoing_exten (const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel) |
enum ast_pbx_result | ast_pbx_run (struct ast_channel *c) |
Execute the PBX in the current thread. | |
static void * | ast_pbx_run_app (void *data) |
run the application and free the descriptor once done | |
enum ast_pbx_result | ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args) |
Execute the PBX in the current thread. | |
enum ast_pbx_result | ast_pbx_start (struct ast_channel *c) |
Create a new thread and start the PBX. | |
int | ast_processed_calls (void) |
Retrieve the total number of calls processed through the PBX since last restart. | |
int | ast_rdlock_context (struct ast_context *con) |
Read locks a given context. | |
int | ast_rdlock_contexts () |
Read locks the context list. | |
int | ast_register_application2 (const char *app, int(*execute)(struct ast_channel *, const char *), 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_str_get_hint (struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten) |
If an extension hint exists, return non-zero. | |
const char * | ast_str_retrieve_variable (struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var) |
void | ast_str_substitute_variables (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ) |
void | ast_str_substitute_variables_full (struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used) |
void | ast_str_substitute_variables_varshead (struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ) |
static const char * | ast_str_substring (struct ast_str *value, int offset, int length) |
int | ast_unlock_context (struct ast_context *con) |
int | ast_unlock_contexts () |
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. | |
static void * | async_wait (void *data) |
static void | cli_match_char_tree (struct match_char *node, char *prefix, int fd) |
static int | collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos) |
collect digits from the channel into the buffer. | |
static int | compare_char (const void *a, const void *b) |
static char * | complete_core_show_hint (const char *line, const char *word, int pos, int state) |
autocomplete for CLI command 'core show hint' | |
static char * | complete_show_dialplan_context (const char *line, const char *word, int pos, int state) |
static void | context_merge (struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar) |
static void | context_merge_incls_swits_igps_other_registrars (struct ast_context *new, struct ast_context *old, const char *registrar) |
static void | create_match_char_tree (struct ast_context *con) |
static void | decrease_call_count (void) |
static void | destroy_exten (struct ast_exten *e) |
static void | destroy_pattern_tree (struct match_char *pattern_tree) |
static void | device_state_cb (const struct ast_event *event, void *unused) |
static void | exception_store_free (void *data) |
static int | ext_cmp (const char *a, const char *b) |
the full routine to compare extensions in rules. | |
static int | ext_cmp1 (const char **p, unsigned char *bitwise) |
helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first. | |
static int | ext_strncpy (char *dst, const char *src, int len) |
copy a string skipping whitespace | |
static int | extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
static struct ast_context * | find_context (const char *context) |
lookup for a context with a given name, | |
static struct ast_context * | find_context_locked (const char *context) |
lookup for a context with a given name, | |
static int | find_hint_by_cb_id (void *obj, void *arg, int flags) |
Remove a watcher from the callback list. | |
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, const char *const names[], const char *msg) |
helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers. | |
static void | get_timerange (struct ast_timing *i, char *times) |
store a bitmask of valid times, one bit each 1 minute | |
static char * | handle_debug_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Send ack once. | |
static char * | handle_set_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_set_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_set_global (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_application (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_applications (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
CLI support for listing chanvar's variables in a parseable way. | |
static char * | handle_show_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_function (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_functions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_show_globals (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
CLI support for listing global variables in a parseable way. | |
static char * | handle_show_hint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
handle_show_hint: CLI support for listing registered dial plan hint | |
static char * | handle_show_hints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
handle_show_hints: CLI support for listing registered dial plan hints | |
static char * | handle_show_switches (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
handle_show_switches: CLI support for listing registered dial plan switches | |
static int | handle_statechange (void *datap) |
static char * | handle_unset_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | hashtab_compare_exten_labels (const void *ah_a, const void *ah_b) |
static int | hashtab_compare_exten_numbers (const void *ah_a, const void *ah_b) |
static int | hashtab_compare_extens (const void *ha_a, const void *ah_b) |
static unsigned int | hashtab_hash_extens (const void *obj) |
static unsigned int | hashtab_hash_labels (const void *obj) |
static unsigned int | hashtab_hash_priority (const void *obj) |
static int | hint_cmp (void *obj, void *arg, int flags) |
static int | hint_hash (const void *obj, const int flags) |
static int | hint_id_cmp (void *obj, void *arg, int flags) |
static int | hints_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root) |
static int | include_valid (struct ast_include *i) |
static int | increase_call_count (const struct ast_channel *c) |
Increase call count for channel. | |
static void | insert_in_next_chars_alt_char_list (struct match_char **parent_ptr, struct match_char *node) |
int | load_pbx (void) |
static int | lookup_name (const char *s, const char *const names[], int max) |
Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values. | |
static void | manager_dpsendack (struct mansession *s, const struct message *m) |
Send ack once. | |
static int | manager_show_dialplan (struct mansession *s, const struct message *m) |
Manager listing of dial plan. | |
static int | manager_show_dialplan_helper (struct mansession *s, const struct message *m, const char *actionidtext, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude) |
Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dialplan. Must check whether the difference is intentional or not. | |
static int | matchcid (const char *cidpattern, const char *callerid) |
static void | new_find_extension (const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action) |
static int | parse_variable_name (char *var, int *offset, int *length, int *isfunc) |
extract offset:length from variable name. | |
static int | pbx_builtin_answer (struct ast_channel *, const char *) |
static int | pbx_builtin_background (struct ast_channel *, const char *) |
static int | pbx_builtin_busy (struct ast_channel *, const char *) |
void | pbx_builtin_clear_globals (void) |
static int | pbx_builtin_congestion (struct ast_channel *, const char *) |
static int | pbx_builtin_execiftime (struct ast_channel *, const char *) |
const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
Return a pointer to the value of the corresponding channel variable. | |
static int | pbx_builtin_goto (struct ast_channel *, const char *) |
static int | pbx_builtin_gotoif (struct ast_channel *, const char *) |
static int | pbx_builtin_gotoiftime (struct ast_channel *, const char *) |
static int | pbx_builtin_hangup (struct ast_channel *, const char *) |
static int | pbx_builtin_importvar (struct ast_channel *, const char *) |
static int | pbx_builtin_incomplete (struct ast_channel *, const char *) |
static int | pbx_builtin_noop (struct ast_channel *, const char *) |
static int | pbx_builtin_proceeding (struct ast_channel *, const char *) |
static int | pbx_builtin_progress (struct ast_channel *, const char *) |
void | pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value) |
Add a variable to the channel variable stack, without removing any previously set value. | |
int | pbx_builtin_raise_exception (struct ast_channel *chan, const char *reason) |
static int | pbx_builtin_resetcdr (struct ast_channel *, const char *) |
static int | pbx_builtin_ringing (struct ast_channel *, const char *) |
static int | pbx_builtin_saycharacters (struct ast_channel *, const char *) |
static int | pbx_builtin_saydigits (struct ast_channel *, const char *) |
static int | pbx_builtin_saynumber (struct ast_channel *, const char *) |
static int | pbx_builtin_sayphonetic (struct ast_channel *, const char *) |
int | pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf) |
Create a human-readable string, specifying all variables and their corresponding values. | |
static int | pbx_builtin_setamaflags (struct ast_channel *, const char *) |
int | pbx_builtin_setvar (struct ast_channel *chan, const char *data) |
Parse and set a single channel variable, where the name and value are separated with an '=' character. | |
int | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
Add a variable to the channel variable stack, removing the most recently set value for the same name. | |
int | pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *vdata) |
Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character. | |
static int | pbx_builtin_wait (struct ast_channel *, const char *) |
static int | pbx_builtin_waitexten (struct ast_channel *, const char *) |
int | pbx_checkcondition (const char *condition) |
Evaluate a condition. | |
static void | pbx_destroy (struct ast_pbx *p) |
int | pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data) |
Execute an application. | |
static int | pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn) |
The return value depends on the action:. | |
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) |
Retrieve the value of a builtin variable or variable from the channel variable stack. | |
int | pbx_set_autofallthrough (int newval) |
int | pbx_set_extenpatternmatchnew (int newval) |
void | pbx_set_overrideswitch (const char *newval) |
static void | pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e) |
void | pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count) |
void | pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used) |
void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
static void * | pbx_thread (void *data) |
static void | print_app_docs (struct ast_app *aa, int fd) |
static void | print_ext (struct ast_exten *e, char *buf, int buflen) |
helper function to print an extension | |
static void | set_ext_pri (struct ast_channel *c, const char *exten, int pri) |
static int | show_debug_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[]) |
static int | show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[]) |
static int | statecbs_cmp (void *obj, void *arg, int flags) |
static char * | substring (const char *value, int offset, int length, char *workspace, size_t workspace_len) |
takes a substring. It is ok to call with value == workspace. | |
static int | testtime_write (struct ast_channel *chan, const char *cmd, char *var, const char *value) |
static struct ast_exten * | trie_find_next_match (struct match_char *node) |
static void | unreference_cached_app (struct ast_app *app) |
static void | update_scoreboard (struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node) |
static void | wait_for_hangup (struct ast_channel *chan, const void *data) |
Variables | |
static int | autofallthrough = 1 |
static struct ast_app_option | background_opts [128] = { [ 's' ] = { .flag = (1 << 0) }, [ 'n' ] = { .flag = (1 << 1) }, [ 'm' ] = { .flag = (1 << 2) }, [ 'p' ] = { .flag = (1 << 3) },} |
static struct pbx_builtin | builtins [] |
Declaration of builtin applications. | |
static ast_mutex_t | conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
Lock for the ast_context list This lock MUST be recursive, or a deadlock on reload may result. See https://issues.asterisk.org/view.php?id=17643. | |
static struct ast_context * | contexts |
static struct ast_hashtab * | contexts_table = NULL |
static int | countcalls |
static const char *const | days [] |
static struct ast_event_sub * | device_state_sub |
Subscription for device state change events. | |
static struct ast_taskprocessor * | device_state_tps |
static struct ast_custom_function | exception_function |
static struct ast_datastore_info | exception_store_info |
static int | extenpatternmatchnew = 0 |
static struct cfextension_states | extension_states [] |
static struct ast_threadstorage | extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , } |
static struct varshead | globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE |
static ast_rwlock_t | globalslock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } |
static const int | HASH_EXTENHINT_SIZE = 563 |
static struct ao2_container * | hints |
static struct ast_data_handler | hints_data_provider |
static ast_mutex_t | maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
static const char *const | months [] |
static char * | overrideswitch = NULL |
static struct ast_cli_entry | pbx_cli [] |
static struct ast_data_entry | pbx_data_providers [] |
static struct ast_app_option | resetcdr_opts [128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },} |
static struct ao2_container * | statecbs |
static int | stateid = 1 |
static struct ast_threadstorage | switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , } |
static struct ast_custom_function | testtime_function |
static int | totalcalls |
static struct ast_app_option | waitexten_opts [128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },} |
Definition in file pbx.c.
#define AST_PBX_MAX_STACK 128 |
#define BACKGROUND_MATCHEXTEN (1 << 2) |
#define BACKGROUND_NOANSWER (1 << 1) |
#define BACKGROUND_PLAYBACK (1 << 3) |
#define BACKGROUND_SKIP (1 << 0) |
#define EXT_DATA_SIZE 8192 |
A new algorithm to do searching based on a 'compiled' pattern tree is introduced here, and shows a fairly flat (constant) search time, even for over 10000 patterns.
Also, using a hash table for context/priority name lookup can help prevent the find_extension routines from absorbing exponential cpu cycles as the number of contexts/priorities grow. I've previously tested find_extension with red-black trees, which have O(log2(n)) speed. Right now, I'm using hash tables, which do searches (ideally) in O(1) time. While these techniques do not yield much speed in small dialplans, they are worth the trouble in large dialplans.
Definition at line 770 of file pbx.c.
Referenced by pbx_extension_helper().
#define NEW_MATCHER_CHK_MATCH |
Referenced by new_find_extension().
#define NEW_MATCHER_RECURSE |
#define VAR_BUF_SIZE 4096 |
Definition at line 775 of file pbx.c.
Referenced by ast_add_extension2_lockopt(), ast_func_read2(), pbx_builtin_importvar(), and pbx_substitute_variables_helper_full().
#define WAITEXTEN_DIALTONE (1 << 1) |
#define WAITEXTEN_MOH (1 << 0) |
void __ast_context_destroy | ( | struct ast_context * | list, | |
struct ast_hashtab * | contexttab, | |||
struct ast_context * | con, | |||
const char * | registrar | |||
) |
Definition at line 8714 of file pbx.c.
References __ast_internal_context_destroy(), ast_context_remove_extension_callerid2(), ast_copy_string(), ast_debug, ast_free, ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_remove_this_object(), ast_hashtab_start_traversal(), AST_LIST_EMPTY, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_MAX_EXTENSION, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, contexts, ast_exten::exten, ast_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().
08715 { 08716 struct ast_context *tmp, *tmpl=NULL; 08717 struct ast_exten *exten_item, *prio_item; 08718 08719 for (tmp = list; tmp; ) { 08720 struct ast_context *next = NULL; /* next starting point */ 08721 /* The following code used to skip forward to the next 08722 context with matching registrar, but this didn't 08723 make sense; individual priorities registrar'd to 08724 the matching registrar could occur in any context! */ 08725 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar); 08726 if (con) { 08727 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */ 08728 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar); 08729 if ( !strcasecmp(tmp->name, con->name) ) { 08730 break; /* found it */ 08731 } 08732 } 08733 } 08734 08735 if (!tmp) /* not found, we are done */ 08736 break; 08737 ast_wrlock_context(tmp); 08738 08739 if (registrar) { 08740 /* then search thru and remove any extens that match registrar. */ 08741 struct ast_hashtab_iter *exten_iter; 08742 struct ast_hashtab_iter *prio_iter; 08743 struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL; 08744 struct ast_include *i, *pi = NULL, *ni = NULL; 08745 struct ast_sw *sw = NULL; 08746 08747 /* remove any ignorepats whose registrar matches */ 08748 for (ip = tmp->ignorepats; ip; ip = ipn) { 08749 ipn = ip->next; 08750 if (!strcmp(ip->registrar, registrar)) { 08751 if (ipl) { 08752 ipl->next = ip->next; 08753 ast_free(ip); 08754 continue; /* don't change ipl */ 08755 } else { 08756 tmp->ignorepats = ip->next; 08757 ast_free(ip); 08758 continue; /* don't change ipl */ 08759 } 08760 } 08761 ipl = ip; 08762 } 08763 /* remove any includes whose registrar matches */ 08764 for (i = tmp->includes; i; i = ni) { 08765 ni = i->next; 08766 if (strcmp(i->registrar, registrar) == 0) { 08767 /* remove from list */ 08768 if (pi) { 08769 pi->next = i->next; 08770 /* free include */ 08771 ast_free(i); 08772 continue; /* don't change pi */ 08773 } else { 08774 tmp->includes = i->next; 08775 /* free include */ 08776 ast_free(i); 08777 continue; /* don't change pi */ 08778 } 08779 } 08780 pi = i; 08781 } 08782 /* remove any switches whose registrar matches */ 08783 AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) { 08784 if (strcmp(sw->registrar,registrar) == 0) { 08785 AST_LIST_REMOVE_CURRENT(list); 08786 ast_free(sw); 08787 } 08788 } 08789 AST_LIST_TRAVERSE_SAFE_END; 08790 08791 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */ 08792 exten_iter = ast_hashtab_start_traversal(tmp->root_table); 08793 while ((exten_item=ast_hashtab_next(exten_iter))) { 08794 int end_traversal = 1; 08795 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 08796 while ((prio_item=ast_hashtab_next(prio_iter))) { 08797 char extension[AST_MAX_EXTENSION]; 08798 char cidmatch[AST_MAX_EXTENSION]; 08799 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) { 08800 continue; 08801 } 08802 ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n", 08803 tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL); 08804 /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */ 08805 ast_copy_string(extension, prio_item->exten, sizeof(extension)); 08806 if (prio_item->cidmatch) { 08807 ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch)); 08808 } 08809 end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, prio_item->cidmatch ? cidmatch : NULL, 1, NULL, 1); 08810 } 08811 /* Explanation: 08812 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This 08813 * destruction includes destroying the exten's peer_table, which we are currently traversing. If 08814 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed 08815 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result 08816 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply 08817 * free the iterator 08818 */ 08819 if (end_traversal) { 08820 ast_hashtab_end_traversal(prio_iter); 08821 } else { 08822 ast_free(prio_iter); 08823 } 08824 } 08825 ast_hashtab_end_traversal(exten_iter); 08826 } 08827 08828 /* delete the context if it's registrar matches, is empty, has refcount of 1, */ 08829 /* it's not empty, if it has includes, ignorepats, or switches that are registered from 08830 another registrar. It's not empty if there are any extensions */ 08831 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) { 08832 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 08833 ast_hashtab_remove_this_object(contexttab, tmp); 08834 08835 next = tmp->next; 08836 if (tmpl) 08837 tmpl->next = next; 08838 else 08839 contexts = next; 08840 /* Okay, now we're safe to let it go -- in a sense, we were 08841 ready to let it go as soon as we locked it. */ 08842 ast_unlock_context(tmp); 08843 __ast_internal_context_destroy(tmp); 08844 } else { 08845 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar, 08846 tmp->refcount, tmp->root); 08847 ast_unlock_context(tmp); 08848 next = tmp->next; 08849 tmpl = tmp; 08850 } 08851 } else if (con) { 08852 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar); 08853 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar); 08854 ast_hashtab_remove_this_object(contexttab, tmp); 08855 08856 next = tmp->next; 08857 if (tmpl) 08858 tmpl->next = next; 08859 else 08860 contexts = next; 08861 /* Okay, now we're safe to let it go -- in a sense, we were 08862 ready to let it go as soon as we locked it. */ 08863 ast_unlock_context(tmp); 08864 __ast_internal_context_destroy(tmp); 08865 } 08866 08867 /* if we have a specific match, we are done, otherwise continue */ 08868 tmp = con ? NULL : next; 08869 } 08870 }
int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
struct ast_module * | mod | |||
) |
Register a custom function.
Definition at line 3413 of file pbx.c.
References acf_retrieve_docs(), ast_custom_function::acflist, ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_verb, COLOR_BRCYAN, ast_custom_function::docsrc, LOG_ERROR, ast_custom_function::mod, ast_custom_function::name, and term_color().
Referenced by load_pbx().
03414 { 03415 struct ast_custom_function *cur; 03416 char tmps[80]; 03417 03418 if (!acf) { 03419 return -1; 03420 } 03421 03422 acf->mod = mod; 03423 #ifdef AST_XML_DOCS 03424 acf->docsrc = AST_STATIC_DOC; 03425 #endif 03426 03427 if (acf_retrieve_docs(acf)) { 03428 return -1; 03429 } 03430 03431 AST_RWLIST_WRLOCK(&acf_root); 03432 03433 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03434 if (!strcmp(acf->name, cur->name)) { 03435 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03436 AST_RWLIST_UNLOCK(&acf_root); 03437 return -1; 03438 } 03439 } 03440 03441 /* Store in alphabetical order */ 03442 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03443 if (strcasecmp(acf->name, cur->name) < 0) { 03444 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03445 break; 03446 } 03447 } 03448 AST_RWLIST_TRAVERSE_SAFE_END; 03449 03450 if (!cur) { 03451 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03452 } 03453 03454 AST_RWLIST_UNLOCK(&acf_root); 03455 03456 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03457 03458 return 0; 03459 }
static int __ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int | async | |||
) | [static] |
Definition at line 10106 of file pbx.c.
References ast_async_goto(), ast_exists_extension(), ast_explicit_goto(), AST_PBX_GOTO_FAILED, ast_channel::context, ast_channel::exten, and S_COR.
Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().
10107 { 10108 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 10109 10110 if (!chan) 10111 return -2; 10112 10113 if (context == NULL) 10114 context = chan->context; 10115 if (exten == NULL) 10116 exten = chan->exten; 10117 10118 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 10119 if (ast_exists_extension(chan, context, exten, priority, 10120 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) 10121 return goto_func(chan, context, exten, priority); 10122 else { 10123 return AST_PBX_GOTO_FAILED; 10124 } 10125 }
static void __ast_internal_context_destroy | ( | struct ast_context * | con | ) | [static] |
Definition at line 8667 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().
08668 { 08669 struct ast_include *tmpi; 08670 struct ast_sw *sw; 08671 struct ast_exten *e, *el, *en; 08672 struct ast_ignorepat *ipi; 08673 struct ast_context *tmp = con; 08674 08675 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 08676 struct ast_include *tmpil = tmpi; 08677 tmpi = tmpi->next; 08678 ast_free(tmpil); 08679 } 08680 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 08681 struct ast_ignorepat *ipl = ipi; 08682 ipi = ipi->next; 08683 ast_free(ipl); 08684 } 08685 if (tmp->registrar) 08686 ast_free(tmp->registrar); 08687 08688 /* destroy the hash tabs */ 08689 if (tmp->root_table) { 08690 ast_hashtab_destroy(tmp->root_table, 0); 08691 } 08692 /* and destroy the pattern tree */ 08693 if (tmp->pattern_tree) 08694 destroy_pattern_tree(tmp->pattern_tree); 08695 08696 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 08697 ast_free(sw); 08698 for (e = tmp->root; e;) { 08699 for (en = e->peer; en;) { 08700 el = en; 08701 en = en->peer; 08702 destroy_exten(el); 08703 } 08704 el = e; 08705 e = e->next; 08706 destroy_exten(el); 08707 } 08708 tmp->root = NULL; 08709 ast_rwlock_destroy(&tmp->lock); 08710 ast_free(tmp); 08711 }
static enum ast_pbx_result __ast_pbx_run | ( | struct ast_channel * | c, | |
struct ast_pbx_args * | args | |||
) | [static] |
Definition at line 4654 of file pbx.c.
References ast_channel::_softhangup, ast_calloc, ast_cdr_update(), ast_channel_clear_softhangup(), ast_check_hangup(), ast_copy_string(), ast_debug, ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_free, ast_log(), ast_set_flag, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_test_flag, ast_verb, ast_channel::caller, ast_channel::cdr, ast_channel::context, ast_pbx::dtimeoutms, ast_channel::exten, ast_party_caller::id, LOG_WARNING, ast_channel::name, ast_party_id::number, ast_channel::pbx, pbx_builtin_raise_exception(), ast_channel::priority, ast_pbx::rtimeoutms, S_COR, set_ext_pri(), ast_party_number::str, and ast_party_number::valid.
Referenced by ast_pbx_run_args(), and pbx_thread().
04656 { 04657 int found = 0; /* set if we find at least one match */ 04658 int res = 0; 04659 int autoloopflag; 04660 int error = 0; /* set an error conditions */ 04661 04662 /* A little initial setup here */ 04663 if (c->pbx) { 04664 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 04665 /* XXX and now what ? */ 04666 ast_free(c->pbx); 04667 } 04668 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 04669 return -1; 04670 /* Set reasonable defaults */ 04671 c->pbx->rtimeoutms = 10000; 04672 c->pbx->dtimeoutms = 5000; 04673 04674 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 04675 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 04676 04677 /* Start by trying whatever the channel is set to */ 04678 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 04679 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04680 /* If not successful fall back to 's' */ 04681 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); 04682 /* XXX the original code used the existing priority in the call to 04683 * ast_exists_extension(), and reset it to 1 afterwards. 04684 * I believe the correct thing is to set it to 1 immediately. 04685 */ 04686 set_ext_pri(c, "s", 1); 04687 if (!ast_exists_extension(c, c->context, c->exten, c->priority, 04688 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04689 /* JK02: And finally back to default if everything else failed */ 04690 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); 04691 ast_copy_string(c->context, "default", sizeof(c->context)); 04692 } 04693 } 04694 if (c->cdr) { 04695 /* allow CDR variables that have been collected after channel was created to be visible during call */ 04696 ast_cdr_update(c); 04697 } 04698 for (;;) { 04699 char dst_exten[256]; /* buffer to accumulate digits */ 04700 int pos = 0; /* XXX should check bounds */ 04701 int digit = 0; 04702 int invalid = 0; 04703 int timeout = 0; 04704 04705 /* loop on priorities in this context/exten */ 04706 while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority, 04707 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 04708 &found, 1))) { 04709 if ((c->_softhangup & AST_SOFTHANGUP_TIMEOUT) 04710 && ast_exists_extension(c, c->context, "T", 1, 04711 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04712 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */ 04713 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 04714 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 04715 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 04716 } else if ((c->_softhangup & AST_SOFTHANGUP_TIMEOUT) 04717 && ast_exists_extension(c, c->context, "e", 1, 04718 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04719 pbx_builtin_raise_exception(c, "ABSOLUTETIMEOUT"); 04720 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 04721 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 04722 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 04723 } else if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 04724 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 04725 continue; 04726 } else if (ast_check_hangup(c)) { 04727 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n", 04728 c->exten, c->priority); 04729 error = 1; 04730 break; 04731 } 04732 c->priority++; 04733 } /* end while - from here on we can use 'break' to go out */ 04734 if (found && res) { 04735 /* Something bad happened, or a hangup has been requested. */ 04736 if (strchr("0123456789ABCDEF*#", res)) { 04737 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res); 04738 pos = 0; 04739 dst_exten[pos++] = digit = res; 04740 dst_exten[pos] = '\0'; 04741 } else if (res == AST_PBX_INCOMPLETE) { 04742 ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 04743 ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name); 04744 04745 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */ 04746 if (!ast_matchmore_extension(c, c->context, c->exten, 1, 04747 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04748 invalid = 1; 04749 } else { 04750 ast_copy_string(dst_exten, c->exten, sizeof(dst_exten)); 04751 digit = 1; 04752 pos = strlen(dst_exten); 04753 } 04754 } else { 04755 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 04756 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 04757 04758 if ((res == AST_PBX_ERROR) 04759 && ast_exists_extension(c, c->context, "e", 1, 04760 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04761 /* if we are already on the 'e' exten, don't jump to it again */ 04762 if (!strcmp(c->exten, "e")) { 04763 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); 04764 error = 1; 04765 } else { 04766 pbx_builtin_raise_exception(c, "ERROR"); 04767 continue; 04768 } 04769 } 04770 04771 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 04772 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 04773 continue; 04774 } else if ((c->_softhangup & AST_SOFTHANGUP_TIMEOUT) 04775 && ast_exists_extension(c, c->context, "T", 1, 04776 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04777 set_ext_pri(c, "T", 1); 04778 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 04779 memset(&c->whentohangup, 0, sizeof(c->whentohangup)); 04780 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 04781 continue; 04782 } else { 04783 if (c->cdr) 04784 ast_cdr_update(c); 04785 error = 1; 04786 break; 04787 } 04788 } 04789 } 04790 if (error) 04791 break; 04792 04793 /*!\note 04794 * We get here on a failure of some kind: non-existing extension or 04795 * hangup. We have options, here. We can either catch the failure 04796 * and continue, or we can drop out entirely. */ 04797 04798 if (invalid 04799 || !ast_exists_extension(c, c->context, c->exten, 1, 04800 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04801 /*!\note 04802 * If there is no match at priority 1, it is not a valid extension anymore. 04803 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if 04804 * neither exist. 04805 */ 04806 if (ast_exists_extension(c, c->context, "i", 1, 04807 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04808 ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 04809 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 04810 set_ext_pri(c, "i", 1); 04811 } else if (ast_exists_extension(c, c->context, "e", 1, 04812 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04813 pbx_builtin_raise_exception(c, "INVALID"); 04814 } else { 04815 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 04816 c->name, c->exten, c->context); 04817 error = 1; /* we know what to do with it */ 04818 break; 04819 } 04820 } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { 04821 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 04822 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); 04823 } else { /* keypress received, get more digits for a full extension */ 04824 int waittime = 0; 04825 if (digit) 04826 waittime = c->pbx->dtimeoutms; 04827 else if (!autofallthrough) 04828 waittime = c->pbx->rtimeoutms; 04829 if (!waittime) { 04830 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 04831 if (!status) 04832 status = "UNKNOWN"; 04833 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 04834 if (!strcasecmp(status, "CONGESTION")) 04835 res = pbx_builtin_congestion(c, "10"); 04836 else if (!strcasecmp(status, "CHANUNAVAIL")) 04837 res = pbx_builtin_congestion(c, "10"); 04838 else if (!strcasecmp(status, "BUSY")) 04839 res = pbx_builtin_busy(c, "10"); 04840 error = 1; /* XXX disable message */ 04841 break; /* exit from the 'for' loop */ 04842 } 04843 04844 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 04845 break; 04846 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos])) 04847 timeout = 1; 04848 if (!timeout 04849 && ast_exists_extension(c, c->context, dst_exten, 1, 04850 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */ 04851 set_ext_pri(c, dst_exten, 1); 04852 } else { 04853 /* No such extension */ 04854 if (!timeout && !ast_strlen_zero(dst_exten)) { 04855 /* An invalid extension */ 04856 if (ast_exists_extension(c, c->context, "i", 1, 04857 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04858 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 04859 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 04860 set_ext_pri(c, "i", 1); 04861 } else if (ast_exists_extension(c, c->context, "e", 1, 04862 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04863 pbx_builtin_raise_exception(c, "INVALID"); 04864 } else { 04865 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context); 04866 found = 1; /* XXX disable message */ 04867 break; 04868 } 04869 } else { 04870 /* A simple timeout */ 04871 if (ast_exists_extension(c, c->context, "t", 1, 04872 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04873 ast_verb(3, "Timeout on %s\n", c->name); 04874 set_ext_pri(c, "t", 1); 04875 } else if (ast_exists_extension(c, c->context, "e", 1, 04876 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04877 pbx_builtin_raise_exception(c, "RESPONSETIMEOUT"); 04878 } else { 04879 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); 04880 found = 1; /* XXX disable message */ 04881 break; 04882 } 04883 } 04884 } 04885 if (c->cdr) { 04886 ast_verb(2, "CDR updated on %s\n",c->name); 04887 ast_cdr_update(c); 04888 } 04889 } 04890 } 04891 04892 if (!found && !error) { 04893 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 04894 } 04895 04896 if (!args || !args->no_hangup_chan) { 04897 ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD); 04898 } 04899 04900 if ((!args || !args->no_hangup_chan) 04901 && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) 04902 && ast_exists_extension(c, c->context, "h", 1, 04903 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04904 set_ext_pri(c, "h", 1); 04905 if (c->cdr && ast_opt_end_cdr_before_h_exten) { 04906 ast_cdr_end(c->cdr); 04907 } 04908 while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, 04909 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL), 04910 &found, 1)) == 0) { 04911 c->priority++; 04912 } 04913 if (found && res) { 04914 /* Something bad happened, or a hangup has been requested. */ 04915 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 04916 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 04917 } 04918 } 04919 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 04920 ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */ 04921 pbx_destroy(c->pbx); 04922 c->pbx = NULL; 04923 04924 if (!args || !args->no_hangup_chan) { 04925 ast_hangup(c); 04926 } 04927 04928 return 0; 04929 }
static void __init_extensionstate_buf | ( | void | ) | [static] |
static void __init_switch_data | ( | void | ) | [static] |
static int _extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 2307 of file pbx.c.
References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, LOG_NOTICE, and LOG_WARNING.
Referenced by extension_match_core().
02308 { 02309 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 02310 02311 #ifdef NEED_DEBUG_HERE 02312 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode); 02313 #endif 02314 02315 if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */ 02316 #ifdef NEED_DEBUG_HERE 02317 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n"); 02318 #endif 02319 return 1; 02320 } 02321 02322 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 02323 int ld = strlen(data), lp = strlen(pattern); 02324 02325 if (lp < ld) { /* pattern too short, cannot match */ 02326 #ifdef NEED_DEBUG_HERE 02327 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n"); 02328 #endif 02329 return 0; 02330 } 02331 /* depending on the mode, accept full or partial match or both */ 02332 if (mode == E_MATCH) { 02333 #ifdef NEED_DEBUG_HERE 02334 ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data); 02335 #endif 02336 return !strcmp(pattern, data); /* 1 on match, 0 on fail */ 02337 } 02338 if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */ 02339 #ifdef NEED_DEBUG_HERE 02340 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld); 02341 #endif 02342 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 02343 } else { 02344 #ifdef NEED_DEBUG_HERE 02345 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data); 02346 #endif 02347 return 0; 02348 } 02349 } 02350 pattern++; /* skip leading _ */ 02351 /* 02352 * XXX below we stop at '/' which is a separator for the CID info. However we should 02353 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 02354 */ 02355 while (*data && *pattern && *pattern != '/') { 02356 const char *end; 02357 02358 if (*data == '-') { /* skip '-' in data (just a separator) */ 02359 data++; 02360 continue; 02361 } 02362 switch (toupper(*pattern)) { 02363 case '[': /* a range */ 02364 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */ 02365 if (end == NULL) { 02366 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02367 return 0; /* unconditional failure */ 02368 } 02369 for (pattern++; pattern != end; pattern++) { 02370 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 02371 if (*data >= pattern[0] && *data <= pattern[2]) 02372 break; /* match found */ 02373 else { 02374 pattern += 2; /* skip a total of 3 chars */ 02375 continue; 02376 } 02377 } else if (*data == pattern[0]) 02378 break; /* match found */ 02379 } 02380 if (pattern == end) { 02381 #ifdef NEED_DEBUG_HERE 02382 ast_log(LOG_NOTICE,"return (0) when pattern==end\n"); 02383 #endif 02384 return 0; 02385 } 02386 pattern = end; /* skip and continue */ 02387 break; 02388 case 'N': 02389 if (*data < '2' || *data > '9') { 02390 #ifdef NEED_DEBUG_HERE 02391 ast_log(LOG_NOTICE,"return (0) N is matched\n"); 02392 #endif 02393 return 0; 02394 } 02395 break; 02396 case 'X': 02397 if (*data < '0' || *data > '9') { 02398 #ifdef NEED_DEBUG_HERE 02399 ast_log(LOG_NOTICE,"return (0) X is matched\n"); 02400 #endif 02401 return 0; 02402 } 02403 break; 02404 case 'Z': 02405 if (*data < '1' || *data > '9') { 02406 #ifdef NEED_DEBUG_HERE 02407 ast_log(LOG_NOTICE,"return (0) Z is matched\n"); 02408 #endif 02409 return 0; 02410 } 02411 break; 02412 case '.': /* Must match, even with more digits */ 02413 #ifdef NEED_DEBUG_HERE 02414 ast_log(LOG_NOTICE, "return (1) when '.' is matched\n"); 02415 #endif 02416 return 1; 02417 case '!': /* Early match */ 02418 #ifdef NEED_DEBUG_HERE 02419 ast_log(LOG_NOTICE, "return (2) when '!' is matched\n"); 02420 #endif 02421 return 2; 02422 case ' ': 02423 case '-': /* Ignore these in patterns */ 02424 data--; /* compensate the final data++ */ 02425 break; 02426 default: 02427 if (*data != *pattern) { 02428 #ifdef NEED_DEBUG_HERE 02429 ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern); 02430 #endif 02431 return 0; 02432 } 02433 } 02434 data++; 02435 pattern++; 02436 } 02437 if (*data) /* data longer than pattern, no match */ { 02438 #ifdef NEED_DEBUG_HERE 02439 ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n"); 02440 #endif 02441 return 0; 02442 } 02443 02444 /* 02445 * match so far, but ran off the end of the data. 02446 * Depending on what is next, determine match or not. 02447 */ 02448 if (*pattern == '\0' || *pattern == '/') { /* exact match */ 02449 #ifdef NEED_DEBUG_HERE 02450 ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1); 02451 #endif 02452 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 02453 } else if (*pattern == '!') { /* early match */ 02454 #ifdef NEED_DEBUG_HERE 02455 ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n"); 02456 #endif 02457 return 2; 02458 } else { /* partial match */ 02459 #ifdef NEED_DEBUG_HERE 02460 ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1); 02461 #endif 02462 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 02463 } 02464 }
static int acf_exception_read | ( | struct ast_channel * | chan, | |
const char * | name, | |||
char * | data, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 3150 of file pbx.c.
References ast_channel_datastore_find(), ast_copy_string(), pbx_exception::context, ast_datastore::data, exception_store_info, pbx_exception::exten, pbx_exception::priority, and pbx_exception::reason.
03151 { 03152 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03153 struct pbx_exception *exception = NULL; 03154 if (!ds || !ds->data) 03155 return -1; 03156 exception = ds->data; 03157 if (!strcasecmp(data, "REASON")) 03158 ast_copy_string(buf, exception->reason, buflen); 03159 else if (!strcasecmp(data, "CONTEXT")) 03160 ast_copy_string(buf, exception->context, buflen); 03161 else if (!strncasecmp(data, "EXTEN", 5)) 03162 ast_copy_string(buf, exception->exten, buflen); 03163 else if (!strcasecmp(data, "PRIORITY")) 03164 snprintf(buf, buflen, "%d", exception->priority); 03165 else 03166 return -1; 03167 return 0; 03168 }
static int acf_retrieve_docs | ( | struct ast_custom_function * | acf | ) | [static] |
Definition at line 3368 of file pbx.c.
References ast_custom_function::arguments, ast_free, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), desc, ast_custom_function::desc, ast_custom_function::docsrc, ast_custom_function::name, ast_custom_function::seealso, synopsis, ast_custom_function::synopsis, and ast_custom_function::syntax.
Referenced by __ast_custom_function_register().
03369 { 03370 #ifdef AST_XML_DOCS 03371 char *tmpxml; 03372 03373 /* Let's try to find it in the Documentation XML */ 03374 if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) { 03375 return 0; 03376 } 03377 03378 if (ast_string_field_init(acf, 128)) { 03379 return -1; 03380 } 03381 03382 /* load synopsis */ 03383 tmpxml = ast_xmldoc_build_synopsis("function", acf->name); 03384 ast_string_field_set(acf, synopsis, tmpxml); 03385 ast_free(tmpxml); 03386 03387 /* load description */ 03388 tmpxml = ast_xmldoc_build_description("function", acf->name); 03389 ast_string_field_set(acf, desc, tmpxml); 03390 ast_free(tmpxml); 03391 03392 /* load syntax */ 03393 tmpxml = ast_xmldoc_build_syntax("function", acf->name); 03394 ast_string_field_set(acf, syntax, tmpxml); 03395 ast_free(tmpxml); 03396 03397 /* load arguments */ 03398 tmpxml = ast_xmldoc_build_arguments("function", acf->name); 03399 ast_string_field_set(acf, arguments, tmpxml); 03400 ast_free(tmpxml); 03401 03402 /* load seealso */ 03403 tmpxml = ast_xmldoc_build_seealso("function", acf->name); 03404 ast_string_field_set(acf, seealso, tmpxml); 03405 ast_free(tmpxml); 03406 03407 acf->docsrc = AST_XML_DOC; 03408 #endif 03409 03410 return 0; 03411 }
static struct match_char * add_exten_to_pattern_tree | ( | struct ast_context * | con, | |
struct ast_exten * | e1, | |||
int | findonly | |||
) | [static] |
Definition at line 1943 of file pbx.c.
References add_pattern_node(), already_in_tree(), ast_copy_string(), ast_log(), ast_exten::cidmatch, compare_char(), match_char::deleted, match_char::exten, ast_exten::exten, LOG_DEBUG, LOG_ERROR, LOG_WARNING, ast_exten::matchcid, match_char::next_char, and ast_context::pattern_tree.
Referenced by ast_add_extension2_lockopt(), ast_context_remove_extension_callerid2(), and create_match_char_tree().
01944 { 01945 struct match_char *m1 = NULL, *m2 = NULL, **m0; 01946 int specif; 01947 int already; 01948 int pattern = 0; 01949 char buf[256]; 01950 char extenbuf[512]; 01951 char *s1 = extenbuf; 01952 int l1 = strlen(e1->exten) + strlen(e1->cidmatch) + 2; 01953 01954 01955 ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf)); 01956 01957 if (e1->matchcid && l1 <= sizeof(extenbuf)) { 01958 strcat(extenbuf, "/"); 01959 strcat(extenbuf, e1->cidmatch); 01960 } else if (l1 > sizeof(extenbuf)) { 01961 ast_log(LOG_ERROR, "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", e1->exten, e1->cidmatch); 01962 return 0; 01963 } 01964 #ifdef NEED_DEBUG 01965 ast_log(LOG_DEBUG, "Adding exten %s%c%s to tree\n", s1, e1->matchcid ? '/' : ' ', e1->matchcid ? e1->cidmatch : ""); 01966 #endif 01967 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */ 01968 m0 = &con->pattern_tree; 01969 already = 1; 01970 01971 if ( *s1 == '_') { 01972 pattern = 1; 01973 s1++; 01974 } 01975 while (*s1) { 01976 if (pattern && *s1 == '[' && *(s1 - 1) != '\\') { 01977 char *s2 = buf; 01978 buf[0] = 0; 01979 s1++; /* get past the '[' */ 01980 while (*s1 != ']' && *(s1 - 1) != '\\') { 01981 if (*s1 == '\\') { 01982 if (*(s1 + 1) == ']') { 01983 *s2++ = ']'; 01984 s1 += 2; 01985 } else if (*(s1 + 1) == '\\') { 01986 *s2++ = '\\'; 01987 s1 += 2; 01988 } else if (*(s1 + 1) == '-') { 01989 *s2++ = '-'; 01990 s1 += 2; 01991 } else if (*(s1 + 1) == '[') { 01992 *s2++ = '['; 01993 s1 += 2; 01994 } 01995 } else if (*s1 == '-') { /* remember to add some error checking to all this! */ 01996 char s3 = *(s1 - 1); 01997 char s4 = *(s1 + 1); 01998 for (s3++; s3 <= s4; s3++) { 01999 *s2++ = s3; 02000 } 02001 s1 += 2; 02002 } else if (*s1 == '\0') { 02003 ast_log(LOG_WARNING, "A matching ']' was not found for '[' in pattern string '%s'\n", extenbuf); 02004 break; 02005 } else { 02006 *s2++ = *s1++; 02007 } 02008 } 02009 *s2 = 0; /* null terminate the exploded range */ 02010 /* sort the characters */ 02011 02012 specif = strlen(buf); 02013 qsort(buf, specif, 1, compare_char); 02014 specif <<= 8; 02015 specif += buf[0]; 02016 } else if (*s1 == '-') { 02017 /* Skip dashes in patterns */ 02018 s1++; 02019 continue; 02020 } else { 02021 if (*s1 == '\\') { 02022 s1++; 02023 buf[0] = *s1; 02024 } else { 02025 if (pattern) { 02026 if (*s1 == 'n') { /* make sure n,x,z patterns are canonicalized to N,X,Z */ 02027 *s1 = 'N'; 02028 } else if (*s1 == 'x') { 02029 *s1 = 'X'; 02030 } else if (*s1 == 'z') { 02031 *s1 = 'Z'; 02032 } 02033 } 02034 buf[0] = *s1; 02035 } 02036 buf[1] = 0; 02037 specif = 1; 02038 } 02039 m2 = 0; 02040 if (already && (m2 = already_in_tree(m1, buf, pattern)) && m2->next_char) { 02041 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... 02042 a shorter pattern might win if the longer one doesn't match */ 02043 if (m2->exten) { 02044 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", m2->exten->exten, e1->exten); 02045 } 02046 m2->exten = e1; 02047 m2->deleted = 0; 02048 } 02049 m1 = m2->next_char; /* m1 points to the node to compare against */ 02050 m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */ 02051 } else { /* not already OR not m2 OR nor m2->next_char */ 02052 if (m2) { 02053 if (findonly) { 02054 return m2; 02055 } 02056 m1 = m2; /* while m0 stays the same */ 02057 } else { 02058 if (findonly) { 02059 return m1; 02060 } 02061 if (!(m1 = add_pattern_node(con, m1, buf, pattern, already,specif, m0))) { /* m1 is the node just added */ 02062 return NULL; 02063 } 02064 m0 = &m1->next_char; 02065 } 02066 if (!(*(s1 + 1))) { 02067 if (m2 && m2->exten) { 02068 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", m2->exten->exten, e1->exten); 02069 } 02070 m1->deleted = 0; 02071 m1->exten = e1; 02072 } 02073 02074 /* The 'already' variable is a mini-optimization designed to make it so that we 02075 * don't have to call already_in_tree when we know it will return false. 02076 */ 02077 already = 0; 02078 } 02079 s1++; /* advance to next char */ 02080 } 02081 return m1; 02082 }
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 1901 of file pbx.c.
References ast_calloc, insert_in_next_chars_alt_char_list(), match_char::next_char, and ast_context::pattern_tree.
Referenced by add_exten_to_pattern_tree().
01902 { 01903 struct match_char *m; 01904 01905 if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern)))) { 01906 return NULL; 01907 } 01908 01909 /* strcpy is safe here since we know its size and have allocated 01910 * just enough space for when we allocated m 01911 */ 01912 strcpy(m->x, pattern); 01913 01914 /* the specificity scores are the same as used in the old 01915 pattern matcher. */ 01916 m->is_pattern = is_pattern; 01917 if (specificity == 1 && is_pattern && pattern[0] == 'N') 01918 m->specificity = 0x0832; 01919 else if (specificity == 1 && is_pattern && pattern[0] == 'Z') 01920 m->specificity = 0x0931; 01921 else if (specificity == 1 && is_pattern && pattern[0] == 'X') 01922 m->specificity = 0x0a30; 01923 else if (specificity == 1 && is_pattern && pattern[0] == '.') 01924 m->specificity = 0x18000; 01925 else if (specificity == 1 && is_pattern && pattern[0] == '!') 01926 m->specificity = 0x28000; 01927 else 01928 m->specificity = specificity; 01929 01930 if (!con->pattern_tree) { 01931 insert_in_next_chars_alt_char_list(&con->pattern_tree, m); 01932 } else { 01933 if (already) { /* switch to the new regime (traversing vs appending)*/ 01934 insert_in_next_chars_alt_char_list(nextcharptr, m); 01935 } else { 01936 insert_in_next_chars_alt_char_list(¤t->next_char, m); 01937 } 01938 } 01939 01940 return m; 01941 }
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 7876 of file pbx.c.
References add_pri_lockopt(), and el.
Referenced by ast_add_extension2_lockopt().
07878 { 07879 return add_pri_lockopt(con, tmp, el, e, replace, 1); 07880 }
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 7887 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().
07889 { 07890 struct ast_exten *ep; 07891 struct ast_exten *eh=e; 07892 07893 for (ep = NULL; e ; ep = e, e = e->peer) { 07894 if (e->priority >= tmp->priority) 07895 break; 07896 } 07897 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 07898 ast_hashtab_insert_safe(eh->peer_table, tmp); 07899 07900 if (tmp->label) { 07901 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 07902 } 07903 ep->peer = tmp; 07904 return 0; /* success */ 07905 } 07906 if (e->priority == tmp->priority) { 07907 /* Can't have something exactly the same. Is this a 07908 replacement? If so, replace, otherwise, bonk. */ 07909 if (!replace) { 07910 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 07911 if (tmp->datad) { 07912 tmp->datad(tmp->data); 07913 /* if you free this, null it out */ 07914 tmp->data = NULL; 07915 } 07916 07917 ast_free(tmp); 07918 return -1; 07919 } 07920 /* we are replacing e, so copy the link fields and then update 07921 * whoever pointed to e to point to us 07922 */ 07923 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 07924 tmp->peer = e->peer; /* always meaningful */ 07925 if (ep) { /* We're in the peer list, just insert ourselves */ 07926 ast_hashtab_remove_object_via_lookup(eh->peer_table,e); 07927 07928 if (e->label) { 07929 ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e); 07930 } 07931 07932 ast_hashtab_insert_safe(eh->peer_table,tmp); 07933 if (tmp->label) { 07934 ast_hashtab_insert_safe(eh->peer_label_table,tmp); 07935 } 07936 07937 ep->peer = tmp; 07938 } else if (el) { /* We're the first extension. Take over e's functions */ 07939 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 07940 tmp->peer_table = e->peer_table; 07941 tmp->peer_label_table = e->peer_label_table; 07942 ast_hashtab_remove_object_via_lookup(tmp->peer_table,e); 07943 ast_hashtab_insert_safe(tmp->peer_table,tmp); 07944 if (e->label) { 07945 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 07946 } 07947 if (tmp->label) { 07948 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 07949 } 07950 07951 ast_hashtab_remove_object_via_lookup(con->root_table, e); 07952 ast_hashtab_insert_safe(con->root_table, tmp); 07953 el->next = tmp; 07954 /* The pattern trie points to this exten; replace the pointer, 07955 and all will be well */ 07956 if (x) { /* if the trie isn't formed yet, don't sweat this */ 07957 if (x->exten) { /* this test for safety purposes */ 07958 x->exten = tmp; /* replace what would become a bad pointer */ 07959 } else { 07960 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 07961 } 07962 } 07963 } else { /* We're the very first extension. */ 07964 struct match_char *x = add_exten_to_pattern_tree(con, e, 1); 07965 ast_hashtab_remove_object_via_lookup(con->root_table, e); 07966 ast_hashtab_insert_safe(con->root_table, tmp); 07967 tmp->peer_table = e->peer_table; 07968 tmp->peer_label_table = e->peer_label_table; 07969 ast_hashtab_remove_object_via_lookup(tmp->peer_table, e); 07970 ast_hashtab_insert_safe(tmp->peer_table, tmp); 07971 if (e->label) { 07972 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e); 07973 } 07974 if (tmp->label) { 07975 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 07976 } 07977 07978 ast_hashtab_remove_object_via_lookup(con->root_table, e); 07979 ast_hashtab_insert_safe(con->root_table, tmp); 07980 con->root = tmp; 07981 /* The pattern trie points to this exten; replace the pointer, 07982 and all will be well */ 07983 if (x) { /* if the trie isn't formed yet; no problem */ 07984 if (x->exten) { /* this test for safety purposes */ 07985 x->exten = tmp; /* replace what would become a bad pointer */ 07986 } else { 07987 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n"); 07988 } 07989 } 07990 } 07991 if (tmp->priority == PRIORITY_HINT) 07992 ast_change_hint(e,tmp); 07993 /* Destroy the old one */ 07994 if (e->datad) 07995 e->datad(e->data); 07996 ast_free(e); 07997 } else { /* Slip ourselves in just before e */ 07998 tmp->peer = e; 07999 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 08000 if (ep) { /* Easy enough, we're just in the peer list */ 08001 if (tmp->label) { 08002 ast_hashtab_insert_safe(eh->peer_label_table, tmp); 08003 } 08004 ast_hashtab_insert_safe(eh->peer_table, tmp); 08005 ep->peer = tmp; 08006 } else { /* we are the first in some peer list, so link in the ext list */ 08007 tmp->peer_table = e->peer_table; 08008 tmp->peer_label_table = e->peer_label_table; 08009 e->peer_table = 0; 08010 e->peer_label_table = 0; 08011 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08012 if (tmp->label) { 08013 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08014 } 08015 ast_hashtab_remove_object_via_lookup(con->root_table, e); 08016 ast_hashtab_insert_safe(con->root_table, tmp); 08017 if (el) 08018 el->next = tmp; /* in the middle... */ 08019 else 08020 con->root = tmp; /* ... or at the head */ 08021 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 08022 } 08023 /* And immediately return success. */ 08024 if (tmp->priority == PRIORITY_HINT) { 08025 if (lockhints) { 08026 ast_add_hint(tmp); 08027 } else { 08028 ast_add_hint(tmp); 08029 } 08030 } 08031 } 08032 return 0; 08033 }
static struct match_char * already_in_tree | ( | struct match_char * | current, | |
char * | pat, | |||
int | is_pattern | |||
) | [static] |
Definition at line 1846 of file pbx.c.
References match_char::alt_char, match_char::is_pattern, and match_char::x.
Referenced by add_exten_to_pattern_tree().
01847 { 01848 struct match_char *t; 01849 01850 if (!current) { 01851 return 0; 01852 } 01853 01854 for (t = current; t; t = t->alt_char) { 01855 if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */ 01856 return t; 01857 } 01858 } 01859 01860 return 0; 01861 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5067 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05068 { 05069 return countcalls; 05070 }
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 7739 of file pbx.c.
References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_extension_state(), ast_extension_state_add(), handle_cli_dialplan_add_extension(), park_add_hints(), register_exten(), register_peer_exten(), and RegisterExtension().
07742 { 07743 int ret = -1; 07744 struct ast_context *c = find_context_locked(context); 07745 07746 if (c) { 07747 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 07748 application, data, datad, registrar); 07749 ast_unlock_contexts(); 07750 } 07751 07752 return ret; 07753 }
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 8060 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by add_extensions(), ast_add_extension(), build_parkinglot(), context_merge(), load_module(), manage_parkinglot(), park_call_full(), and pbx_load_users().
08064 { 08065 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1); 08066 }
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 8073 of file pbx.c.
References add_exten_to_pattern_tree(), add_pri(), ast_exten::app, ast_add_hint(), ast_calloc, ast_channel_release(), ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_hashtab_create(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, ast_channel::context, ast_exten::data, ast_exten::datad, el, errno, ext_cmp(), ext_strncpy(), ast_exten::exten, ast_channel::exten, hashtab_compare_exten_labels(), hashtab_compare_exten_numbers(), hashtab_compare_extens(), hashtab_hash_extens(), hashtab_hash_labels(), hashtab_hash_priority(), ast_exten::label, LOG_ERROR, ast_exten::matchcid, ast_context::name, ast_exten::next, option_debug, ast_exten::parent, ast_context::pattern_tree, pbx_substitute_variables_helper(), ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, ast_context::root, ast_context::root_table, ast_exten::stuff, and VAR_BUF_SIZE.
Referenced by ast_add_extension2(), and ast_add_extension_nolock().
08077 { 08078 /* 08079 * Sort extensions (or patterns) according to the rules indicated above. 08080 * These are implemented by the function ext_cmp()). 08081 * All priorities for the same ext/pattern/cid are kept in a list, 08082 * using the 'peer' field as a link field.. 08083 */ 08084 struct ast_exten *tmp, *tmp2, *e, *el = NULL; 08085 int res; 08086 int length; 08087 char *p; 08088 char expand_buf[VAR_BUF_SIZE]; 08089 struct ast_exten dummy_exten = {0}; 08090 char dummy_name[1024]; 08091 08092 if (ast_strlen_zero(extension)) { 08093 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", 08094 con->name); 08095 return -1; 08096 } 08097 08098 /* If we are adding a hint evalulate in variables and global variables */ 08099 if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) { 08100 struct ast_channel *c = ast_dummy_channel_alloc(); 08101 ast_copy_string(c->exten, extension, sizeof(c->exten)); 08102 ast_copy_string(c->context, con->name, sizeof(c->context)); 08103 08104 pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf)); 08105 application = expand_buf; 08106 ast_channel_release(c); 08107 } 08108 08109 length = sizeof(struct ast_exten); 08110 length += strlen(extension) + 1; 08111 length += strlen(application) + 1; 08112 if (label) 08113 length += strlen(label) + 1; 08114 if (callerid) 08115 length += strlen(callerid) + 1; 08116 else 08117 length ++; /* just the '\0' */ 08118 08119 /* Be optimistic: Build the extension structure first */ 08120 if (!(tmp = ast_calloc(1, length))) 08121 return -1; 08122 08123 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */ 08124 label = 0; 08125 08126 /* use p as dst in assignments, as the fields are const char * */ 08127 p = tmp->stuff; 08128 if (label) { 08129 tmp->label = p; 08130 strcpy(p, label); 08131 p += strlen(label) + 1; 08132 } 08133 tmp->exten = p; 08134 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 08135 tmp->priority = priority; 08136 tmp->cidmatch = p; /* but use p for assignments below */ 08137 08138 /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */ 08139 if (callerid) { 08140 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 08141 tmp->matchcid = 1; 08142 } else { 08143 *p++ = '\0'; 08144 tmp->matchcid = 0; 08145 } 08146 tmp->app = p; 08147 strcpy(p, application); 08148 tmp->parent = con; 08149 tmp->data = data; 08150 tmp->datad = datad; 08151 tmp->registrar = registrar; 08152 08153 if (lockconts) { 08154 ast_wrlock_context(con); 08155 } 08156 08157 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding 08158 an extension, and the trie exists, then we need to incrementally add this pattern to it. */ 08159 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 08160 dummy_exten.exten = dummy_name; 08161 dummy_exten.matchcid = 0; 08162 dummy_exten.cidmatch = 0; 08163 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten); 08164 if (!tmp2) { 08165 /* hmmm, not in the trie; */ 08166 add_exten_to_pattern_tree(con, tmp, 0); 08167 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */ 08168 } 08169 } 08170 res = 0; /* some compilers will think it is uninitialized otherwise */ 08171 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 08172 res = ext_cmp(e->exten, tmp->exten); 08173 if (res == 0) { /* extension match, now look at cidmatch */ 08174 if (!e->matchcid && !tmp->matchcid) 08175 res = 0; 08176 else if (tmp->matchcid && !e->matchcid) 08177 res = 1; 08178 else if (e->matchcid && !tmp->matchcid) 08179 res = -1; 08180 else 08181 res = ext_cmp(e->cidmatch, tmp->cidmatch); 08182 } 08183 if (res >= 0) 08184 break; 08185 } 08186 if (e && res == 0) { /* exact match, insert in the pri chain */ 08187 res = add_pri(con, tmp, el, e, replace); 08188 if (lockconts) { 08189 ast_unlock_context(con); 08190 } 08191 if (res < 0) { 08192 errno = EEXIST; /* XXX do we care ? */ 08193 return 0; /* XXX should we return -1 maybe ? */ 08194 } 08195 } else { 08196 /* 08197 * not an exact match, this is the first entry with this pattern, 08198 * so insert in the main list right before 'e' (if any) 08199 */ 08200 tmp->next = e; 08201 if (el) { /* there is another exten already in this context */ 08202 el->next = tmp; 08203 tmp->peer_table = ast_hashtab_create(13, 08204 hashtab_compare_exten_numbers, 08205 ast_hashtab_resize_java, 08206 ast_hashtab_newsize_java, 08207 hashtab_hash_priority, 08208 0); 08209 tmp->peer_label_table = ast_hashtab_create(7, 08210 hashtab_compare_exten_labels, 08211 ast_hashtab_resize_java, 08212 ast_hashtab_newsize_java, 08213 hashtab_hash_labels, 08214 0); 08215 if (label) { 08216 ast_hashtab_insert_safe(tmp->peer_label_table, tmp); 08217 } 08218 ast_hashtab_insert_safe(tmp->peer_table, tmp); 08219 } else { /* this is the first exten in this context */ 08220 if (!con->root_table) 08221 con->root_table = ast_hashtab_create(27, 08222 hashtab_compare_extens, 08223 ast_hashtab_resize_java, 08224 ast_hashtab_newsize_java, 08225 hashtab_hash_extens, 08226 0); 08227 con->root = tmp; 08228 con->root->peer_table = ast_hashtab_create(13, 08229 hashtab_compare_exten_numbers, 08230 ast_hashtab_resize_java, 08231 ast_hashtab_newsize_java, 08232 hashtab_hash_priority, 08233 0); 08234 con->root->peer_label_table = ast_hashtab_create(7, 08235 hashtab_compare_exten_labels, 08236 ast_hashtab_resize_java, 08237 ast_hashtab_newsize_java, 08238 hashtab_hash_labels, 08239 0); 08240 if (label) { 08241 ast_hashtab_insert_safe(con->root->peer_label_table, tmp); 08242 } 08243 ast_hashtab_insert_safe(con->root->peer_table, tmp); 08244 08245 } 08246 ast_hashtab_insert_safe(con->root_table, tmp); 08247 if (lockconts) { 08248 ast_unlock_context(con); 08249 } 08250 if (tmp->priority == PRIORITY_HINT) { 08251 if (lockhints) { 08252 ast_add_hint(tmp); 08253 } else { 08254 ast_add_hint(tmp); 08255 } 08256 } 08257 } 08258 if (option_debug) { 08259 if (tmp->matchcid) { 08260 ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n", 08261 tmp->exten, tmp->priority, tmp->cidmatch, con->name, con); 08262 } else { 08263 ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n", 08264 tmp->exten, tmp->priority, con->name, con); 08265 } 08266 } 08267 08268 if (tmp->matchcid) { 08269 ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n", 08270 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 08271 } else { 08272 ast_verb(3, "Added extension '%s' priority %d to %s\n", 08273 tmp->exten, tmp->priority, con->name); 08274 } 08275 08276 return 0; 08277 }
static int ast_add_extension_nolock | ( | const char * | context, | |
int | replace, | |||
const char * | extension, | |||
int | priority, | |||
const char * | label, | |||
const char * | callerid, | |||
const char * | application, | |||
void * | data, | |||
void(*)(void *) | datad, | |||
const char * | registrar | |||
) | [static] |
Definition at line 7720 of file pbx.c.
References ast_add_extension2_lockopt(), and find_context().
Referenced by ast_merge_contexts_and_delete().
07723 { 07724 int ret = -1; 07725 struct ast_context *c = find_context(context); 07726 07727 if (c) { 07728 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid, 07729 application, data, datad, registrar, 0, 0); 07730 } 07731 07732 return ret; 07733 }
static int ast_add_hint | ( | struct ast_exten * | e | ) | [static] |
Add hint to hint list, check initial extension state.
Definition at line 4452 of file pbx.c.
References ao2_alloc, ao2_container_alloc, ao2_find, ao2_link, ao2_ref, ast_debug, ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), hint_id_cmp(), and hints.
Referenced by ast_add_extension2_lockopt().
04453 { 04454 struct ast_hint *hint; 04455 04456 if (!e) { 04457 return -1; 04458 } 04459 04460 /* Search if hint exists, do nothing */ 04461 hint = ao2_find(hints, e, 0); 04462 if (hint) { 04463 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 04464 ao2_ref(hint, -1); 04465 return -1; 04466 } 04467 04468 ast_debug(2, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 04469 04470 if (!(hint = ao2_alloc(sizeof(*hint), NULL))) { 04471 return -1; 04472 } 04473 if (!(hint->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp))) { 04474 return -1; 04475 } 04476 04477 /* Initialize and insert new item at the top */ 04478 hint->exten = e; 04479 hint->laststate = ast_extension_state2(e); 04480 04481 ao2_link(hints, hint); 04482 04483 ao2_ref(hint, -1); 04484 04485 return 0; 04486 }
int ast_async_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Set the channel to next execute the specified dialplan location.
Definition at line 7778 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, ast_channel::context, ast_channel::exten, ast_channel::linkedid, 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_dtmf(), handle_request_bye(), handle_request_refer(), my_handle_dtmf(), pbx_parseable_goto(), process_ast_dsp(), process_sdp(), sip_read(), and socket_process().
07779 { 07780 int res = 0; 07781 07782 ast_channel_lock(chan); 07783 07784 if (chan->pbx) { /* This channel is currently in the PBX */ 07785 ast_explicit_goto(chan, context, exten, priority + 1); 07786 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 07787 } else { 07788 /* In order to do it when the channel doesn't really exist within 07789 the PBX, we have to make a new channel, masquerade, and start the PBX 07790 at the new location */ 07791 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->linkedid, chan->amaflags, "AsyncGoto/%s", chan->name); 07792 if (!tmpchan) { 07793 res = -1; 07794 } else { 07795 if (chan->cdr) { 07796 ast_cdr_discard(tmpchan->cdr); 07797 tmpchan->cdr = ast_cdr_dup(chan->cdr); /* share the love */ 07798 } 07799 /* Make formats okay */ 07800 tmpchan->readformat = chan->readformat; 07801 tmpchan->writeformat = chan->writeformat; 07802 /* Setup proper location */ 07803 ast_explicit_goto(tmpchan, 07804 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 07805 07806 /* Masquerade into temp channel */ 07807 if (ast_channel_masquerade(tmpchan, chan)) { 07808 /* Failed to set up the masquerade. It's probably chan_local 07809 * in the middle of optimizing itself out. Sad. :( */ 07810 ast_hangup(tmpchan); 07811 tmpchan = NULL; 07812 res = -1; 07813 } else { 07814 /* it may appear odd to unlock chan here since the masquerade is on 07815 * tmpchan, but no channel locks should be held when doing a masquerade 07816 * since a masquerade requires a lock on the channels ao2 container. */ 07817 ast_channel_unlock(chan); 07818 ast_do_masquerade(tmpchan); 07819 ast_channel_lock(chan); 07820 /* Start the PBX going on our stolen channel */ 07821 if (ast_pbx_start(tmpchan)) { 07822 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 07823 ast_hangup(tmpchan); 07824 res = -1; 07825 } 07826 } 07827 } 07828 } 07829 ast_channel_unlock(chan); 07830 return res; 07831 }
int ast_async_goto_by_name | ( | const char * | channame, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Set the channel to next execute the specified dialplan location.
Definition at line 7833 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
07834 { 07835 struct ast_channel *chan; 07836 int res = -1; 07837 07838 if ((chan = ast_channel_get_by_name(channame))) { 07839 res = ast_async_goto(chan, context, exten, priority); 07840 chan = ast_channel_unref(chan); 07841 } 07842 07843 return res; 07844 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10132 of file pbx.c.
References __ast_goto_if_exists().
10133 { 10134 return __ast_goto_if_exists(chan, context, exten, priority, 1); 10135 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10197 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
10198 { 10199 return pbx_parseable_goto(chan, goto_string, 1); 10200 }
int ast_build_timing | ( | struct ast_timing * | i, | |
const char * | info | |||
) |
Construct a timing bitmap, for use in time-based conditionals.
i | Pointer to an ast_timing structure. | |
info | Standard string containing a timerange, weekday range, monthday range, and month range, as well as an optional timezone. |
Returns | 1 on success or 0 on failure. |
Definition at line 7369 of file pbx.c.
References ast_strdup, ast_strdupa, ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, strsep(), and ast_timing::timezone.
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
07370 { 07371 char *info_save, *info; 07372 int j, num_fields, last_sep = -1; 07373 07374 /* Check for empty just in case */ 07375 if (ast_strlen_zero(info_in)) { 07376 return 0; 07377 } 07378 07379 /* make a copy just in case we were passed a static string */ 07380 info_save = info = ast_strdupa(info_in); 07381 07382 /* count the number of fields in the timespec */ 07383 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 07384 if (info[j] == ',') { 07385 last_sep = j; 07386 num_fields++; 07387 } 07388 } 07389 07390 /* save the timezone, if it is specified */ 07391 if (num_fields == 5) { 07392 i->timezone = ast_strdup(info + last_sep + 1); 07393 } else { 07394 i->timezone = NULL; 07395 } 07396 07397 /* Assume everything except time */ 07398 i->monthmask = 0xfff; /* 12 bits */ 07399 i->daymask = 0x7fffffffU; /* 31 bits */ 07400 i->dowmask = 0x7f; /* 7 bits */ 07401 /* on each call, use strsep() to move info to the next argument */ 07402 get_timerange(i, strsep(&info, "|,")); 07403 if (info) 07404 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 07405 if (info) 07406 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 07407 if (info) 07408 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 07409 return 1; 07410 }
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 4596 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), analog_ss_thread(), background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), handle_link_data(), handle_link_phone_dtmf(), leave_voicemail(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), skinny_ss(), and valid_exit().
04597 { 04598 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 04599 }
Change hint for an extension.
Definition at line 4489 of file pbx.c.
References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_hint::exten, and hints.
04490 { 04491 struct ast_hint *hint; 04492 04493 hint = ao2_find(hints, oe, 0); 04494 04495 if (!hint) { 04496 return -1; 04497 } 04498 04499 ao2_lock(hint); 04500 hint->exten = ne; 04501 ao2_unlock(hint); 04502 ao2_ref(hint, -1); 04503 04504 return 0; 04505 }
int ast_check_timing | ( | const struct ast_timing * | i | ) |
Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified.
i | Pointer to an ast_timing structure. |
Returns | 1, if the time matches or 0, if the current time falls outside of the specified range. |
Definition at line 7412 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
07413 { 07414 return ast_check_timing2(i, ast_tvnow()); 07415 }
int ast_check_timing2 | ( | const struct ast_timing * | i, | |
const struct timeval | tv | |||
) |
Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified.
i | Pointer to an ast_timing structure. | |
tv | Specified time |
Returns | 1, if the time matches or 0, if the time falls outside of the specified range. |
Definition at line 7417 of file pbx.c.
References ast_localtime(), ast_log(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, ast_timing::monthmask, ast_timing::timezone, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and ast_tm::tm_wday.
Referenced by ast_check_timing(), and pbx_builtin_gotoiftime().
07418 { 07419 struct ast_tm tm; 07420 07421 ast_localtime(&tv, &tm, i->timezone); 07422 07423 /* If it's not the right month, return */ 07424 if (!(i->monthmask & (1 << tm.tm_mon))) 07425 return 0; 07426 07427 /* If it's not that time of the month.... */ 07428 /* Warning, tm_mday has range 1..31! */ 07429 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 07430 return 0; 07431 07432 /* If it's not the right day of the week */ 07433 if (!(i->dowmask & (1 << tm.tm_wday))) 07434 return 0; 07435 07436 /* Sanity check the hour just to be safe */ 07437 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 07438 ast_log(LOG_WARNING, "Insane time...\n"); 07439 return 0; 07440 } 07441 07442 /* Now the tough part, we calculate if it fits 07443 in the right time based on min/hour */ 07444 if (!(i->minmask[tm.tm_hour * 2 + (tm.tm_min >= 30 ? 1 : 0)] & (1 << (tm.tm_min >= 30 ? tm.tm_min - 30 : tm.tm_min)))) 07445 return 0; 07446 07447 /* If we got this far, then we're good */ 07448 return 1; 07449 }
char* ast_complete_applications | ( | const char * | line, | |
const char * | word, | |||
int | state | |||
) |
Command completion for the list of installed applications.
This can be called from a CLI command completion function that wants to complete from the list of available applications.
Definition at line 10202 of file pbx.c.
References app, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, and ast_app::list.
Referenced by handle_orig(), and handle_show_application().
10203 { 10204 struct ast_app *app = NULL; 10205 int which = 0; 10206 char *ret = NULL; 10207 size_t wordlen = strlen(word); 10208 10209 AST_RWLIST_RDLOCK(&apps); 10210 AST_RWLIST_TRAVERSE(&apps, app, list) { 10211 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 10212 ret = ast_strdup(app->name); 10213 break; 10214 } 10215 } 10216 AST_RWLIST_UNLOCK(&apps); 10217 10218 return ret; 10219 }
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 7651 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
07652 { 07653 int ret = -1; 07654 struct ast_context *c = find_context_locked(context); 07655 07656 if (c) { 07657 ret = ast_context_add_ignorepat2(c, value, registrar); 07658 ast_unlock_contexts(); 07659 } 07660 return ret; 07661 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | value, | |||
const char * | registrar | |||
) |
Definition at line 7663 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(), and context_merge_incls_swits_igps_other_registrars().
07664 { 07665 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 07666 int length; 07667 char *pattern; 07668 length = sizeof(struct ast_ignorepat); 07669 length += strlen(value) + 1; 07670 if (!(ignorepat = ast_calloc(1, length))) 07671 return -1; 07672 /* The cast to char * is because we need to write the initial value. 07673 * The field is not supposed to be modified otherwise. Also, gcc 4.2 07674 * sees the cast as dereferencing a type-punned pointer and warns about 07675 * it. This is the workaround (we're telling gcc, yes, that's really 07676 * what we wanted to do). 07677 */ 07678 pattern = (char *) ignorepat->pattern; 07679 strcpy(pattern, value); 07680 ignorepat->next = NULL; 07681 ignorepat->registrar = registrar; 07682 ast_wrlock_context(con); 07683 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 07684 ignorepatl = ignorepatc; 07685 if (!strcasecmp(ignorepatc->pattern, value)) { 07686 /* Already there */ 07687 ast_unlock_context(con); 07688 errno = EEXIST; 07689 return -1; 07690 } 07691 } 07692 if (ignorepatl) 07693 ignorepatl->next = ignorepat; 07694 else 07695 con->ignorepats = ignorepat; 07696 ast_unlock_context(con); 07697 return 0; 07698 07699 }
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 7198 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
07199 { 07200 int ret = -1; 07201 struct ast_context *c = find_context_locked(context); 07202 07203 if (c) { 07204 ret = ast_context_add_include2(c, include, registrar); 07205 ast_unlock_contexts(); 07206 } 07207 return ret; 07208 }
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 7466 of file pbx.c.
References ast_build_timing(), ast_calloc, ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), errno, ast_include::hastime, ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, ast_include::rname, ast_include::stuff, and ast_include::timing.
Referenced by ast_context_add_include(), and context_merge_incls_swits_igps_other_registrars().
07468 { 07469 struct ast_include *new_include; 07470 char *c; 07471 struct ast_include *i, *il = NULL; /* include, include_last */ 07472 int length; 07473 char *p; 07474 07475 length = sizeof(struct ast_include); 07476 length += 2 * (strlen(value) + 1); 07477 07478 /* allocate new include structure ... */ 07479 if (!(new_include = ast_calloc(1, length))) 07480 return -1; 07481 /* Fill in this structure. Use 'p' for assignments, as the fields 07482 * in the structure are 'const char *' 07483 */ 07484 p = new_include->stuff; 07485 new_include->name = p; 07486 strcpy(p, value); 07487 p += strlen(value) + 1; 07488 new_include->rname = p; 07489 strcpy(p, value); 07490 /* Strip off timing info, and process if it is there */ 07491 if ( (c = strchr(p, ',')) ) { 07492 *c++ = '\0'; 07493 new_include->hastime = ast_build_timing(&(new_include->timing), c); 07494 } 07495 new_include->next = NULL; 07496 new_include->registrar = registrar; 07497 07498 ast_wrlock_context(con); 07499 07500 /* ... go to last include and check if context is already included too... */ 07501 for (i = con->includes; i; i = i->next) { 07502 if (!strcasecmp(i->name, new_include->name)) { 07503 ast_destroy_timing(&(new_include->timing)); 07504 ast_free(new_include); 07505 ast_unlock_context(con); 07506 errno = EEXIST; 07507 return -1; 07508 } 07509 il = i; 07510 } 07511 07512 /* ... include new context into context list, unlock, return */ 07513 if (il) 07514 il->next = new_include; 07515 else 07516 con->includes = new_include; 07517 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 07518 07519 ast_unlock_context(con); 07520 07521 return 0; 07522 }
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 7529 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
07530 { 07531 int ret = -1; 07532 struct ast_context *c = find_context_locked(context); 07533 07534 if (c) { /* found, add switch to this context */ 07535 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 07536 ast_unlock_contexts(); 07537 } 07538 return ret; 07539 }
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 7548 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(), and lua_register_switches().
07550 { 07551 struct ast_sw *new_sw; 07552 struct ast_sw *i; 07553 int length; 07554 char *p; 07555 07556 length = sizeof(struct ast_sw); 07557 length += strlen(value) + 1; 07558 if (data) 07559 length += strlen(data); 07560 length++; 07561 07562 /* allocate new sw structure ... */ 07563 if (!(new_sw = ast_calloc(1, length))) 07564 return -1; 07565 /* ... fill in this structure ... */ 07566 p = new_sw->stuff; 07567 new_sw->name = p; 07568 strcpy(new_sw->name, value); 07569 p += strlen(value) + 1; 07570 new_sw->data = p; 07571 if (data) { 07572 strcpy(new_sw->data, data); 07573 p += strlen(data) + 1; 07574 } else { 07575 strcpy(new_sw->data, ""); 07576 p++; 07577 } 07578 new_sw->eval = eval; 07579 new_sw->registrar = registrar; 07580 07581 /* ... try to lock this context ... */ 07582 ast_wrlock_context(con); 07583 07584 /* ... go to last sw and check if context is already swd too... */ 07585 AST_LIST_TRAVERSE(&con->alts, i, list) { 07586 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 07587 ast_free(new_sw); 07588 ast_unlock_context(con); 07589 errno = EEXIST; 07590 return -1; 07591 } 07592 } 07593 07594 /* ... sw new context into context list, unlock, return */ 07595 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 07596 07597 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 07598 07599 ast_unlock_context(con); 07600 07601 return 0; 07602 }
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 8872 of file pbx.c.
References __ast_context_destroy(), ast_unlock_contexts(), ast_wrlock_contexts(), contexts, and contexts_table.
Referenced by __unload_module(), cleanup_stale_contexts(), parkinglot_destroy(), sla_destroy(), and unload_module().
08873 { 08874 ast_wrlock_contexts(); 08875 __ast_context_destroy(contexts, contexts_table, con,registrar); 08876 ast_unlock_contexts(); 08877 }
struct ast_context* ast_context_find | ( | const char * | name | ) |
Find a context.
name | name of the context to find |
Definition at line 2511 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::name, and fake_context::name.
Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_ignore_pattern(), cleanup_stale_contexts(), isexten_function_read(), manage_parkinglot(), park_exec_full(), parkinglot_destroy(), register_exten(), register_peer_exten(), unload_module(), and unregister_exten().
02512 { 02513 struct ast_context *tmp = NULL; 02514 struct fake_context item; 02515 02516 ast_copy_string(item.name, name, sizeof(item.name)); 02517 02518 ast_rdlock_contexts(); 02519 if( contexts_table ) { 02520 tmp = ast_hashtab_lookup(contexts_table,&item); 02521 } else { 02522 while ( (tmp = ast_walk_contexts(tmp)) ) { 02523 if (!name || !strcasecmp(name, tmp->name)) { 02524 break; 02525 } 02526 } 02527 } 02528 ast_unlock_contexts(); 02529 return tmp; 02530 }
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 6843 of file pbx.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_insert_immediate(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_mutex_init, ast_rdlock_contexts(), ast_rwlock_init, ast_strdup, ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), contexts, contexts_table, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, ast_context::macrolock, ast_context::name, fake_context::name, name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by build_parkinglot(), config_parse_variables(), context_merge(), load_module(), lua_register_switches(), manage_parkinglot(), park_call_full(), pbx_load_config(), pbx_load_users(), and set_config().
06844 { 06845 struct ast_context *tmp, **local_contexts; 06846 struct fake_context search; 06847 int length = sizeof(struct ast_context) + strlen(name) + 1; 06848 06849 if (!contexts_table) { 06850 contexts_table = ast_hashtab_create(17, 06851 ast_hashtab_compare_contexts, 06852 ast_hashtab_resize_java, 06853 ast_hashtab_newsize_java, 06854 ast_hashtab_hash_contexts, 06855 0); 06856 } 06857 06858 ast_copy_string(search.name, name, sizeof(search.name)); 06859 if (!extcontexts) { 06860 ast_rdlock_contexts(); 06861 local_contexts = &contexts; 06862 tmp = ast_hashtab_lookup(contexts_table, &search); 06863 ast_unlock_contexts(); 06864 if (tmp) { 06865 tmp->refcount++; 06866 return tmp; 06867 } 06868 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 06869 local_contexts = extcontexts; 06870 tmp = ast_hashtab_lookup(exttable, &search); 06871 if (tmp) { 06872 tmp->refcount++; 06873 return tmp; 06874 } 06875 } 06876 06877 if ((tmp = ast_calloc(1, length))) { 06878 ast_rwlock_init(&tmp->lock); 06879 ast_mutex_init(&tmp->macrolock); 06880 strcpy(tmp->name, name); 06881 tmp->root = NULL; 06882 tmp->root_table = NULL; 06883 tmp->registrar = ast_strdup(registrar); 06884 tmp->includes = NULL; 06885 tmp->ignorepats = NULL; 06886 tmp->refcount = 1; 06887 } else { 06888 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 06889 return NULL; 06890 } 06891 06892 if (!extcontexts) { 06893 ast_wrlock_contexts(); 06894 tmp->next = *local_contexts; 06895 *local_contexts = tmp; 06896 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 06897 ast_unlock_contexts(); 06898 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 06899 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 06900 } else { 06901 tmp->next = *local_contexts; 06902 if (exttable) 06903 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 06904 06905 *local_contexts = tmp; 06906 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 06907 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 06908 } 06909 return tmp; 06910 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 5447 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_mutex_lock, ast_rdlock_contexts(), ast_unlock_contexts(), contexts_table, ast_context::macrolock, and fake_context::name.
Referenced by _macro_exec().
05448 { 05449 struct ast_context *c = NULL; 05450 int ret = -1; 05451 struct fake_context item; 05452 05453 ast_rdlock_contexts(); 05454 05455 ast_copy_string(item.name, context, sizeof(item.name)); 05456 05457 c = ast_hashtab_lookup(contexts_table,&item); 05458 if (c) 05459 ret = 0; 05460 ast_unlock_contexts(); 05461 05462 /* if we found context, lock macrolock */ 05463 if (ret == 0) { 05464 ret = ast_mutex_lock(&c->macrolock); 05465 } 05466 05467 return ret; 05468 }
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) | |
registrar | registrar of the extension |
0 | on success | |
-1 | on failure |
Definition at line 5255 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), unregister_exten(), and UnregisterExtension().
05256 { 05257 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 05258 }
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 5282 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by manage_parkinglot(), park_exec_full(), and unload_module().
05283 { 05284 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 05285 }
int ast_context_remove_extension_callerid | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | callerid, | |||
int | matchcallerid, | |||
const char * | registrar | |||
) |
Definition at line 5260 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().
05261 { 05262 int ret = -1; /* default error return */ 05263 struct ast_context *c = find_context_locked(context); 05264 05265 if (c) { /* ... remove extension ... */ 05266 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1); 05267 ast_unlock_contexts(); 05268 } 05269 return ret; 05270 }
int ast_context_remove_extension_callerid2 | ( | struct ast_context * | con, | |
const char * | extension, | |||
int | priority, | |||
const char * | callerid, | |||
int | matchcallerid, | |||
const char * | registrar, | |||
int | already_locked | |||
) |
Definition at line 5287 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(), ast_exten::exten, exten, ast_exten::label, LOG_ERROR, 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().
05288 { 05289 struct ast_exten *exten, *prev_exten = NULL; 05290 struct ast_exten *peer; 05291 struct ast_exten ex, *exten2, *exten3; 05292 char dummy_name[1024]; 05293 struct ast_exten *previous_peer = NULL; 05294 struct ast_exten *next_peer = NULL; 05295 int found = 0; 05296 05297 if (!already_locked) 05298 ast_wrlock_context(con); 05299 05300 /* Handle this is in the new world */ 05301 05302 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 05303 * peers, not just those matching the callerid. */ 05304 #ifdef NEED_DEBUG 05305 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 05306 #endif 05307 #ifdef CONTEXT_DEBUG 05308 check_contexts(__FILE__, __LINE__); 05309 #endif 05310 /* find this particular extension */ 05311 ex.exten = dummy_name; 05312 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 05313 ex.cidmatch = callerid; 05314 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 05315 exten = ast_hashtab_lookup(con->root_table, &ex); 05316 if (exten) { 05317 if (priority == 0) { 05318 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05319 if (!exten2) 05320 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); 05321 if (con->pattern_tree) { 05322 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05323 05324 if (x->exten) { /* this test for safety purposes */ 05325 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05326 x->exten = 0; /* get rid of what will become a bad pointer */ 05327 } else { 05328 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 05329 } 05330 } 05331 } else { 05332 ex.priority = priority; 05333 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 05334 if (exten2) { 05335 05336 if (exten2->label) { /* if this exten has a label, remove that, too */ 05337 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 05338 if (!exten3) 05339 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); 05340 } 05341 05342 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 05343 if (!exten3) 05344 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); 05345 if (exten2 == exten && exten2->peer) { 05346 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05347 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 05348 } 05349 if (ast_hashtab_size(exten->peer_table) == 0) { 05350 /* well, if the last priority of an exten is to be removed, 05351 then, the extension is removed, too! */ 05352 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 05353 if (!exten3) 05354 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 05355 if (con->pattern_tree) { 05356 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05357 if (x->exten) { /* this test for safety purposes */ 05358 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05359 x->exten = 0; /* get rid of what will become a bad pointer */ 05360 } 05361 } 05362 } 05363 } else { 05364 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 05365 priority, exten->exten, con->name); 05366 } 05367 } 05368 } else { 05369 /* hmmm? this exten is not in this pattern tree? */ 05370 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 05371 extension, con->name); 05372 } 05373 #ifdef NEED_DEBUG 05374 if (con->pattern_tree) { 05375 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 05376 log_match_char_tree(con->pattern_tree, " "); 05377 } 05378 #endif 05379 05380 /* scan the extension list to find first matching extension-registrar */ 05381 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 05382 if (!strcmp(exten->exten, extension) && 05383 (!registrar || !strcmp(exten->registrar, registrar)) && 05384 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 05385 break; 05386 } 05387 if (!exten) { 05388 /* we can't find right extension */ 05389 if (!already_locked) 05390 ast_unlock_context(con); 05391 return -1; 05392 } 05393 05394 /* scan the priority list to remove extension with exten->priority == priority */ 05395 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 05396 peer && !strcmp(peer->exten, extension) && (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(peer->cidmatch) && !strcmp(peer->cidmatch,callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(peer->cidmatch))); 05397 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 05398 if ((priority == 0 || peer->priority == priority) && 05399 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 05400 (!registrar || !strcmp(peer->registrar, registrar) )) { 05401 found = 1; 05402 05403 /* we are first priority extension? */ 05404 if (!previous_peer) { 05405 /* 05406 * We are first in the priority chain, so must update the extension chain. 05407 * The next node is either the next priority or the next extension 05408 */ 05409 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 05410 if (peer->peer) { 05411 /* move the peer_table and peer_label_table down to the next peer, if 05412 it is there */ 05413 peer->peer->peer_table = peer->peer_table; 05414 peer->peer->peer_label_table = peer->peer_label_table; 05415 peer->peer_table = NULL; 05416 peer->peer_label_table = NULL; 05417 } 05418 if (!prev_exten) { /* change the root... */ 05419 con->root = next_node; 05420 } else { 05421 prev_exten->next = next_node; /* unlink */ 05422 } 05423 if (peer->peer) { /* update the new head of the pri list */ 05424 peer->peer->next = peer->next; 05425 } 05426 } else { /* easy, we are not first priority in extension */ 05427 previous_peer->peer = peer->peer; 05428 } 05429 05430 /* now, free whole priority extension */ 05431 destroy_exten(peer); 05432 } else { 05433 previous_peer = peer; 05434 } 05435 } 05436 if (!already_locked) 05437 ast_unlock_context(con); 05438 return found ? 0 : -1; 05439 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 7608 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
07609 { 07610 int ret = -1; 07611 struct ast_context *c = find_context_locked(context); 07612 07613 if (c) { 07614 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 07615 ast_unlock_contexts(); 07616 } 07617 return ret; 07618 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 7620 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().
07621 { 07622 struct ast_ignorepat *ip, *ipl = NULL; 07623 07624 ast_wrlock_context(con); 07625 07626 for (ip = con->ignorepats; ip; ip = ip->next) { 07627 if (!strcmp(ip->pattern, ignorepat) && 07628 (!registrar || (registrar == ip->registrar))) { 07629 if (ipl) { 07630 ipl->next = ip->next; 07631 ast_free(ip); 07632 } else { 07633 con->ignorepats = ip->next; 07634 ast_free(ip); 07635 } 07636 ast_unlock_context(con); 07637 return 0; 07638 } 07639 ipl = ip; 07640 } 07641 07642 ast_unlock_context(con); 07643 errno = EINVAL; 07644 return -1; 07645 }
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 5146 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
05147 { 05148 int ret = -1; 05149 struct ast_context *c = find_context_locked(context); 05150 05151 if (c) { 05152 /* found, remove include from this context ... */ 05153 ret = ast_context_remove_include2(c, include, registrar); 05154 ast_unlock_contexts(); 05155 } 05156 return ret; 05157 }
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 5168 of file pbx.c.
References ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, and ast_include::timing.
Referenced by ast_context_remove_include().
05169 { 05170 struct ast_include *i, *pi = NULL; 05171 int ret = -1; 05172 05173 ast_wrlock_context(con); 05174 05175 /* find our include */ 05176 for (i = con->includes; i; pi = i, i = i->next) { 05177 if (!strcmp(i->name, include) && 05178 (!registrar || !strcmp(i->registrar, registrar))) { 05179 /* remove from list */ 05180 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 05181 if (pi) 05182 pi->next = i->next; 05183 else 05184 con->includes = i->next; 05185 /* free include and return */ 05186 ast_destroy_timing(&(i->timing)); 05187 ast_free(i); 05188 ret = 0; 05189 break; 05190 } 05191 } 05192 05193 ast_unlock_context(con); 05194 05195 return ret; 05196 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 5203 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
05204 { 05205 int ret = -1; /* default error return */ 05206 struct ast_context *c = find_context_locked(context); 05207 05208 if (c) { 05209 /* remove switch from this context ... */ 05210 ret = ast_context_remove_switch2(c, sw, data, registrar); 05211 ast_unlock_contexts(); 05212 } 05213 return ret; 05214 }
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 5224 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().
05225 { 05226 struct ast_sw *i; 05227 int ret = -1; 05228 05229 ast_wrlock_context(con); 05230 05231 /* walk switches */ 05232 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 05233 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 05234 (!registrar || !strcmp(i->registrar, registrar))) { 05235 /* found, remove from list */ 05236 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 05237 AST_LIST_REMOVE_CURRENT(list); 05238 ast_free(i); /* free switch and return */ 05239 ret = 0; 05240 break; 05241 } 05242 } 05243 AST_LIST_TRAVERSE_SAFE_END; 05244 05245 ast_unlock_context(con); 05246 05247 return ret; 05248 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 5475 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_mutex_unlock, ast_rdlock_contexts(), ast_unlock_contexts(), contexts_table, ast_context::macrolock, and fake_context::name.
Referenced by _macro_exec().
05476 { 05477 struct ast_context *c = NULL; 05478 int ret = -1; 05479 struct fake_context item; 05480 05481 ast_rdlock_contexts(); 05482 05483 ast_copy_string(item.name, context, sizeof(item.name)); 05484 05485 c = ast_hashtab_lookup(contexts_table,&item); 05486 if (c) 05487 ret = 0; 05488 ast_unlock_contexts(); 05489 05490 /* if we found context, unlock macrolock */ 05491 if (ret == 0) { 05492 ret = ast_mutex_unlock(&c->macrolock); 05493 } 05494 05495 return ret; 05496 }
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 10087 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().
10088 { 10089 struct ast_include *inc = NULL; 10090 int res = 0; 10091 10092 while ( (inc = ast_walk_context_includes(con, inc)) ) { 10093 if (ast_context_find(inc->rname)) 10094 continue; 10095 10096 res = -1; 10097 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 10098 ast_get_context_name(con), inc->rname); 10099 break; 10100 } 10101 10102 return res; 10103 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) |
Definition at line 3324 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_function::name.
Referenced by ast_func_read(), ast_func_read2(), ast_func_write(), config_curl(), destroy_curl(), handle_show_function(), op_func(), realtime_curl(), realtime_multi_curl(), require_curl(), store_curl(), update2_curl(), and update_curl().
03325 { 03326 struct ast_custom_function *acf = NULL; 03327 03328 AST_RWLIST_RDLOCK(&acf_root); 03329 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03330 if (!strcmp(name, acf->name)) 03331 break; 03332 } 03333 AST_RWLIST_UNLOCK(&acf_root); 03334 03335 return acf; 03336 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3338 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, AST_XML_DOC, ast_custom_function::docsrc, and ast_custom_function::name.
Referenced by _unload_module(), load_module(), reload(), and unload_module().
03339 { 03340 struct ast_custom_function *cur; 03341 03342 if (!acf) { 03343 return -1; 03344 } 03345 03346 AST_RWLIST_WRLOCK(&acf_root); 03347 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03348 #ifdef AST_XML_DOCS 03349 if (cur->docsrc == AST_XML_DOC) { 03350 ast_string_field_free_memory(acf); 03351 } 03352 #endif 03353 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03354 } 03355 AST_RWLIST_UNLOCK(&acf_root); 03356 03357 return cur ? 0 : -1; 03358 }
int ast_destroy_timing | ( | struct ast_timing * | i | ) |
Deallocates memory structures associated with a timing bitmap.
i | Pointer to an ast_timing structure. |
0 | success | |
non-zero | failure (number suitable to pass to |
Definition at line 7451 of file pbx.c.
References ast_free, and ast_timing::timezone.
Referenced by ast_context_add_include2(), ast_context_remove_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
07452 { 07453 if (i->timezone) { 07454 ast_free(i->timezone); 07455 i->timezone = NULL; 07456 } 07457 return 0; 07458 }
enum ast_extension_states ast_devstate_to_extenstate | ( | enum ast_device_state | devstate | ) |
Map devstate to an extension state.
[in] | devstate | device state |
Definition at line 4144 of file pbx.c.
References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_TOTAL, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, and AST_EXTENSION_UNAVAILABLE.
Referenced by ast_extension_state2().
04145 { 04146 switch (devstate) { 04147 case AST_DEVICE_ONHOLD: 04148 return AST_EXTENSION_ONHOLD; 04149 case AST_DEVICE_BUSY: 04150 return AST_EXTENSION_BUSY; 04151 case AST_DEVICE_UNKNOWN: 04152 return AST_EXTENSION_NOT_INUSE; 04153 case AST_DEVICE_UNAVAILABLE: 04154 case AST_DEVICE_INVALID: 04155 return AST_EXTENSION_UNAVAILABLE; 04156 case AST_DEVICE_RINGINUSE: 04157 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04158 case AST_DEVICE_RINGING: 04159 return AST_EXTENSION_RINGING; 04160 case AST_DEVICE_INUSE: 04161 return AST_EXTENSION_INUSE; 04162 case AST_DEVICE_NOT_INUSE: 04163 return AST_EXTENSION_NOT_INUSE; 04164 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04165 break; 04166 } 04167 04168 return AST_EXTENSION_NOT_INUSE; 04169 }
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 4581 of file pbx.c.
References E_MATCH, and pbx_extension_helper().
Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), analog_ss_thread(), answer_call(), ast_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dahdi_r2_on_call_offered(), dahdi_r2_on_dnis_digit_received(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmf(), park_space_reserve(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), pri_dchannel(), pri_ss_thread(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), rpt_exec(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), vm_authenticate(), and waitstream_core().
04582 { 04583 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 04584 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 7755 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_FLAG_IN_AUTOLOOP, ast_strlen_zero(), ast_test_flag, ast_channel::context, ast_channel::exten, and ast_channel::priority.
Referenced by __ast_goto_if_exists(), ast_async_goto(), builtin_atxfer(), do_bridge_masquerade(), handle_setpriority(), pbx_parseable_goto(), and return_exec().
07756 { 07757 if (!chan) 07758 return -1; 07759 07760 ast_channel_lock(chan); 07761 07762 if (!ast_strlen_zero(context)) 07763 ast_copy_string(chan->context, context, sizeof(chan->context)); 07764 if (!ast_strlen_zero(exten)) 07765 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07766 if (priority > -1) { 07767 chan->priority = priority; 07768 /* see flag description in channel.h for explanation */ 07769 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 07770 chan->priority--; 07771 } 07772 07773 ast_channel_unlock(chan); 07774 07775 return 0; 07776 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 2488 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().
02489 { 02490 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02491 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02492 return extension_match_core(pattern, data, needmore); 02493 }
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 2290 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02291 { 02292 return ext_cmp(a, b); 02293 }
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 2483 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(), show_dialplan_helper(), and sig_pri_msn_match().
02484 { 02485 return extension_match_core(pattern, data, E_MATCH); 02486 }
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 4207 of file pbx.c.
References ast_exten::app, ast_add_extension(), ast_extension_state2(), ast_free_ptr, ast_hint_extension(), ast_strdup, ast_exten::cidmatch, ast_exten::data, ast_exten::exten, ast_exten::label, ast_exten::matchcid, ast_context::name, ast_exten::parent, ast_exten::priority, and ast_exten::registrar.
Referenced by action_extensionstate(), extstate_read(), get_queue_member_status(), and handle_request_subscribe().
04208 { 04209 struct ast_exten *e; 04210 04211 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04212 return -1; /* No hint, return -1 */ 04213 } 04214 04215 if (e->exten[0] == '_') { 04216 /* Create this hint on-the-fly */ 04217 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04218 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04219 e->registrar); 04220 if (!(e = ast_hint_extension(c, context, exten))) { 04221 /* Improbable, but not impossible */ 04222 return -1; 04223 } 04224 } 04225 04226 return ast_extension_state2(e); /* Check all devices in the hint */ 04227 }
static int ast_extension_state2 | ( | struct ast_exten * | e | ) | [static] |
Check state of extension by using hints.
Definition at line 4172 of file pbx.c.
References ast_device_state(), ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_devstate_to_extenstate(), ast_get_extension_app(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), extensionstate_buf, and strsep().
Referenced by ast_add_hint(), ast_extension_state(), and handle_statechange().
04173 { 04174 struct ast_str *hint = ast_str_thread_get(&extensionstate_buf, 16); 04175 char *cur, *rest; 04176 struct ast_devstate_aggregate agg; 04177 04178 if (!e) 04179 return -1; 04180 04181 ast_devstate_aggregate_init(&agg); 04182 04183 ast_str_set(&hint, 0, "%s", ast_get_extension_app(e)); 04184 04185 rest = ast_str_buffer(hint); /* One or more devices separated with a & character */ 04186 04187 while ( (cur = strsep(&rest, "&")) ) { 04188 ast_devstate_aggregate_add(&agg, ast_device_state(cur)); 04189 } 04190 04191 return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg)); 04192 }
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 4195 of file pbx.c.
References ARRAY_LEN, extension_states, and cfextension_states::text.
Referenced by cb_extensionstate(), handle_request_subscribe(), handle_show_hint(), handle_show_hints(), hints_data_provider_get(), and show_channels_cb().
04196 { 04197 int i; 04198 04199 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04200 if (extension_states[i].extension_state == extension_state) 04201 return extension_states[i].text; 04202 } 04203 return "Unknown"; 04204 }
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 4304 of file pbx.c.
References ao2_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension(), ast_free_ptr, ast_hint_extension(), ast_strdup, ast_hint::callbacks, ast_exten::cidmatch, ast_exten::data, ast_state_cb::data, ast_exten::exten, hints, ast_exten::label, ast_exten::matchcid, ast_context::name, ast_exten::parent, ast_exten::priority, ast_exten::registrar, statecbs, and stateid.
Referenced by __init_manager(), handle_request_subscribe(), load_module(), and skinny_register().
04306 { 04307 struct ast_hint *hint; 04308 struct ast_state_cb *state_cb; 04309 struct ast_exten *e; 04310 04311 /* If there's no context and extension: add callback to statecbs list */ 04312 if (!context && !exten) { 04313 ao2_lock(hints); 04314 04315 state_cb = ao2_find(statecbs, callback, 0); 04316 if (state_cb) { 04317 state_cb->data = data; 04318 ao2_ref(state_cb, -1); 04319 ao2_unlock(hints); 04320 return 0; 04321 } 04322 04323 /* Now insert the callback */ 04324 if (!(state_cb = ao2_alloc(sizeof(*state_cb), NULL))) { 04325 ao2_unlock(hints); 04326 return -1; 04327 } 04328 state_cb->id = 0; 04329 state_cb->callback = callback; 04330 state_cb->data = data; 04331 04332 ao2_link(statecbs, state_cb); 04333 ao2_ref(state_cb, -1); 04334 04335 ao2_unlock(hints); 04336 return 0; 04337 } 04338 04339 if (!context || !exten) 04340 return -1; 04341 04342 /* This callback type is for only one hint, so get the hint */ 04343 e = ast_hint_extension(NULL, context, exten); 04344 if (!e) { 04345 return -1; 04346 } 04347 04348 /* If this is a pattern, dynamically create a new extension for this 04349 * particular match. Note that this will only happen once for each 04350 * individual extension, because the pattern will no longer match first. 04351 */ 04352 if (e->exten[0] == '_') { 04353 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04354 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04355 e->registrar); 04356 e = ast_hint_extension(NULL, context, exten); 04357 if (!e || e->exten[0] == '_') { 04358 return -1; 04359 } 04360 } 04361 04362 /* Find the hint in the list of hints */ 04363 hint = ao2_find(hints, e, 0); 04364 04365 if (!hint) { 04366 return -1; 04367 } 04368 04369 /* Now insert the callback in the callback list */ 04370 if (!(state_cb = ao2_alloc(sizeof(*state_cb), NULL))) { 04371 ao2_ref(hint, -1); 04372 return -1; 04373 } 04374 04375 state_cb->id = stateid++; /* Unique ID for this callback */ 04376 state_cb->callback = callback; /* Pointer to callback routine */ 04377 state_cb->data = data; /* Data for the callback */ 04378 04379 ao2_lock(hint); 04380 ao2_link(hint->callbacks, state_cb); 04381 ao2_ref(state_cb, -1); 04382 ao2_unlock(hint); 04383 04384 ao2_ref(hint, -1); 04385 04386 return state_cb->id; 04387 }
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 4405 of file pbx.c.
References ao2_callback, ao2_find, ao2_lock, ao2_ref, ao2_unlock, find_hint_by_cb_id(), hints, OBJ_UNLINK, and statecbs.
Referenced by dialog_unlink_all(), handle_request_subscribe(), skinny_unregister(), and unload_module().
04406 { 04407 struct ast_state_cb *p_cur = NULL; 04408 int ret = -1; 04409 04410 if (!id && !callback) { 04411 return -1; 04412 } 04413 04414 if (!id) { /* id == 0 is a callback without extension */ 04415 ao2_lock(hints); 04416 p_cur = ao2_find(statecbs, callback, OBJ_UNLINK); 04417 if (p_cur) { 04418 ret = 0; 04419 ao2_ref(p_cur, -1); 04420 } 04421 ao2_unlock(hints); 04422 } else { /* callback with extension, find the callback based on ID */ 04423 struct ast_hint *hint; 04424 04425 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 04426 04427 if (hint) { 04428 ao2_lock(hint); 04429 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 04430 if (p_cur) { 04431 ret = 0; 04432 ao2_ref(p_cur, -1); 04433 } 04434 ao2_unlock(hint); 04435 ao2_ref(hint, -1); 04436 } 04437 } 04438 04439 return ret; 04440 }
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 4586 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().
04587 { 04588 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04589 }
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 4591 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
04592 { 04593 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04594 }
int ast_func_read | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | workspace, | |||
size_t | len | |||
) |
executes a read operation on a function
chan | Channel to execute on | |
function | Data containing the function call string (will be modified) | |
workspace | A pointer to safe memory to use for a return value | |
len | the number of bytes in workspace |
0 | success | |
non-zero | failure |
Definition at line 3482 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_copy_string(), ast_custom_function_find(), ast_free, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_size(), ast_strdupa, ast_module_user::chan, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, and str.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
03483 { 03484 char *copy = ast_strdupa(function); 03485 char *args = func_args(copy); 03486 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03487 int res; 03488 struct ast_module_user *u = NULL; 03489 03490 if (acfptr == NULL) { 03491 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03492 } else if (!acfptr->read && !acfptr->read2) { 03493 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03494 } else if (acfptr->read) { 03495 if (acfptr->mod) { 03496 u = __ast_module_user_add(acfptr->mod, chan); 03497 } 03498 res = acfptr->read(chan, copy, args, workspace, len); 03499 if (acfptr->mod && u) { 03500 __ast_module_user_remove(acfptr->mod, u); 03501 } 03502 return res; 03503 } else { 03504 struct ast_str *str = ast_str_create(16); 03505 if (acfptr->mod) { 03506 u = __ast_module_user_add(acfptr->mod, chan); 03507 } 03508 res = acfptr->read2(chan, copy, args, &str, 0); 03509 if (acfptr->mod && u) { 03510 __ast_module_user_remove(acfptr->mod, u); 03511 } 03512 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 03513 ast_free(str); 03514 return res; 03515 } 03516 return -1; 03517 }
int ast_func_read2 | ( | struct ast_channel * | chan, | |
const char * | function, | |||
struct ast_str ** | str, | |||
ssize_t | maxlen | |||
) |
executes a read operation on a function
chan | Channel to execute on | |
function | Data containing the function call string (will be modified) | |
str | A dynamic string buffer into which to place the result. | |
maxlen | <0 if the dynamic buffer should not grow; >0 if the dynamic buffer should be limited to that number of bytes; 0 if the dynamic buffer has no upper limit |
0 | success | |
non-zero | failure |
Definition at line 3519 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_str_buffer(), ast_str_make_space(), ast_str_reset(), ast_str_size(), ast_strdupa, ast_module_user::chan, copy(), func_args(), LOG_ERROR, maxsize, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, str, and VAR_BUF_SIZE.
Referenced by append_channel_vars(), and ast_str_substitute_variables_full().
03520 { 03521 char *copy = ast_strdupa(function); 03522 char *args = func_args(copy); 03523 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03524 int res; 03525 struct ast_module_user *u = NULL; 03526 03527 if (acfptr == NULL) { 03528 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03529 } else if (!acfptr->read && !acfptr->read2) { 03530 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03531 } else { 03532 if (acfptr->mod) { 03533 u = __ast_module_user_add(acfptr->mod, chan); 03534 } 03535 if (acfptr->read2) { 03536 /* ast_str enabled */ 03537 ast_str_reset(*str); 03538 res = acfptr->read2(chan, copy, args, str, maxlen); 03539 } else { 03540 /* Legacy function pointer, allocate buffer for result */ 03541 int maxsize = ast_str_size(*str); 03542 if (maxlen > -1) { 03543 if (maxlen == 0) { 03544 if (acfptr->read_max) { 03545 maxsize = acfptr->read_max; 03546 } else { 03547 maxsize = VAR_BUF_SIZE; 03548 } 03549 } else { 03550 maxsize = maxlen; 03551 } 03552 ast_str_make_space(str, maxsize); 03553 } 03554 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 03555 } 03556 if (acfptr->mod && u) { 03557 __ast_module_user_remove(acfptr->mod, u); 03558 } 03559 return res; 03560 } 03561 return -1; 03562 }
int ast_func_write | ( | struct ast_channel * | chan, | |
const char * | function, | |||
const char * | value | |||
) |
executes a write operation on a function
chan | Channel to execute on | |
function | Data containing the function call string (will be modified) | |
value | A value parameter to pass for writing |
0 | success | |
non-zero | failure |
Definition at line 3564 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_strdupa, ast_module_user::chan, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.
Referenced by conf_run(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
03565 { 03566 char *copy = ast_strdupa(function); 03567 char *args = func_args(copy); 03568 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03569 03570 if (acfptr == NULL) 03571 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03572 else if (!acfptr->write) 03573 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 03574 else { 03575 int res; 03576 struct ast_module_user *u = NULL; 03577 if (acfptr->mod) 03578 u = __ast_module_user_add(acfptr->mod, chan); 03579 res = acfptr->write(chan, copy, args, value); 03580 if (acfptr->mod && u) 03581 __ast_module_user_remove(acfptr->mod, u); 03582 return res; 03583 } 03584 03585 return -1; 03586 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 9939 of file pbx.c.
References ast_context::name.
Referenced by _macro_exec(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_include2(), ast_context_remove_switch2(), 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_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), hints_data_provider_get(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
09940 { 09941 return con ? con->name : NULL; 09942 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 9977 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
09978 { 09979 return c ? c->registrar : NULL; 09980 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 10007 of file pbx.c.
References ast_exten::app.
Referenced by _macro_exec(), ast_add_hint(), ast_extension_state2(), ast_get_hint(), ast_parking_ext_valid(), ast_str_get_hint(), find_matching_endwhile(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), and print_ext().
10008 { 10009 return e ? e->app : NULL; 10010 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 10012 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), ast_str_get_hint(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().
10013 { 10014 return e ? e->data : NULL; 10015 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 10002 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10003 { 10004 return e ? e->cidmatch : NULL; 10005 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) |
Definition at line 9944 of file pbx.c.
References exten.
Referenced by handle_show_hint(), handle_show_hints(), and hints_data_provider_get().
const char* ast_get_extension_label | ( | struct ast_exten * | exten | ) |
Definition at line 9954 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 9997 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
09998 { 09999 return e ? e->matchcid : 0; 10000 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 9949 of file pbx.c.
References exten.
Referenced by ast_add_hint(), complete_core_show_hint(), complete_dialplan_remove_extension(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), hint_hash(), hints_data_provider_get(), manager_show_dialplan_helper(), and show_dialplan_helper().
int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 9969 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 9982 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09983 { 09984 return e ? e->registrar : NULL; 09985 }
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.
hint | buffer for hint | |
hintsize | size of hint buffer, in bytes | |
name | buffer for name portion of hint | |
namesize | size of name buffer | |
c | Channel from which to return the hint. This is only important when the hint or name contains an expression to be expanded. | |
context | which context to look in | |
exten | which extension to search for |
Definition at line 4543 of file pbx.c.
References ast_copy_string(), ast_get_extension_app(), ast_get_extension_app_data(), and ast_hint_extension().
Referenced by action_extensionstate(), get_cid_name(), get_destination(), hint_read(), manager_state_cb(), skinny_extensionstate_cb(), and state_notify_build_xml().
04544 { 04545 struct ast_exten *e = ast_hint_extension(c, context, exten); 04546 04547 if (e) { 04548 if (hint) 04549 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 04550 if (name) { 04551 const char *tmp = ast_get_extension_app_data(e); 04552 if (tmp) 04553 ast_copy_string(name, tmp, namesize); 04554 } 04555 return -1; 04556 } 04557 return 0; 04558 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 9964 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().
09965 { 09966 return ip ? ip->pattern : NULL; 09967 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 9992 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().
09993 { 09994 return ip ? ip->registrar : NULL; 09995 }
const char* ast_get_include_name | ( | struct ast_include * | inc | ) |
Definition at line 9959 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().
09960 { 09961 return inc ? inc->name : NULL; 09962 }
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 9987 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().
09988 { 09989 return i ? i->registrar : NULL; 09990 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 10022 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().
10023 { 10024 return sw ? sw->data : NULL; 10025 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 10027 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
10028 { 10029 return sw->eval; 10030 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 10017 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().
10018 { 10019 return sw ? sw->name : NULL; 10020 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 10032 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().
10033 { 10034 return sw ? sw->registrar : NULL; 10035 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10127 of file pbx.c.
References __ast_goto_if_exists().
Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), dial_exec_full(), goto_exten(), onedigit_goto(), priority_jump(), select_entry(), valid_exit(), vm_execmain(), and vmauthenticate().
10128 { 10129 return __ast_goto_if_exists(chan, context, exten, priority, 0); 10130 }
int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
const void * | ah_b | |||
) |
hashtable functions for contexts
Definition at line 1046 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01047 { 01048 const struct ast_context *ac = ah_a; 01049 const struct ast_context *bc = ah_b; 01050 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01051 return 1; 01052 /* assume context names are registered in a string table! */ 01053 return strcmp(ac->name, bc->name); 01054 }
unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1089 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().
01090 { 01091 const struct ast_context *ac = obj; 01092 return ast_hashtab_hash_string(ac->name); 01093 }
static struct ast_exten* ast_hint_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) | [static] |
Definition at line 4135 of file pbx.c.
References ast_hint_extension_nolock(), ast_rdlock_contexts(), and ast_unlock_contexts().
Referenced by ast_extension_state(), ast_extension_state_add(), ast_get_hint(), and ast_str_get_hint().
04136 { 04137 struct ast_exten *e; 04138 ast_rdlock_contexts(); 04139 e = ast_hint_extension_nolock(c, context, exten); 04140 ast_unlock_contexts(); 04141 return e; 04142 }
static struct ast_exten* ast_hint_extension_nolock | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten | |||
) | [static] |
Find hint for given extension in context.
Definition at line 4129 of file pbx.c.
References E_MATCH, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.
Referenced by ast_hint_extension(), and ast_merge_contexts_and_delete().
04130 { 04131 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */ 04132 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH); 04133 }
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 7701 of file pbx.c.
References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_enbloc_call_message(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), pri_ss_thread(), and skinny_ss().
07702 { 07703 struct ast_context *con = ast_context_find(context); 07704 if (con) { 07705 struct ast_ignorepat *pat; 07706 for (pat = con->ignorepats; pat; pat = pat->next) { 07707 if (ast_extension_match(pat->pattern, pattern)) 07708 return 1; 07709 } 07710 } 07711 07712 return 0; 07713 }
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 4601 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_app_dtget(), collect_digits(), dahdi_r2_on_dnis_digit_received(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_link_data(), handle_link_phone_dtmf(), local_dtmf_helper(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), pri_ss_thread(), readexten_exec(), and skinny_ss().
04602 { 04603 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 04604 }
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 7042 of file pbx.c.
References __ast_internal_context_destroy(), ao2_callback, ao2_container_count(), ao2_find, AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr, ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_rdlock_contexts(), ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_state_cb::callback, ast_hint::callbacks, context_merge(), contexts, contexts_table, ast_state_cb::data, E_MATCH, store_hint::exten, ast_exten::exten, ast_hint::exten, hints, ast_hint::laststate, store_hint::laststate, store_hint::list, ast_context::name, ast_context::next, store_hint::next, OBJ_UNLINK, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
07043 { 07044 double ft; 07045 struct ast_context *tmp, *oldcontextslist; 07046 struct ast_hashtab *oldtable; 07047 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 07048 struct store_hint *this; 07049 struct ast_hint *hint; 07050 struct ast_exten *exten; 07051 int length; 07052 struct ast_state_cb *thiscb; 07053 struct ast_hashtab_iter *iter; 07054 struct ao2_iterator i; 07055 07056 /* it is very important that this function hold the hint list lock _and_ the conlock 07057 during its operation; not only do we need to ensure that the list of contexts 07058 and extensions does not change, but also that no hint callbacks (watchers) are 07059 added or removed during the merge/delete process 07060 07061 in addition, the locks _must_ be taken in this order, because there are already 07062 other code paths that use this order 07063 */ 07064 07065 struct timeval begintime, writelocktime, endlocktime, enddeltime; 07066 07067 begintime = ast_tvnow(); 07068 ast_rdlock_contexts(); 07069 iter = ast_hashtab_start_traversal(contexts_table); 07070 while ((tmp = ast_hashtab_next(iter))) { 07071 context_merge(extcontexts, exttable, tmp, registrar); 07072 } 07073 ast_hashtab_end_traversal(iter); 07074 07075 ao2_lock(hints); 07076 writelocktime = ast_tvnow(); 07077 07078 /* preserve all watchers for hints */ 07079 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07080 for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) { 07081 if (ao2_container_count(hint->callbacks)) { 07082 07083 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 07084 if (!(this = ast_calloc(1, length))) { 07085 continue; 07086 } 07087 ao2_lock(hint); 07088 07089 if (hint->exten == NULL) { 07090 ao2_unlock(hint); 07091 continue; 07092 } 07093 07094 /* this removes all the callbacks from the hint into 'this'. */ 07095 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 07096 AST_LIST_INSERT_TAIL(&this->callbacks, thiscb, entry); 07097 /* We intentionally do not unref thiscb to account for the non-ao2 reference in this->callbacks */ 07098 } 07099 07100 this->laststate = hint->laststate; 07101 this->context = this->data; 07102 strcpy(this->data, hint->exten->parent->name); 07103 this->exten = this->data + strlen(this->context) + 1; 07104 strcpy(this->exten, hint->exten->exten); 07105 ao2_unlock(hint); 07106 AST_LIST_INSERT_HEAD(&store, this, list); 07107 } 07108 } 07109 07110 /* save the old table and list */ 07111 oldtable = contexts_table; 07112 oldcontextslist = contexts; 07113 07114 /* move in the new table and list */ 07115 contexts_table = exttable; 07116 contexts = *extcontexts; 07117 07118 /* restore the watchers for hints that can be found; notify those that 07119 cannot be restored 07120 */ 07121 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 07122 struct pbx_find_info q = { .stacklen = 0 }; 07123 exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH); 07124 /* If this is a pattern, dynamically create a new extension for this 07125 * particular match. Note that this will only happen once for each 07126 * individual extension, because the pattern will no longer match first. 07127 */ 07128 if (exten && exten->exten[0] == '_') { 07129 ast_add_extension_nolock(exten->parent->name, 0, this->exten, PRIORITY_HINT, NULL, 07130 0, exten->app, ast_strdup(exten->data), ast_free_ptr, exten->registrar); 07131 /* rwlocks are not recursive locks */ 07132 exten = ast_hint_extension_nolock(NULL, this->context, this->exten); 07133 } 07134 07135 /* Find the hint in the list of hints */ 07136 hint = ao2_find(hints, exten, 0); 07137 if (!exten || !hint) { 07138 /* this hint has been removed, notify the watchers */ 07139 while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) { 07140 thiscb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, thiscb->data); 07141 ao2_ref(thiscb, -1); /* Ref that we added when putting into this->callbacks */ 07142 } 07143 } else { 07144 ao2_lock(hint); 07145 while ((thiscb = AST_LIST_REMOVE_HEAD(&this->callbacks, entry))) { 07146 ao2_link(hint->callbacks, thiscb); 07147 ao2_ref(thiscb, -1); /* Ref that we added when putting into this->callbacks */ 07148 } 07149 hint->laststate = this->laststate; 07150 ao2_unlock(hint); 07151 } 07152 ast_free(this); 07153 if (hint) { 07154 ao2_ref(hint, -1); 07155 } 07156 } 07157 07158 ao2_unlock(hints); 07159 ast_unlock_contexts(); 07160 endlocktime = ast_tvnow(); 07161 07162 /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk 07163 is now freely using the new stuff instead */ 07164 07165 ast_hashtab_destroy(oldtable, NULL); 07166 07167 for (tmp = oldcontextslist; tmp; ) { 07168 struct ast_context *next; /* next starting point */ 07169 next = tmp->next; 07170 __ast_internal_context_destroy(tmp); 07171 tmp = next; 07172 } 07173 enddeltime = ast_tvnow(); 07174 07175 ft = ast_tvdiff_us(writelocktime, begintime); 07176 ft /= 1000000.0; 07177 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 07178 07179 ft = ast_tvdiff_us(endlocktime, writelocktime); 07180 ft /= 1000000.0; 07181 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 07182 07183 ft = ast_tvdiff_us(enddeltime, endlocktime); 07184 ft /= 1000000.0; 07185 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 07186 07187 ft = ast_tvdiff_us(enddeltime, begintime); 07188 ft /= 1000000.0; 07189 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 07190 return; 07191 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10192 of file pbx.c.
References pbx_parseable_goto().
Referenced by _while_exec(), check_goto_on_transfer(), dial_exec_full(), gosub_exec(), ivr_dispatch(), parkandannounce_exec(), pbx_builtin_goto(), and while_continue_exec().
10193 { 10194 return pbx_parseable_goto(chan, goto_string, 0); 10195 }
int ast_pbx_init | ( | void | ) |
Provided by pbx.c
Definition at line 10250 of file pbx.c.
References ao2_container_alloc, hint_cmp(), hint_hash(), hints, statecbs, and statecbs_cmp().
Referenced by main().
10251 { 10252 hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp); 10253 statecbs = ao2_container_alloc(HASH_EXTENHINT_SIZE, NULL, statecbs_cmp); 10254 10255 return (hints && statecbs) ? 0 : -1; 10256 }
int ast_pbx_outgoing_app | ( | const char * | type, | |
format_t | 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 8544 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(), async_stat::chan, errno, LOG_WARNING, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_app(), and originate_exec().
08545 { 08546 struct ast_channel *chan; 08547 struct app_tmp *tmp; 08548 int res = -1, cdr_res = -1; 08549 struct outgoing_helper oh; 08550 08551 memset(&oh, 0, sizeof(oh)); 08552 oh.vars = vars; 08553 oh.account = account; 08554 08555 if (locked_channel) 08556 *locked_channel = NULL; 08557 if (ast_strlen_zero(app)) { 08558 res = -1; 08559 goto outgoing_app_cleanup; 08560 } 08561 if (synchronous) { 08562 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08563 if (chan) { 08564 ast_set_variables(chan, vars); 08565 if (account) 08566 ast_cdr_setaccount(chan, account); 08567 if (chan->_state == AST_STATE_UP) { 08568 res = 0; 08569 ast_verb(4, "Channel %s was answered.\n", chan->name); 08570 tmp = ast_calloc(1, sizeof(*tmp)); 08571 if (!tmp) 08572 res = -1; 08573 else { 08574 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 08575 if (appdata) 08576 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 08577 tmp->chan = chan; 08578 if (synchronous > 1) { 08579 if (locked_channel) 08580 ast_channel_unlock(chan); 08581 ast_pbx_run_app(tmp); 08582 } else { 08583 if (locked_channel) 08584 ast_channel_lock(chan); 08585 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 08586 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 08587 ast_free(tmp); 08588 if (locked_channel) 08589 ast_channel_unlock(chan); 08590 ast_hangup(chan); 08591 res = -1; 08592 } else { 08593 if (locked_channel) 08594 *locked_channel = chan; 08595 } 08596 } 08597 } 08598 } else { 08599 ast_verb(4, "Channel %s was never answered.\n", chan->name); 08600 if (chan->cdr) { /* update the cdr */ 08601 /* here we update the status of the call, which sould be busy. 08602 * if that fails then we set the status to failed */ 08603 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 08604 ast_cdr_failed(chan->cdr); 08605 } 08606 ast_hangup(chan); 08607 } 08608 } 08609 08610 if (res < 0) { /* the call failed for some reason */ 08611 if (*reason == 0) { /* if the call failed (not busy or no answer) 08612 * update the cdr with the failed message */ 08613 cdr_res = ast_pbx_outgoing_cdr_failed(); 08614 if (cdr_res != 0) { 08615 res = cdr_res; 08616 goto outgoing_app_cleanup; 08617 } 08618 } 08619 } 08620 08621 } else { 08622 struct async_stat *as; 08623 if (!(as = ast_calloc(1, sizeof(*as)))) { 08624 res = -1; 08625 goto outgoing_app_cleanup; 08626 } 08627 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08628 if (!chan) { 08629 ast_free(as); 08630 res = -1; 08631 goto outgoing_app_cleanup; 08632 } 08633 as->chan = chan; 08634 ast_copy_string(as->app, app, sizeof(as->app)); 08635 if (appdata) 08636 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 08637 as->timeout = timeout; 08638 ast_set_variables(chan, vars); 08639 if (account) 08640 ast_cdr_setaccount(chan, account); 08641 /* Start a new thread, and get something handling this channel. */ 08642 if (locked_channel) 08643 ast_channel_lock(chan); 08644 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 08645 ast_log(LOG_WARNING, "Failed to start async wait\n"); 08646 ast_free(as); 08647 if (locked_channel) 08648 ast_channel_unlock(chan); 08649 ast_hangup(chan); 08650 res = -1; 08651 goto outgoing_app_cleanup; 08652 } else { 08653 if (locked_channel) 08654 *locked_channel = chan; 08655 } 08656 res = 0; 08657 } 08658 outgoing_app_cleanup: 08659 ast_variables_destroy(vars); 08660 return res; 08661 }
static int ast_pbx_outgoing_cdr_failed | ( | void | ) | [static] |
Function to post an empty cdr after a spool call fails.
Definition at line 8351 of file pbx.c.
References ast_cdr_alloc(), ast_cdr_detach(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_start(), ast_channel_release(), ast_dummy_channel_alloc(), and ast_channel::cdr.
Referenced by ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
08352 { 08353 /* allocate a channel */ 08354 struct ast_channel *chan = ast_dummy_channel_alloc(); 08355 08356 if (!chan) 08357 return -1; /* failure */ 08358 08359 chan->cdr = ast_cdr_alloc(); 08360 if (!chan->cdr) { 08361 /* allocation of the cdr failed */ 08362 chan = ast_channel_release(chan); /* free the channel */ 08363 return -1; /* return failure */ 08364 } 08365 08366 /* allocation of the cdr was successful */ 08367 ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ 08368 ast_cdr_start(chan->cdr); /* record the start and stop time */ 08369 ast_cdr_end(chan->cdr); 08370 ast_cdr_failed(chan->cdr); /* set the status to failed */ 08371 ast_cdr_detach(chan->cdr); /* post and free the record */ 08372 chan->cdr = NULL; 08373 chan = ast_channel_release(chan); /* free the channel */ 08374 08375 return 0; /* success */ 08376 }
int ast_pbx_outgoing_exten | ( | const char * | type, | |
format_t | 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 8378 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, outgoing_helper::cid_name, outgoing_helper::cid_num, ast_channel::context, outgoing_helper::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(), orig_exten(), and originate_exec().
08379 { 08380 struct ast_channel *chan; 08381 struct async_stat *as; 08382 int res = -1, cdr_res = -1; 08383 struct outgoing_helper oh; 08384 08385 if (synchronous) { 08386 oh.context = context; 08387 oh.exten = exten; 08388 oh.priority = priority; 08389 oh.cid_num = cid_num; 08390 oh.cid_name = cid_name; 08391 oh.account = account; 08392 oh.vars = vars; 08393 oh.parent_channel = NULL; 08394 08395 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08396 if (channel) { 08397 *channel = chan; 08398 if (chan) 08399 ast_channel_lock(chan); 08400 } 08401 if (chan) { 08402 if (chan->_state == AST_STATE_UP) { 08403 res = 0; 08404 ast_verb(4, "Channel %s was answered.\n", chan->name); 08405 08406 if (synchronous > 1) { 08407 if (channel) 08408 ast_channel_unlock(chan); 08409 if (ast_pbx_run(chan)) { 08410 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08411 if (channel) 08412 *channel = NULL; 08413 ast_hangup(chan); 08414 chan = NULL; 08415 res = -1; 08416 } 08417 } else { 08418 if (ast_pbx_start(chan)) { 08419 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 08420 if (channel) { 08421 *channel = NULL; 08422 ast_channel_unlock(chan); 08423 } 08424 ast_hangup(chan); 08425 res = -1; 08426 } 08427 chan = NULL; 08428 } 08429 } else { 08430 ast_verb(4, "Channel %s was never answered.\n", chan->name); 08431 08432 if (chan->cdr) { /* update the cdr */ 08433 /* here we update the status of the call, which sould be busy. 08434 * if that fails then we set the status to failed */ 08435 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 08436 ast_cdr_failed(chan->cdr); 08437 } 08438 08439 if (channel) { 08440 *channel = NULL; 08441 ast_channel_unlock(chan); 08442 } 08443 ast_hangup(chan); 08444 chan = NULL; 08445 } 08446 } 08447 08448 if (res < 0) { /* the call failed for some reason */ 08449 if (*reason == 0) { /* if the call failed (not busy or no answer) 08450 * update the cdr with the failed message */ 08451 cdr_res = ast_pbx_outgoing_cdr_failed(); 08452 if (cdr_res != 0) { 08453 res = cdr_res; 08454 goto outgoing_exten_cleanup; 08455 } 08456 } 08457 08458 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 08459 /* check if "failed" exists */ 08460 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 08461 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 08462 if (chan) { 08463 char failed_reason[4] = ""; 08464 if (!ast_strlen_zero(context)) 08465 ast_copy_string(chan->context, context, sizeof(chan->context)); 08466 set_ext_pri(chan, "failed", 1); 08467 ast_set_variables(chan, vars); 08468 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 08469 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 08470 if (account) 08471 ast_cdr_setaccount(chan, account); 08472 if (ast_pbx_run(chan)) { 08473 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08474 ast_hangup(chan); 08475 } 08476 chan = NULL; 08477 } 08478 } 08479 } 08480 } else { 08481 if (!(as = ast_calloc(1, sizeof(*as)))) { 08482 res = -1; 08483 goto outgoing_exten_cleanup; 08484 } 08485 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 08486 if (channel) { 08487 *channel = chan; 08488 if (chan) 08489 ast_channel_lock(chan); 08490 } 08491 if (!chan) { 08492 ast_free(as); 08493 res = -1; 08494 goto outgoing_exten_cleanup; 08495 } 08496 as->chan = chan; 08497 ast_copy_string(as->context, context, sizeof(as->context)); 08498 set_ext_pri(as->chan, exten, priority); 08499 as->timeout = timeout; 08500 ast_set_variables(chan, vars); 08501 if (account) 08502 ast_cdr_setaccount(chan, account); 08503 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 08504 ast_log(LOG_WARNING, "Failed to start async wait\n"); 08505 ast_free(as); 08506 if (channel) { 08507 *channel = NULL; 08508 ast_channel_unlock(chan); 08509 } 08510 ast_hangup(chan); 08511 res = -1; 08512 goto outgoing_exten_cleanup; 08513 } 08514 res = 0; 08515 } 08516 outgoing_exten_cleanup: 08517 ast_variables_destroy(vars); 08518 return res; 08519 }
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 5062 of file pbx.c.
References ast_pbx_run_args().
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_pbx_outgoing_exten(), async_wait(), do_idle_thread(), do_notify(), mgcp_ss(), pri_ss_thread(), skinny_newcall(), and unistim_ss().
05063 { 05064 return ast_pbx_run_args(c, NULL); 05065 }
static void* ast_pbx_run_app | ( | void * | data | ) | [static] |
run the application and free the descriptor once done
Definition at line 8529 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().
08530 { 08531 struct app_tmp *tmp = data; 08532 struct ast_app *app; 08533 app = pbx_findapp(tmp->app); 08534 if (app) { 08535 ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 08536 pbx_exec(tmp->chan, app, tmp->data); 08537 } else 08538 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 08539 ast_hangup(tmp->chan); 08540 ast_free(tmp); 08541 return NULL; 08542 }
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 5047 of file pbx.c.
References __ast_pbx_run(), args, 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().
05048 { 05049 enum ast_pbx_result res = AST_PBX_SUCCESS; 05050 05051 if (increase_call_count(c)) { 05052 return AST_PBX_CALL_LIMIT; 05053 } 05054 05055 res = __ast_pbx_run(c, args); 05056 05057 decrease_call_count(); 05058 05059 return res; 05060 }
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 5025 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_iax2_new(), ast_pbx_outgoing_exten(), bridge_call_thread(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), generic_recall(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), manage_parkinglot(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), rpt_call(), sip_new(), skinny_new(), unistim_new(), and usbradio_new().
05026 { 05027 pthread_t t; 05028 05029 if (!c) { 05030 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05031 return AST_PBX_FAILED; 05032 } 05033 05034 if (increase_call_count(c)) 05035 return AST_PBX_CALL_LIMIT; 05036 05037 /* Start a new thread, and get something handling this channel. */ 05038 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05039 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05040 decrease_call_count(); 05041 return AST_PBX_FAILED; 05042 } 05043 05044 return AST_PBX_SUCCESS; 05045 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5072 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05073 { 05074 return totalcalls; 05075 }
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 9926 of file pbx.c.
References ast_rwlock_rdlock, and ast_context::lock.
Referenced by _macro_exec(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_cli_dialplan_save(), lookup_c_ip(), lookup_ci(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
09927 { 09928 return ast_rwlock_rdlock(&con->lock); 09929 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 9908 of file pbx.c.
References ast_mutex_lock, 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(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
09909 { 09910 return ast_mutex_lock(&conlock); 09911 }
int ast_register_application2 | ( | const char * | app, | |
int(*)(struct ast_channel *, const char *) | 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 5499 of file pbx.c.
References ast_app::arguments, ast_calloc, ast_free, ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_verb, AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), COLOR_BRCYAN, ast_app::docsrc, ast_app::execute, ast_app::list, LOG_WARNING, ast_app::module, ast_app::name, ast_app::seealso, ast_app::syntax, and term_color().
Referenced by ast_cc_init(), ast_features_init(), and load_pbx().
05500 { 05501 struct ast_app *tmp, *cur = NULL; 05502 char tmps[80]; 05503 int length, res; 05504 #ifdef AST_XML_DOCS 05505 char *tmpxml; 05506 #endif 05507 05508 AST_RWLIST_WRLOCK(&apps); 05509 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 05510 if (!(res = strcasecmp(app, tmp->name))) { 05511 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 05512 AST_RWLIST_UNLOCK(&apps); 05513 return -1; 05514 } else if (res < 0) 05515 break; 05516 } 05517 05518 length = sizeof(*tmp) + strlen(app) + 1; 05519 05520 if (!(tmp = ast_calloc(1, length))) { 05521 AST_RWLIST_UNLOCK(&apps); 05522 return -1; 05523 } 05524 05525 if (ast_string_field_init(tmp, 128)) { 05526 AST_RWLIST_UNLOCK(&apps); 05527 ast_free(tmp); 05528 return -1; 05529 } 05530 05531 #ifdef AST_XML_DOCS 05532 /* Try to lookup the docs in our XML documentation database */ 05533 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 05534 /* load synopsis */ 05535 tmpxml = ast_xmldoc_build_synopsis("application", app); 05536 ast_string_field_set(tmp, synopsis, tmpxml); 05537 ast_free(tmpxml); 05538 05539 /* load description */ 05540 tmpxml = ast_xmldoc_build_description("application", app); 05541 ast_string_field_set(tmp, description, tmpxml); 05542 ast_free(tmpxml); 05543 05544 /* load syntax */ 05545 tmpxml = ast_xmldoc_build_syntax("application", app); 05546 ast_string_field_set(tmp, syntax, tmpxml); 05547 ast_free(tmpxml); 05548 05549 /* load arguments */ 05550 tmpxml = ast_xmldoc_build_arguments("application", app); 05551 ast_string_field_set(tmp, arguments, tmpxml); 05552 ast_free(tmpxml); 05553 05554 /* load seealso */ 05555 tmpxml = ast_xmldoc_build_seealso("application", app); 05556 ast_string_field_set(tmp, seealso, tmpxml); 05557 ast_free(tmpxml); 05558 tmp->docsrc = AST_XML_DOC; 05559 } else { 05560 #endif 05561 ast_string_field_set(tmp, synopsis, synopsis); 05562 ast_string_field_set(tmp, description, description); 05563 #ifdef AST_XML_DOCS 05564 tmp->docsrc = AST_STATIC_DOC; 05565 } 05566 #endif 05567 05568 strcpy(tmp->name, app); 05569 tmp->execute = execute; 05570 tmp->module = mod; 05571 05572 /* Store in alphabetical order */ 05573 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 05574 if (strcasecmp(tmp->name, cur->name) < 0) { 05575 AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list); 05576 break; 05577 } 05578 } 05579 AST_RWLIST_TRAVERSE_SAFE_END; 05580 if (!cur) 05581 AST_RWLIST_INSERT_TAIL(&apps, tmp, list); 05582 05583 ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 05584 05585 AST_RWLIST_UNLOCK(&apps); 05586 05587 return 0; 05588 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
0 | success | |
non-zero | failure |
Definition at line 5594 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().
05595 { 05596 struct ast_switch *tmp; 05597 05598 AST_RWLIST_WRLOCK(&switches); 05599 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 05600 if (!strcasecmp(tmp->name, sw->name)) { 05601 AST_RWLIST_UNLOCK(&switches); 05602 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 05603 return -1; 05604 } 05605 } 05606 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 05607 AST_RWLIST_UNLOCK(&switches); 05608 05609 return 0; 05610 }
static int ast_remove_hint | ( | struct ast_exten * | e | ) | [static] |
Remove hint from extension.
Definition at line 4508 of file pbx.c.
References ao2_callback, ao2_find, ao2_lock, ao2_ref, ao2_unlink, ao2_unlock, AST_EXTENSION_DEACTIVATED, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_exten::exten, ast_hint::exten, hints, ast_context::name, OBJ_UNLINK, and ast_exten::parent.
Referenced by destroy_exten().
04509 { 04510 /* Cleanup the Notifys if hint is removed */ 04511 struct ast_hint *hint; 04512 struct ast_state_cb *state_cb; 04513 04514 if (!e) { 04515 return -1; 04516 } 04517 04518 hint = ao2_find(hints, e, 0); 04519 04520 if (!hint) { 04521 return -1; 04522 } 04523 ao2_lock(hint); 04524 04525 while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 04526 /* Notify with -1 and remove all callbacks */ 04527 state_cb->callback(hint->exten->parent->name, hint->exten->exten, 04528 AST_EXTENSION_DEACTIVATED, state_cb->data); 04529 ao2_ref(state_cb, -1); 04530 } 04531 04532 hint->exten = NULL; 04533 ao2_unlink(hints, hint); 04534 ao2_ref(hint->callbacks, -1); 04535 ao2_unlock(hint); 04536 ao2_ref(hint, -1); 04537 04538 return 0; 04539 }
int ast_spawn_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | callerid, | |||
int * | found, | |||
int | combined_find_spawn | |||
) |
Launch a new extension (i.e. new stack).
c | not important | |
context | which context to generate the extension within | |
exten | new extension to add | |
priority | priority of new extension | |
callerid | callerid of extension | |
found | ||
combined_find_spawn | This adds a new extension to the asterisk extension list. |
0 | on success | |
-1 | on failure. |
Definition at line 4606 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().
04607 { 04608 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 04609 }
int ast_str_get_hint | ( | struct ast_str ** | hint, | |
ssize_t | hintsize, | |||
struct ast_str ** | name, | |||
ssize_t | namesize, | |||
struct ast_channel * | c, | |||
const char * | context, | |||
const char * | exten | |||
) |
If an extension hint exists, return non-zero.
hint | buffer for hint | |
hintsize | Maximum size of hint buffer (<0 to prevent growth, >0 to limit growth to that number of bytes, or 0 for unlimited growth) | |
name | buffer for name portion of hint | |
namesize | Maximum size of name buffer (<0 to prevent growth, >0 to limit growth to that number of bytes, or 0 for unlimited growth) | |
c | Channel from which to return the hint. This is only important when the hint or name contains an expression to be expanded. | |
context | which context to look in | |
exten | which extension to search for |
Definition at line 4561 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), ast_str_set(), and fake_context::name.
Referenced by ast_str_retrieve_variable().
04562 { 04563 struct ast_exten *e = ast_hint_extension(c, context, exten); 04564 04565 if (!e) { 04566 return 0; 04567 } 04568 04569 if (hint) { 04570 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 04571 } 04572 if (name) { 04573 const char *tmp = ast_get_extension_app_data(e); 04574 if (tmp) { 04575 ast_str_set(name, namesize, "%s", tmp); 04576 } 04577 } 04578 return -1; 04579 }
const char* ast_str_retrieve_variable | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct ast_channel * | chan, | |||
struct varshead * | headp, | |||
const char * | var | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
chan | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
headp | If no channel is specified, a channel list from which to extract variable values | |
var | Variable name to retrieve. |
Definition at line 2986 of file pbx.c.
References ast_party_caller::ani2, ARRAY_LEN, ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_debug, ast_eid_default, ast_eid_to_str(), AST_LIST_TRAVERSE, ast_party_id_presentation(), ast_rwlock_rdlock, ast_rwlock_unlock, ast_str_buffer(), ast_str_get_hint(), ast_str_set(), ast_str_substring(), ast_strdupa, ast_var_name(), ast_var_value(), ast_channel::caller, ast_channel::context, ast_channel::dialed, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_party_caller::id, ast_channel::name, ast_party_id::number, parse_variable_name(), ast_party_number::plan, ast_channel::priority, str, ast_party_dialed::transit_network_select, and ast_channel::uniqueid.
Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().
02987 { 02988 const char not_found = '\0'; 02989 char *tmpvar; 02990 const char *ret; 02991 const char *s; /* the result */ 02992 int offset, length; 02993 int i, need_substring; 02994 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 02995 02996 if (c) { 02997 ast_channel_lock(c); 02998 places[0] = &c->varshead; 02999 } 03000 /* 03001 * Make a copy of var because parse_variable_name() modifies the string. 03002 * Then if called directly, we might need to run substring() on the result; 03003 * remember this for later in 'need_substring', 'offset' and 'length' 03004 */ 03005 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03006 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03007 03008 /* 03009 * Look first into predefined variables, then into variable lists. 03010 * Variable 's' points to the result, according to the following rules: 03011 * s == ¬_found (set at the beginning) means that we did not find a 03012 * matching variable and need to look into more places. 03013 * If s != ¬_found, s is a valid result string as follows: 03014 * s = NULL if the variable does not have a value; 03015 * you typically do this when looking for an unset predefined variable. 03016 * s = workspace if the result has been assembled there; 03017 * typically done when the result is built e.g. with an snprintf(), 03018 * so we don't need to do an additional copy. 03019 * s != workspace in case we have a string, that needs to be copied 03020 * (the ast_copy_string is done once for all at the end). 03021 * Typically done when the result is already available in some string. 03022 */ 03023 s = ¬_found; /* default value */ 03024 if (c) { /* This group requires a valid channel */ 03025 /* Names with common parts are looked up a piece at a time using strncmp. */ 03026 if (!strncmp(var, "CALL", 4)) { 03027 if (!strncmp(var + 4, "ING", 3)) { 03028 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03029 ast_str_set(str, maxlen, "%d", 03030 ast_party_id_presentation(&c->caller.id)); 03031 s = ast_str_buffer(*str); 03032 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03033 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03034 s = ast_str_buffer(*str); 03035 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03036 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03037 s = ast_str_buffer(*str); 03038 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03039 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03040 s = ast_str_buffer(*str); 03041 } 03042 } 03043 } else if (!strcmp(var, "HINT")) { 03044 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03045 } else if (!strcmp(var, "HINTNAME")) { 03046 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03047 } else if (!strcmp(var, "EXTEN")) { 03048 s = c->exten; 03049 } else if (!strcmp(var, "CONTEXT")) { 03050 s = c->context; 03051 } else if (!strcmp(var, "PRIORITY")) { 03052 ast_str_set(str, maxlen, "%d", c->priority); 03053 s = ast_str_buffer(*str); 03054 } else if (!strcmp(var, "CHANNEL")) { 03055 s = c->name; 03056 } else if (!strcmp(var, "UNIQUEID")) { 03057 s = c->uniqueid; 03058 } else if (!strcmp(var, "HANGUPCAUSE")) { 03059 ast_str_set(str, maxlen, "%d", c->hangupcause); 03060 s = ast_str_buffer(*str); 03061 } 03062 } 03063 if (s == ¬_found) { /* look for more */ 03064 if (!strcmp(var, "EPOCH")) { 03065 ast_str_set(str, maxlen, "%u", (int) time(NULL)); 03066 s = ast_str_buffer(*str); 03067 } else if (!strcmp(var, "SYSTEMNAME")) { 03068 s = ast_config_AST_SYSTEM_NAME; 03069 } else if (!strcmp(var, "ENTITYID")) { 03070 char workspace[20]; 03071 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03072 s = workspace; 03073 } 03074 } 03075 /* if not found, look into chanvars or global vars */ 03076 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03077 struct ast_var_t *variables; 03078 if (!places[i]) 03079 continue; 03080 if (places[i] == &globals) 03081 ast_rwlock_rdlock(&globalslock); 03082 AST_LIST_TRAVERSE(places[i], variables, entries) { 03083 if (!strcasecmp(ast_var_name(variables), var)) { 03084 s = ast_var_value(variables); 03085 break; 03086 } 03087 } 03088 if (places[i] == &globals) 03089 ast_rwlock_unlock(&globalslock); 03090 } 03091 if (s == ¬_found || s == NULL) { 03092 ast_debug(5, "Result of '%s' is NULL\n", var); 03093 ret = NULL; 03094 } else { 03095 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03096 if (s != ast_str_buffer(*str)) { 03097 ast_str_set(str, maxlen, "%s", s); 03098 } 03099 ret = ast_str_buffer(*str); 03100 if (need_substring) { 03101 ret = ast_str_substring(*str, offset, length); 03102 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03103 } 03104 } 03105 03106 if (c) { 03107 ast_channel_unlock(c); 03108 } 03109 return ret; 03110 }
void ast_str_substitute_variables | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct ast_channel * | chan, | |||
const char * | templ | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
chan | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
templ | Variable template to expand. |
Definition at line 3764 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), config_curl(), custom_log(), cut_internal(), destroy_curl(), exec_exec(), func_mchan_read(), function_eval2(), function_fieldnum_helper(), function_fieldqty_helper(), handle_getvariablefull(), import_helper(), listfilter(), make_email_file(), realtime_curl(), realtime_multi_curl(), replace(), require_curl(), sendmail(), sendpage(), shift_pop(), store_curl(), syslog_log(), tryexec_exec(), unshift_push(), update2_curl(), and update_curl().
03765 { 03766 size_t used; 03767 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 03768 }
void ast_str_substitute_variables_full | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct ast_channel * | c, | |||
struct varshead * | headp, | |||
const char * | templ, | |||
size_t * | used | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
c | Channel variables from which to extract values, and channel to pass to any dialplan functions. | |
headp | If no channel is specified, a channel list from which to extract variable values | |
templ | Variable template to expand. | |
used | Number of bytes read from the template. |
Definition at line 3588 of file pbx.c.
References ast_channel_release(), ast_debug, ast_dummy_channel_alloc(), ast_free, ast_func_read2(), ast_log(), ast_str_append(), ast_str_append_substr(), ast_str_buffer(), ast_str_create(), ast_str_expr(), ast_str_reset(), ast_str_retrieve_variable(), ast_str_set_substr(), ast_str_strlen(), ast_str_substitute_variables_full(), ast_str_substring(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), and ast_channel::varshead.
Referenced by ast_str_substitute_variables(), ast_str_substitute_variables_full(), and ast_str_substitute_variables_varshead().
03589 { 03590 /* Substitutes variables into buf, based on string templ */ 03591 char *cp4 = NULL; 03592 const char *tmp, *whereweare; 03593 int orig_size = 0; 03594 int offset, offset2, isfunction; 03595 const char *nextvar, *nextexp, *nextthing; 03596 const char *vars, *vare; 03597 char *finalvars; 03598 int pos, brackets, needsub, len; 03599 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 03600 03601 ast_str_reset(*buf); 03602 whereweare = tmp = templ; 03603 while (!ast_strlen_zero(whereweare)) { 03604 /* Assume we're copying the whole remaining string */ 03605 pos = strlen(whereweare); 03606 nextvar = NULL; 03607 nextexp = NULL; 03608 nextthing = strchr(whereweare, '$'); 03609 if (nextthing) { 03610 switch (nextthing[1]) { 03611 case '{': 03612 nextvar = nextthing; 03613 pos = nextvar - whereweare; 03614 break; 03615 case '[': 03616 nextexp = nextthing; 03617 pos = nextexp - whereweare; 03618 break; 03619 default: 03620 pos = 1; 03621 } 03622 } 03623 03624 if (pos) { 03625 /* Copy that many bytes */ 03626 ast_str_append_substr(buf, maxlen, whereweare, pos); 03627 03628 templ += pos; 03629 whereweare += pos; 03630 } 03631 03632 if (nextvar) { 03633 /* We have a variable. Find the start and end, and determine 03634 if we are going to have to recursively call ourselves on the 03635 contents */ 03636 vars = vare = nextvar + 2; 03637 brackets = 1; 03638 needsub = 0; 03639 03640 /* Find the end of it */ 03641 while (brackets && *vare) { 03642 if ((vare[0] == '$') && (vare[1] == '{')) { 03643 needsub++; 03644 } else if (vare[0] == '{') { 03645 brackets++; 03646 } else if (vare[0] == '}') { 03647 brackets--; 03648 } else if ((vare[0] == '$') && (vare[1] == '[')) 03649 needsub++; 03650 vare++; 03651 } 03652 if (brackets) 03653 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 03654 len = vare - vars - 1; 03655 03656 /* Skip totally over variable string */ 03657 whereweare += (len + 3); 03658 03659 /* Store variable name (and truncate) */ 03660 ast_str_set_substr(&substr1, 0, vars, len); 03661 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 03662 03663 /* Substitute if necessary */ 03664 if (needsub) { 03665 size_t used; 03666 if (!substr2) { 03667 substr2 = ast_str_create(16); 03668 } 03669 03670 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03671 finalvars = ast_str_buffer(substr2); 03672 } else { 03673 finalvars = ast_str_buffer(substr1); 03674 } 03675 03676 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 03677 if (isfunction) { 03678 /* Evaluate function */ 03679 if (c || !headp) { 03680 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03681 } else { 03682 struct varshead old; 03683 struct ast_channel *bogus = ast_dummy_channel_alloc(); 03684 if (bogus) { 03685 memcpy(&old, &bogus->varshead, sizeof(old)); 03686 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 03687 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03688 /* Don't deallocate the varshead that was passed in */ 03689 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 03690 ast_channel_release(bogus); 03691 } else { 03692 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03693 } 03694 } 03695 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03696 } else { 03697 /* Retrieve variable value */ 03698 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 03699 cp4 = ast_str_buffer(substr3); 03700 } 03701 if (cp4) { 03702 ast_str_substring(substr3, offset, offset2); 03703 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 03704 } 03705 } else if (nextexp) { 03706 /* We have an expression. Find the start and end, and determine 03707 if we are going to have to recursively call ourselves on the 03708 contents */ 03709 vars = vare = nextexp + 2; 03710 brackets = 1; 03711 needsub = 0; 03712 03713 /* Find the end of it */ 03714 while (brackets && *vare) { 03715 if ((vare[0] == '$') && (vare[1] == '[')) { 03716 needsub++; 03717 brackets++; 03718 vare++; 03719 } else if (vare[0] == '[') { 03720 brackets++; 03721 } else if (vare[0] == ']') { 03722 brackets--; 03723 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03724 needsub++; 03725 vare++; 03726 } 03727 vare++; 03728 } 03729 if (brackets) 03730 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03731 len = vare - vars - 1; 03732 03733 /* Skip totally over expression */ 03734 whereweare += (len + 3); 03735 03736 /* Store variable name (and truncate) */ 03737 ast_str_set_substr(&substr1, 0, vars, len); 03738 03739 /* Substitute if necessary */ 03740 if (needsub) { 03741 size_t used; 03742 if (!substr2) { 03743 substr2 = ast_str_create(16); 03744 } 03745 03746 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03747 finalvars = ast_str_buffer(substr2); 03748 } else { 03749 finalvars = ast_str_buffer(substr1); 03750 } 03751 03752 if (ast_str_expr(&substr3, 0, c, finalvars)) { 03753 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 03754 } 03755 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 03756 } 03757 } 03758 *used = ast_str_strlen(*buf) - orig_size; 03759 ast_free(substr1); 03760 ast_free(substr2); 03761 ast_free(substr3); 03762 }
void ast_str_substitute_variables_varshead | ( | struct ast_str ** | buf, | |
ssize_t | maxlen, | |||
struct varshead * | headp, | |||
const char * | templ | |||
) |
buf | Result will be placed in this buffer. | |
maxlen | -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes. | |
headp | If no channel is specified, a channel list from which to extract variable values | |
templ | Variable template to expand. |
Definition at line 3770 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by add_user_extension(), build_user_routes(), phoneprov_callback(), pp_each_extension_helper(), and pp_each_user_helper().
03771 { 03772 size_t used; 03773 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 03774 }
static const char* ast_str_substring | ( | struct ast_str * | value, | |
int | offset, | |||
int | length | |||
) | [static] |
Definition at line 2921 of file pbx.c.
References ast_str_buffer(), ast_str_reset(), ast_str_strlen(), ast_str_update(), and value.
Referenced by ast_str_retrieve_variable(), and ast_str_substitute_variables_full().
02922 { 02923 int lr; /* length of the input string after the copy */ 02924 02925 lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */ 02926 02927 /* Quick check if no need to do anything */ 02928 if (offset == 0 && length >= lr) /* take the whole string */ 02929 return ast_str_buffer(value); 02930 02931 if (offset < 0) { /* translate negative offset into positive ones */ 02932 offset = lr + offset; 02933 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 02934 offset = 0; 02935 } 02936 02937 /* too large offset result in empty string so we know what to return */ 02938 if (offset >= lr) { 02939 ast_str_reset(value); 02940 return ast_str_buffer(value); 02941 } 02942 02943 if (offset > 0) { 02944 /* Go ahead and chop off the beginning */ 02945 memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1); 02946 lr -= offset; 02947 } 02948 02949 if (length >= 0 && length < lr) { /* truncate if necessary */ 02950 char *tmp = ast_str_buffer(value); 02951 tmp[length] = '\0'; 02952 ast_str_update(value); 02953 } else if (length < 0) { 02954 if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */ 02955 char *tmp = ast_str_buffer(value); 02956 tmp[lr + length] = '\0'; 02957 ast_str_update(value); 02958 } else { 02959 ast_str_reset(value); 02960 } 02961 } else { 02962 /* Nothing to do, but update the buffer length */ 02963 ast_str_update(value); 02964 } 02965 02966 return ast_str_buffer(value); 02967 }
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 9931 of file pbx.c.
References ast_rwlock_unlock, and ast_context::lock.
Referenced by __ast_context_destroy(), _macro_exec(), ast_add_extension2_lockopt(), ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_extension_callerid2(), ast_context_remove_ignorepat2(), ast_context_remove_include2(), ast_context_remove_switch2(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_cli_dialplan_save(), lookup_c_ip(), lookup_ci(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
09932 { 09933 return ast_rwlock_unlock(&con->lock); 09934 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 9913 of file pbx.c.
References ast_mutex_unlock, and conlock.
Referenced by _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
09914 { 09915 return ast_mutex_unlock(&conlock); 09916 }
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 6822 of file pbx.c.
References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_string_field_free_memory, ast_verb, ast_app::list, ast_app::name, and unreference_cached_app().
Referenced by __unload_module(), load_module(), and unload_module().
06823 { 06824 struct ast_app *tmp; 06825 06826 AST_RWLIST_WRLOCK(&apps); 06827 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 06828 if (!strcasecmp(app, tmp->name)) { 06829 unreference_cached_app(tmp); 06830 AST_RWLIST_REMOVE_CURRENT(list); 06831 ast_verb(2, "Unregistered application '%s'\n", tmp->name); 06832 ast_string_field_free_memory(tmp); 06833 ast_free(tmp); 06834 break; 06835 } 06836 } 06837 AST_RWLIST_TRAVERSE_SAFE_END; 06838 AST_RWLIST_UNLOCK(&apps); 06839 06840 return tmp ? 0 : -1; 06841 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 5612 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().
05613 { 05614 AST_RWLIST_WRLOCK(&switches); 05615 AST_RWLIST_REMOVE(&switches, sw, list); 05616 AST_RWLIST_UNLOCK(&switches); 05617 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | exten | |||
) |
Definition at line 10045 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().
10047 { 10048 if (!exten) 10049 return con ? con->root : NULL; 10050 else 10051 return exten->next; 10052 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) |
Definition at line 10078 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().
10080 { 10081 if (!ip) 10082 return con ? con->ignorepats : NULL; 10083 else 10084 return ip->next; 10085 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) |
Definition at line 10069 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().
10071 { 10072 if (!inc) 10073 return con ? con->includes : NULL; 10074 else 10075 return inc->next; 10076 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) |
Definition at line 10054 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().
10056 { 10057 if (!sw) 10058 return con ? AST_LIST_FIRST(&con->alts) : NULL; 10059 else 10060 return AST_LIST_NEXT(sw, list); 10061 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) |
Definition at line 10040 of file pbx.c.
References contexts, and ast_context::next.
Referenced by _macro_exec(), ast_context_find(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_load_module(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
struct ast_exten* ast_walk_extension_priorities | ( | struct ast_exten * | exten, | |
struct ast_exten * | priority | |||
) |
Definition at line 10063 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(), 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 9921 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().
09922 { 09923 return ast_rwlock_wrlock(&con->lock); 09924 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 9903 of file pbx.c.
References ast_mutex_lock, and conlock.
Referenced by ast_context_destroy(), ast_context_find_or_create(), and complete_dialplan_remove_include().
09904 { 09905 return ast_mutex_lock(&conlock); 09906 }
static void* async_wait | ( | void * | data | ) | [static] |
Definition at line 8290 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, 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().
08291 { 08292 struct async_stat *as = data; 08293 struct ast_channel *chan = as->chan; 08294 int timeout = as->timeout; 08295 int res; 08296 struct ast_frame *f; 08297 struct ast_app *app; 08298 08299 while (timeout && (chan->_state != AST_STATE_UP)) { 08300 res = ast_waitfor(chan, timeout); 08301 if (res < 1) 08302 break; 08303 if (timeout > -1) 08304 timeout = res; 08305 f = ast_read(chan); 08306 if (!f) 08307 break; 08308 if (f->frametype == AST_FRAME_CONTROL) { 08309 if ((f->subclass.integer == AST_CONTROL_BUSY) || 08310 (f->subclass.integer == AST_CONTROL_CONGESTION) ) { 08311 ast_frfree(f); 08312 break; 08313 } 08314 } 08315 ast_frfree(f); 08316 } 08317 if (chan->_state == AST_STATE_UP) { 08318 if (!ast_strlen_zero(as->app)) { 08319 app = pbx_findapp(as->app); 08320 if (app) { 08321 ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name); 08322 pbx_exec(chan, app, as->appdata); 08323 } else 08324 ast_log(LOG_WARNING, "No such application '%s'\n", as->app); 08325 } else { 08326 if (!ast_strlen_zero(as->context)) 08327 ast_copy_string(chan->context, as->context, sizeof(chan->context)); 08328 if (!ast_strlen_zero(as->exten)) 08329 ast_copy_string(chan->exten, as->exten, sizeof(chan->exten)); 08330 if (as->priority > 0) 08331 chan->priority = as->priority; 08332 /* Run the PBX */ 08333 if (ast_pbx_run(chan)) { 08334 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name); 08335 } else { 08336 /* PBX will have taken care of this */ 08337 chan = NULL; 08338 } 08339 } 08340 } 08341 ast_free(as); 08342 if (chan) 08343 ast_hangup(chan); 08344 return NULL; 08345 }
static void cli_match_char_tree | ( | struct match_char * | node, | |
char * | prefix, | |||
int | fd | |||
) | [static] |
Definition at line 1584 of file pbx.c.
References match_char::alt_char, ast_cli(), ast_str_alloca, ast_str_buffer(), ast_str_set(), match_char::deleted, ast_exten::exten, match_char::exten, match_char::is_pattern, match_char::next_char, match_char::specificity, and match_char::x.
Referenced by show_debug_helper().
01585 { 01586 char extenstr[40]; 01587 struct ast_str *my_prefix = ast_str_alloca(1024); 01588 01589 extenstr[0] = '\0'; 01590 01591 if (node && node->exten) 01592 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten); 01593 01594 if (strlen(node->x) > 1) { 01595 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01596 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01597 node->exten ? node->exten->exten : "", extenstr); 01598 } else { 01599 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N', 01600 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "", 01601 node->exten ? node->exten->exten : "", extenstr); 01602 } 01603 01604 ast_str_set(&my_prefix, 0, "%s+ ", prefix); 01605 01606 if (node->next_char) 01607 cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd); 01608 01609 if (node->alt_char) 01610 cli_match_char_tree(node->alt_char, prefix, fd); 01611 }
static int collect_digits | ( | struct ast_channel * | c, | |
int | waittime, | |||
char * | buf, | |||
int | buflen, | |||
int | pos | |||
) | [static] |
collect digits from the channel into the buffer.
c,buf,buflen,pos | ||
waittime | is in milliseconds |
0 | on timeout or done. | |
-1 | on error. |
Definition at line 4627 of file pbx.c.
References ast_channel::_softhangup, ast_channel_clear_softhangup(), ast_matchmore_extension(), AST_SOFTHANGUP_ASYNCGOTO, ast_waitfordigit(), ast_channel::caller, ast_channel::context, ast_pbx::dtimeoutms, ast_party_caller::id, ast_party_id::number, ast_channel::pbx, S_COR, ast_party_number::str, and ast_party_number::valid.
04628 { 04629 int digit; 04630 04631 buf[pos] = '\0'; /* make sure it is properly terminated */ 04632 while (ast_matchmore_extension(c, c->context, buf, 1, 04633 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { 04634 /* As long as we're willing to wait, and as long as it's not defined, 04635 keep reading digits until we can't possibly get a right answer anymore. */ 04636 digit = ast_waitfordigit(c, waittime); 04637 if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { 04638 ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); 04639 } else { 04640 if (!digit) /* No entry */ 04641 break; 04642 if (digit < 0) /* Error, maybe a hangup */ 04643 return -1; 04644 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */ 04645 buf[pos++] = digit; 04646 buf[pos] = '\0'; 04647 } 04648 waittime = c->pbx->dtimeoutms; 04649 } 04650 } 04651 return 0; 04652 }
static int compare_char | ( | const void * | a, | |
const void * | b | |||
) | [static] |
Definition at line 1033 of file pbx.c.
Referenced by add_exten_to_pattern_tree().
01034 { 01035 const char *ac = a; 01036 const char *bc = b; 01037 if ((*ac) < (*bc)) 01038 return -1; 01039 else if ((*ac) == (*bc)) 01040 return 0; 01041 else 01042 return 1; 01043 }
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 5793 of file pbx.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_get_extension_name(), ast_strdup, ast_hint::exten, and hints.
Referenced by handle_show_hint().
05794 { 05795 struct ast_hint *hint; 05796 char *ret = NULL; 05797 int which = 0; 05798 int wordlen; 05799 struct ao2_iterator i; 05800 05801 if (pos != 3) 05802 return NULL; 05803 05804 wordlen = strlen(word); 05805 05806 /* walk through all hints */ 05807 i = ao2_iterator_init(hints, 0); 05808 for (hint = ao2_iterator_next(&i); hint; ao2_unlock(hint), ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) { 05809 ao2_lock(hint); 05810 if (!strncasecmp(word, hint->exten ? ast_get_extension_name(hint->exten) : "", wordlen) && ++which > state) { 05811 ret = ast_strdup(ast_get_extension_name(hint->exten)); 05812 ao2_unlock(hint); 05813 break; 05814 } 05815 } 05816 ao2_iterator_destroy(&i); 05817 05818 return ret; 05819 }
static char* complete_show_dialplan_context | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 5990 of file pbx.c.
References ast_get_context_name(), ast_rdlock_contexts(), ast_strdup, ast_unlock_contexts(), and ast_walk_contexts().
Referenced by handle_debug_dialplan(), and handle_show_dialplan().
05992 { 05993 struct ast_context *c = NULL; 05994 char *ret = NULL; 05995 int which = 0; 05996 int wordlen; 05997 05998 /* we are do completion of [exten@]context on second position only */ 05999 if (pos != 2) 06000 return NULL; 06001 06002 ast_rdlock_contexts(); 06003 06004 wordlen = strlen(word); 06005 06006 /* walk through all contexts and return the n-th match */ 06007 while ( (c = ast_walk_contexts(c)) ) { 06008 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { 06009 ret = ast_strdup(ast_get_context_name(c)); 06010 break; 06011 } 06012 } 06013 06014 ast_unlock_contexts(); 06015 06016 return ret; 06017 }
static void context_merge | ( | struct ast_context ** | extcontexts, | |
struct ast_hashtab * | exttable, | |||
struct ast_context * | context, | |||
const char * | registrar | |||
) | [static] |
Definition at line 6958 of file pbx.c.
References ast_exten::app, ast_add_extension2(), ast_context_find_or_create(), ast_hashtab_end_traversal(), ast_hashtab_lookup(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_log(), ast_strdup, ast_verb, ast_exten::cidmatch, store_hint::context, context_merge_incls_swits_igps_other_registrars(), ast_exten::data, ast_exten::datad, ast_exten::exten, store_hint::first, ast_exten::label, LOG_ERROR, ast_exten::matchcid, ast_exten::peer_table, ast_exten::priority, and ast_exten::registrar.
Referenced by ast_merge_contexts_and_delete().
06959 { 06960 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */ 06961 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item; 06962 struct ast_hashtab_iter *exten_iter; 06963 struct ast_hashtab_iter *prio_iter; 06964 int insert_count = 0; 06965 int first = 1; 06966 06967 /* We'll traverse all the extensions/prios, and see which are not registrar'd with 06968 the current registrar, and copy them to the new context. If the new context does not 06969 exist, we'll create it "on demand". If no items are in this context to copy, then we'll 06970 only create the empty matching context if the old one meets the criteria */ 06971 06972 if (context->root_table) { 06973 exten_iter = ast_hashtab_start_traversal(context->root_table); 06974 while ((exten_item=ast_hashtab_next(exten_iter))) { 06975 if (new) { 06976 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item); 06977 } else { 06978 new_exten_item = NULL; 06979 } 06980 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table); 06981 while ((prio_item=ast_hashtab_next(prio_iter))) { 06982 int res1; 06983 char *dupdstr; 06984 06985 if (new_exten_item) { 06986 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item); 06987 } else { 06988 new_prio_item = NULL; 06989 } 06990 if (strcmp(prio_item->registrar,registrar) == 0) { 06991 continue; 06992 } 06993 /* make sure the new context exists, so we have somewhere to stick this exten/prio */ 06994 if (!new) { 06995 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 */ 06996 } 06997 06998 /* copy in the includes, switches, and ignorepats */ 06999 if (first) { /* but, only need to do this once */ 07000 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07001 first = 0; 07002 } 07003 07004 if (!new) { 07005 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name); 07006 return; /* no sense continuing. */ 07007 } 07008 /* we will not replace existing entries in the new context with stuff from the old context. 07009 but, if this is because of some sort of registrar conflict, we ought to say something... */ 07010 07011 dupdstr = ast_strdup(prio_item->data); 07012 07013 res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 07014 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar); 07015 if (!res1 && new_exten_item && new_prio_item){ 07016 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n", 07017 context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar); 07018 } else { 07019 /* 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, 07020 and no double frees take place, either! */ 07021 insert_count++; 07022 } 07023 } 07024 ast_hashtab_end_traversal(prio_iter); 07025 } 07026 ast_hashtab_end_traversal(exten_iter); 07027 } 07028 07029 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 || 07030 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) { 07031 /* we could have given it the registrar of the other module who incremented the refcount, 07032 but that's not available, so we give it the registrar we know about */ 07033 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar); 07034 07035 /* copy in the includes, switches, and ignorepats */ 07036 context_merge_incls_swits_igps_other_registrars(new, context, registrar); 07037 } 07038 }
static void context_merge_incls_swits_igps_other_registrars | ( | struct ast_context * | new, | |
struct ast_context * | old, | |||
const char * | registrar | |||
) | [static] |
Definition at line 6925 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().
06926 { 06927 struct ast_include *i; 06928 struct ast_ignorepat *ip; 06929 struct ast_sw *sw; 06930 06931 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); 06932 /* copy in the includes, switches, and ignorepats */ 06933 /* walk through includes */ 06934 for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) { 06935 if (strcmp(ast_get_include_registrar(i), registrar) == 0) 06936 continue; /* not mine */ 06937 ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i)); 06938 } 06939 06940 /* walk through switches */ 06941 for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) { 06942 if (strcmp(ast_get_switch_registrar(sw), registrar) == 0) 06943 continue; /* not mine */ 06944 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)); 06945 } 06946 06947 /* walk thru ignorepats ... */ 06948 for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) { 06949 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) 06950 continue; /* not mine */ 06951 ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip)); 06952 } 06953 }
static void create_match_char_tree | ( | struct ast_context * | con | ) | [static] |
Definition at line 2084 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, ast_context::root_table, and t1.
Referenced by pbx_find_extension().
02085 { 02086 struct ast_hashtab_iter *t1; 02087 struct ast_exten *e1; 02088 #ifdef NEED_DEBUG 02089 int biggest_bucket, resizes, numobjs, numbucks; 02090 02091 ast_log(LOG_DEBUG,"Creating Extension Trie for context %s(%p)\n", con->name, con); 02092 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks); 02093 ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n", 02094 numobjs, numbucks, biggest_bucket, resizes); 02095 #endif 02096 t1 = ast_hashtab_start_traversal(con->root_table); 02097 while ((e1 = ast_hashtab_next(t1))) { 02098 if (e1->exten) { 02099 add_exten_to_pattern_tree(con, e1, 0); 02100 } else { 02101 ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n"); 02102 } 02103 } 02104 ast_hashtab_end_traversal(t1); 02105 }
static void decrease_call_count | ( | void | ) | [static] |
Definition at line 4983 of file pbx.c.
References ast_mutex_lock, ast_mutex_unlock, countcalls, and maxcalllock.
Referenced by ast_pbx_run_args(), ast_pbx_start(), and pbx_thread().
04984 { 04985 ast_mutex_lock(&maxcalllock); 04986 if (countcalls > 0) 04987 countcalls--; 04988 ast_mutex_unlock(&maxcalllock); 04989 }
static void destroy_exten | ( | struct ast_exten * | e | ) | [static] |
Definition at line 4991 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().
04992 { 04993 if (e->priority == PRIORITY_HINT) 04994 ast_remove_hint(e); 04995 04996 if (e->peer_table) 04997 ast_hashtab_destroy(e->peer_table,0); 04998 if (e->peer_label_table) 04999 ast_hashtab_destroy(e->peer_label_table, 0); 05000 if (e->datad) 05001 e->datad(e->data); 05002 ast_free(e); 05003 }
static void destroy_pattern_tree | ( | struct match_char * | pattern_tree | ) | [static] |
Definition at line 2107 of file pbx.c.
References match_char::alt_char, ast_free, match_char::exten, and match_char::next_char.
Referenced by __ast_internal_context_destroy().
02108 { 02109 /* destroy all the alternates */ 02110 if (pattern_tree->alt_char) { 02111 destroy_pattern_tree(pattern_tree->alt_char); 02112 pattern_tree->alt_char = 0; 02113 } 02114 /* destroy all the nexts */ 02115 if (pattern_tree->next_char) { 02116 destroy_pattern_tree(pattern_tree->next_char); 02117 pattern_tree->next_char = 0; 02118 } 02119 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */ 02120 ast_free(pattern_tree); 02121 }
static void device_state_cb | ( | const struct ast_event * | event, | |
void * | unused | |||
) | [static] |
Definition at line 9798 of file pbx.c.
References ast_calloc, ast_event_get_ie_str(), AST_EVENT_IE_DEVICE, ast_free, ast_log(), ast_strlen_zero(), ast_taskprocessor_push(), device_state_tps, handle_statechange(), and LOG_ERROR.
09799 { 09800 const char *device; 09801 struct statechange *sc; 09802 09803 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 09804 if (ast_strlen_zero(device)) { 09805 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n"); 09806 return; 09807 } 09808 09809 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1))) 09810 return; 09811 strcpy(sc->dev, device); 09812 if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) { 09813 ast_free(sc); 09814 } 09815 }
static void exception_store_free | ( | void * | data | ) | [static] |
Definition at line 3112 of file pbx.c.
References ast_free, and ast_string_field_free_memory.
03113 { 03114 struct pbx_exception *exception = data; 03115 ast_string_field_free_memory(exception); 03116 ast_free(exception); 03117 }
static int ext_cmp | ( | const char * | a, | |
const char * | b | |||
) | [static] |
the full routine to compare extensions in rules.
Definition at line 2257 of file pbx.c.
References ext_cmp1().
Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().
02258 { 02259 /* make sure non-patterns come first. 02260 * If a is not a pattern, it either comes first or 02261 * we do a more complex pattern comparison. 02262 */ 02263 int ret = 0; 02264 02265 if (a[0] != '_') 02266 return (b[0] == '_') ? -1 : strcmp(a, b); 02267 02268 /* Now we know a is a pattern; if b is not, a comes first */ 02269 if (b[0] != '_') 02270 return 1; 02271 02272 /* ok we need full pattern sorting routine. 02273 * skip past the underscores */ 02274 ++a; ++b; 02275 do { 02276 unsigned char bitwise[2][32] = { { 0, } }; 02277 ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]); 02278 if (ret == 0) { 02279 /* Are the classes different, even though they score the same? */ 02280 ret = memcmp(bitwise[0], bitwise[1], 32); 02281 } 02282 } while (!ret && a && b); 02283 if (ret == 0) { 02284 return 0; 02285 } else { 02286 return (ret > 0) ? 1 : -1; 02287 } 02288 }
static int ext_cmp1 | ( | const char ** | p, | |
unsigned char * | bitwise | |||
) | [static] |
helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first.
ext_cmp1 compares individual characters (or sets of), returning an int where bits 0-7 are the ASCII code of the first char in the set, while bit 8-15 are the cardinality of the set minus 1. This way more specific patterns (smaller cardinality) appear first. Wildcards have a special value, so that we can directly compare them to sets by subtracting the two values. In particular: 0x000xx one character, xx 0x0yyxx yy character set starting with xx 0x10000 '.' (one or more of anything) 0x20000 '!' (zero or more of anything) 0x30000 NUL (end of string) 0x40000 error in set. The pointer to the string is advanced according to needs. NOTES: 1. the empty set is equivalent to NUL. 2. given that a full set has always 0 as the first element, we could encode the special cases as 0xffXX where XX is 1, 2, 3, 4 as used above.
Definition at line 2177 of file pbx.c.
References ast_log(), and LOG_WARNING.
Referenced by ext_cmp().
02178 { 02179 int c, cmin = 0xff, count = 0; 02180 const char *end; 02181 02182 /* load value and advance pointer */ 02183 c = *(*p)++; 02184 02185 /* always return unless we have a set of chars */ 02186 switch (toupper(c)) { 02187 default: /* ordinary character */ 02188 bitwise[c / 8] = 1 << (c % 8); 02189 return 0x0100 | (c & 0xff); 02190 02191 case 'N': /* 2..9 */ 02192 bitwise[6] = 0xfc; 02193 bitwise[7] = 0x03; 02194 return 0x0800 | '2'; 02195 02196 case 'X': /* 0..9 */ 02197 bitwise[6] = 0xff; 02198 bitwise[7] = 0x03; 02199 return 0x0A00 | '0'; 02200 02201 case 'Z': /* 1..9 */ 02202 bitwise[6] = 0xfe; 02203 bitwise[7] = 0x03; 02204 return 0x0900 | '1'; 02205 02206 case '.': /* wildcard */ 02207 return 0x18000; 02208 02209 case '!': /* earlymatch */ 02210 return 0x28000; /* less specific than NULL */ 02211 02212 case '\0': /* empty string */ 02213 *p = NULL; 02214 return 0x30000; 02215 02216 case '[': /* pattern */ 02217 break; 02218 } 02219 /* locate end of set */ 02220 end = strchr(*p, ']'); 02221 02222 if (end == NULL) { 02223 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 02224 return 0x40000; /* XXX make this entry go last... */ 02225 } 02226 02227 for (; *p < end ; (*p)++) { 02228 unsigned char c1, c2; /* first-last char in range */ 02229 c1 = (unsigned char)((*p)[0]); 02230 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */ 02231 c2 = (unsigned char)((*p)[2]); 02232 *p += 2; /* skip a total of 3 chars */ 02233 } else { /* individual character */ 02234 c2 = c1; 02235 } 02236 if (c1 < cmin) { 02237 cmin = c1; 02238 } 02239 for (; c1 <= c2; c1++) { 02240 unsigned char mask = 1 << (c1 % 8); 02241 /*!\note If two patterns score the same, the one with the lowest 02242 * ascii values will compare as coming first. */ 02243 /* Flag the character as included (used) and count it. */ 02244 if (!(bitwise[ c1 / 8 ] & mask)) { 02245 bitwise[ c1 / 8 ] |= mask; 02246 count += 0x100; 02247 } 02248 } 02249 } 02250 (*p)++; 02251 return count == 0 ? 0x30000 : (count | cmin); 02252 }
static int ext_strncpy | ( | char * | dst, | |
const char * | src, | |||
int | len | |||
) | [static] |
copy a string skipping whitespace
Definition at line 7847 of file pbx.c.
Referenced by ast_add_extension2_lockopt().
07848 { 07849 int count = 0; 07850 int insquares = 0; 07851 07852 while (*src && (count < len - 1)) { 07853 if (*src == '[') { 07854 insquares = 1; 07855 } else if (*src == ']') { 07856 insquares = 0; 07857 } else if (*src == ' ' && !insquares) { 07858 src++; 07859 continue; 07860 } 07861 *dst = *src; 07862 dst++; 07863 src++; 07864 count++; 07865 } 07866 *dst = '\0'; 07867 07868 return count; 07869 }
static int extension_match_core | ( | const char * | pattern, | |
const char * | data, | |||
enum ext_match_t | mode | |||
) | [static] |
Definition at line 2470 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().
02471 { 02472 int i; 02473 static int prof_id = -2; /* marker for 'unallocated' id */ 02474 if (prof_id == -2) { 02475 prof_id = ast_add_profile("ext_match", 0); 02476 } 02477 ast_mark(prof_id, 1); 02478 i = _extension_match_core(pattern, data, mode); 02479 ast_mark(prof_id, 0); 02480 return i; 02481 }
static struct ast_context* find_context | ( | const char * | context | ) | [static] |
lookup for a context with a given name,
found | context or NULL if not found. |
Definition at line 5107 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), contexts_table, and fake_context::name.
05108 { 05109 struct ast_context *c = NULL; 05110 struct fake_context item; 05111 05112 ast_copy_string(item.name, context, sizeof(item.name)); 05113 05114 c = ast_hashtab_lookup(contexts_table,&item); 05115 05116 return c; 05117 }
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 5124 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), contexts_table, and fake_context::name.
Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().
05125 { 05126 struct ast_context *c = NULL; 05127 struct fake_context item; 05128 05129 ast_copy_string(item.name, context, sizeof(item.name)); 05130 05131 ast_rdlock_contexts(); 05132 c = ast_hashtab_lookup(contexts_table,&item); 05133 05134 if (!c) 05135 ast_unlock_contexts(); 05136 05137 return c; 05138 }
static int find_hint_by_cb_id | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Remove a watcher from the callback list.
Definition at line 4390 of file pbx.c.
References ao2_find, ao2_ref, ast_hint::callbacks, CMP_MATCH, and CMP_STOP.
Referenced by ast_extension_state_del().
04391 { 04392 struct ast_state_cb *state_cb; 04393 const struct ast_hint *hint = obj; 04394 int *id = arg; 04395 04396 if ((state_cb = ao2_find(hint->callbacks, id, 0))) { 04397 ao2_ref(state_cb, -1); 04398 return CMP_MATCH | CMP_STOP; 04399 } 04400 04401 return 0; 04402 }
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 3464 of file pbx.c.
References args, ast_log(), and LOG_WARNING.
Referenced by ast_func_read(), ast_func_read2(), and ast_func_write().
03465 { 03466 char *args = strchr(function, '('); 03467 03468 if (!args) { 03469 ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function); 03470 } else { 03471 char *p; 03472 *args++ = '\0'; 03473 if ((p = strrchr(args, ')'))) { 03474 *p = '\0'; 03475 } else { 03476 ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args); 03477 } 03478 } 03479 return args; 03480 }
static struct ast_exten * get_canmatch_exten | ( | struct match_char * | node | ) | [static] |
Definition at line 1613 of file pbx.c.
References ast_log(), ast_exten::exten, match_char::exten, LOG_NOTICE, and match_char::next_char.
01614 { 01615 /* find the exten at the end of the rope */ 01616 struct match_char *node2 = node; 01617 01618 for (node2 = node; node2; node2 = node2->next_char) { 01619 if (node2->exten) { 01620 #ifdef NEED_DEBUG_HERE 01621 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten); 01622 #endif 01623 return node2->exten; 01624 } 01625 } 01626 #ifdef NEED_DEBUG_HERE 01627 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x); 01628 #endif 01629 return 0; 01630 }
static unsigned get_range | ( | char * | src, | |
int | max, | |||
const char *const | names[], | |||
const char * | msg | |||
) | [static] |
helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers.
Definition at line 7237 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, lookup_name(), and strsep().
Referenced by ast_build_timing().
07238 { 07239 int start, end; /* start and ending position */ 07240 unsigned int mask = 0; 07241 char *part; 07242 07243 /* Check for whole range */ 07244 if (ast_strlen_zero(src) || !strcmp(src, "*")) { 07245 return (1 << max) - 1; 07246 } 07247 07248 while ((part = strsep(&src, "&"))) { 07249 /* Get start and ending position */ 07250 char *endpart = strchr(part, '-'); 07251 if (endpart) { 07252 *endpart++ = '\0'; 07253 } 07254 /* Find the start */ 07255 if ((start = lookup_name(part, names, max)) < 0) { 07256 ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part); 07257 continue; 07258 } 07259 if (endpart) { /* find end of range */ 07260 if ((end = lookup_name(endpart, names, max)) < 0) { 07261 ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart); 07262 continue; 07263 } 07264 } else { 07265 end = start; 07266 } 07267 /* Fill the mask. Remember that ranges are cyclic */ 07268 mask |= (1 << end); /* initialize with last element */ 07269 while (start != end) { 07270 mask |= (1 << start); 07271 if (++start >= max) { 07272 start = 0; 07273 } 07274 } 07275 } 07276 return mask; 07277 }
static void get_timerange | ( | struct ast_timing * | i, | |
char * | times | |||
) | [static] |
store a bitmask of valid times, one bit each 1 minute
Definition at line 7280 of file pbx.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, ast_timing::minmask, and strsep().
Referenced by ast_build_timing().
07281 { 07282 char *endpart, *part; 07283 int x; 07284 int st_h, st_m; 07285 int endh, endm; 07286 int minute_start, minute_end; 07287 07288 /* start disabling all times, fill the fields with 0's, as they may contain garbage */ 07289 memset(i->minmask, 0, sizeof(i->minmask)); 07290 07291 /* 1-minute per bit */ 07292 /* Star is all times */ 07293 if (ast_strlen_zero(times) || !strcmp(times, "*")) { 07294 /* 48, because each hour takes 2 integers; 30 bits each */ 07295 for (x = 0; x < 48; x++) { 07296 i->minmask[x] = 0x3fffffff; /* 30 bits */ 07297 } 07298 return; 07299 } 07300 /* Otherwise expect a range */ 07301 while ((part = strsep(×, "&"))) { 07302 if (!(endpart = strchr(part, '-'))) { 07303 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 07304 ast_log(LOG_WARNING, "%s isn't a valid time.\n", part); 07305 continue; 07306 } 07307 i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30)); 07308 continue; 07309 } 07310 *endpart++ = '\0'; 07311 /* why skip non digits? Mostly to skip spaces */ 07312 while (*endpart && !isdigit(*endpart)) { 07313 endpart++; 07314 } 07315 if (!*endpart) { 07316 ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part); 07317 continue; 07318 } 07319 if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { 07320 ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part); 07321 continue; 07322 } 07323 if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) { 07324 ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart); 07325 continue; 07326 } 07327 minute_start = st_h * 60 + st_m; 07328 minute_end = endh * 60 + endm; 07329 /* Go through the time and enable each appropriate bit */ 07330 for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) { 07331 i->minmask[x / 30] |= (1 << (x % 30)); 07332 } 07333 /* Do the last one */ 07334 i->minmask[x / 30] |= (1 << (x % 30)); 07335 } 07336 /* All done */ 07337 return; 07338 }
static char* handle_debug_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Send ack once.
Definition at line 6315 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), exten, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_debug_helper(), strsep(), ast_cli_entry::usage, and ast_cli_args::word.
06316 { 06317 char *exten = NULL, *context = NULL; 06318 /* Variables used for different counters */ 06319 struct dialplan_counters counters; 06320 const char *incstack[AST_PBX_MAX_STACK]; 06321 06322 switch (cmd) { 06323 case CLI_INIT: 06324 e->command = "dialplan debug"; 06325 e->usage = 06326 "Usage: dialplan debug [context]\n" 06327 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n"; 06328 return NULL; 06329 case CLI_GENERATE: 06330 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 06331 } 06332 06333 memset(&counters, 0, sizeof(counters)); 06334 06335 if (a->argc != 2 && a->argc != 3) 06336 return CLI_SHOWUSAGE; 06337 06338 /* we obtain [exten@]context? if yes, split them ... */ 06339 /* note: we ignore the exten totally here .... */ 06340 if (a->argc == 3) { 06341 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 06342 context = ast_strdupa(a->argv[2]); 06343 exten = strsep(&context, "@"); 06344 /* change empty strings to NULL */ 06345 if (ast_strlen_zero(exten)) 06346 exten = NULL; 06347 } else { /* no '@' char, only context given */ 06348 context = ast_strdupa(a->argv[2]); 06349 } 06350 if (ast_strlen_zero(context)) 06351 context = NULL; 06352 } 06353 /* else Show complete dial plan, context and exten are NULL */ 06354 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 06355 06356 /* check for input failure and throw some error messages */ 06357 if (context && !counters.context_existence) { 06358 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 06359 return CLI_FAILURE; 06360 } 06361 06362 06363 ast_cli(a->fd,"-= %d %s. =-\n", 06364 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 06365 06366 /* everything ok */ 06367 return CLI_SUCCESS; 06368 }
static char* handle_set_chanvar | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6686 of file pbx.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_get_by_name(), ast_channel_unref, ast_cli(), ast_complete_channels(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, pbx_builtin_setvar_helper(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
06687 { 06688 struct ast_channel *chan; 06689 const char *chan_name, *var_name, *var_value; 06690 06691 switch (cmd) { 06692 case CLI_INIT: 06693 e->command = "dialplan set chanvar"; 06694 e->usage = 06695 "Usage: dialplan set chanvar <channel> <varname> <value>\n" 06696 " Set channel variable <varname> to <value>\n"; 06697 return NULL; 06698 case CLI_GENERATE: 06699 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 06700 } 06701 06702 if (a->argc != e->args + 3) 06703 return CLI_SHOWUSAGE; 06704 06705 chan_name = a->argv[e->args]; 06706 var_name = a->argv[e->args + 1]; 06707 var_value = a->argv[e->args + 2]; 06708 06709 if (!(chan = ast_channel_get_by_name(chan_name))) { 06710 ast_cli(a->fd, "Channel '%s' not found\n", chan_name); 06711 return CLI_FAILURE; 06712 } 06713 06714 pbx_builtin_setvar_helper(chan, var_name, var_value); 06715 06716 chan = ast_channel_unref(chan); 06717 06718 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name); 06719 06720 return CLI_SUCCESS; 06721 }
static char* handle_set_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6723 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.
06724 { 06725 int oldval = 0; 06726 06727 switch (cmd) { 06728 case CLI_INIT: 06729 e->command = "dialplan set extenpatternmatchnew true"; 06730 e->usage = 06731 "Usage: dialplan set extenpatternmatchnew true|false\n" 06732 " Use the NEW extension pattern matching algorithm, true or false.\n"; 06733 return NULL; 06734 case CLI_GENERATE: 06735 return NULL; 06736 } 06737 06738 if (a->argc != 4) 06739 return CLI_SHOWUSAGE; 06740 06741 oldval = pbx_set_extenpatternmatchnew(1); 06742 06743 if (oldval) 06744 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n"); 06745 else 06746 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n"); 06747 06748 return CLI_SUCCESS; 06749 }
static char* handle_set_global | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6664 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.
06665 { 06666 switch (cmd) { 06667 case CLI_INIT: 06668 e->command = "dialplan set global"; 06669 e->usage = 06670 "Usage: dialplan set global <name> <value>\n" 06671 " Set global dialplan variable <name> to <value>\n"; 06672 return NULL; 06673 case CLI_GENERATE: 06674 return NULL; 06675 } 06676 06677 if (a->argc != e->args + 2) 06678 return CLI_SHOWUSAGE; 06679 06680 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]); 06681 ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]); 06682 06683 return CLI_SUCCESS; 06684 }
static char* handle_show_application | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5698 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_complete_applications(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_app::list, ast_cli_args::n, ast_app::name, print_app_docs(), ast_cli_entry::usage, and ast_cli_args::word.
05699 { 05700 struct ast_app *aa; 05701 int app, no_registered_app = 1; 05702 05703 switch (cmd) { 05704 case CLI_INIT: 05705 e->command = "core show application"; 05706 e->usage = 05707 "Usage: core show application <application> [<application> [<application> [...]]]\n" 05708 " Describes a particular application.\n"; 05709 return NULL; 05710 case CLI_GENERATE: 05711 /* 05712 * There is a possibility to show informations about more than one 05713 * application at one time. You can type 'show application Dial Echo' and 05714 * you will see informations about these two applications ... 05715 */ 05716 return ast_complete_applications(a->line, a->word, a->n); 05717 } 05718 05719 if (a->argc < 4) { 05720 return CLI_SHOWUSAGE; 05721 } 05722 05723 AST_RWLIST_RDLOCK(&apps); 05724 AST_RWLIST_TRAVERSE(&apps, aa, list) { 05725 /* Check for each app that was supplied as an argument */ 05726 for (app = 3; app < a->argc; app++) { 05727 if (strcasecmp(aa->name, a->argv[app])) { 05728 continue; 05729 } 05730 05731 /* We found it! */ 05732 no_registered_app = 0; 05733 05734 print_app_docs(aa, a->fd); 05735 } 05736 } 05737 AST_RWLIST_UNLOCK(&apps); 05738 05739 /* we found at least one app? no? */ 05740 if (no_registered_app) { 05741 ast_cli(a->fd, "Your application(s) is (are) not registered\n"); 05742 return CLI_FAILURE; 05743 } 05744 05745 return CLI_SUCCESS; 05746 }
static char* handle_show_applications | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5904 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.
05905 { 05906 struct ast_app *aa; 05907 int like = 0, describing = 0; 05908 int total_match = 0; /* Number of matches in like clause */ 05909 int total_apps = 0; /* Number of apps registered */ 05910 static const char * const choices[] = { "like", "describing", NULL }; 05911 05912 switch (cmd) { 05913 case CLI_INIT: 05914 e->command = "core show applications [like|describing]"; 05915 e->usage = 05916 "Usage: core show applications [{like|describing} <text>]\n" 05917 " List applications which are currently available.\n" 05918 " If 'like', <text> will be a substring of the app name\n" 05919 " If 'describing', <text> will be a substring of the description\n"; 05920 return NULL; 05921 case CLI_GENERATE: 05922 return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n); 05923 } 05924 05925 AST_RWLIST_RDLOCK(&apps); 05926 05927 if (AST_RWLIST_EMPTY(&apps)) { 05928 ast_cli(a->fd, "There are no registered applications\n"); 05929 AST_RWLIST_UNLOCK(&apps); 05930 return CLI_SUCCESS; 05931 } 05932 05933 /* core list applications like <keyword> */ 05934 if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) { 05935 like = 1; 05936 } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) { 05937 describing = 1; 05938 } 05939 05940 /* core list applications describing <keyword1> [<keyword2>] [...] */ 05941 if ((!like) && (!describing)) { 05942 ast_cli(a->fd, " -= Registered Asterisk Applications =-\n"); 05943 } else { 05944 ast_cli(a->fd, " -= Matching Asterisk Applications =-\n"); 05945 } 05946 05947 AST_RWLIST_TRAVERSE(&apps, aa, list) { 05948 int printapp = 0; 05949 total_apps++; 05950 if (like) { 05951 if (strcasestr(aa->name, a->argv[4])) { 05952 printapp = 1; 05953 total_match++; 05954 } 05955 } else if (describing) { 05956 if (aa->description) { 05957 /* Match all words on command line */ 05958 int i; 05959 printapp = 1; 05960 for (i = 4; i < a->argc; i++) { 05961 if (!strcasestr(aa->description, a->argv[i])) { 05962 printapp = 0; 05963 } else { 05964 total_match++; 05965 } 05966 } 05967 } 05968 } else { 05969 printapp = 1; 05970 } 05971 05972 if (printapp) { 05973 ast_cli(a->fd," %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>"); 05974 } 05975 } 05976 if ((!like) && (!describing)) { 05977 ast_cli(a->fd, " -= %d Applications Registered =-\n",total_apps); 05978 } else { 05979 ast_cli(a->fd, " -= %d Applications Matching =-\n",total_match); 05980 } 05981 05982 AST_RWLIST_UNLOCK(&apps); 05983 05984 return CLI_SUCCESS; 05985 }
static char* handle_show_chanvar | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
CLI support for listing chanvar's variables in a parseable way.
Definition at line 6629 of file pbx.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_get_by_name(), ast_channel_unref, ast_cli(), ast_complete_channels(), ast_str_alloca, ast_str_buffer(), ast_str_strlen(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, pbx_builtin_serialize_variables(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
06630 { 06631 struct ast_channel *chan = NULL; 06632 struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */ 06633 06634 switch (cmd) { 06635 case CLI_INIT: 06636 e->command = "dialplan show chanvar"; 06637 e->usage = 06638 "Usage: dialplan show chanvar <channel>\n" 06639 " List current channel variables and their values\n"; 06640 return NULL; 06641 case CLI_GENERATE: 06642 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); 06643 } 06644 06645 if (a->argc != e->args + 1) 06646 return CLI_SHOWUSAGE; 06647 06648 if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) { 06649 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]); 06650 return CLI_FAILURE; 06651 } 06652 06653 pbx_builtin_serialize_variables(chan, &vars); 06654 06655 if (ast_str_strlen(vars)) { 06656 ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars)); 06657 } 06658 06659 chan = ast_channel_unref(chan); 06660 06661 return CLI_SUCCESS; 06662 }
static char* handle_show_dialplan | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6248 of file pbx.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), exten, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, show_dialplan_helper(), strsep(), ast_cli_entry::usage, and ast_cli_args::word.
06249 { 06250 char *exten = NULL, *context = NULL; 06251 /* Variables used for different counters */ 06252 struct dialplan_counters counters; 06253 const char *incstack[AST_PBX_MAX_STACK]; 06254 06255 switch (cmd) { 06256 case CLI_INIT: 06257 e->command = "dialplan show"; 06258 e->usage = 06259 "Usage: dialplan show [[exten@]context]\n" 06260 " Show dialplan\n"; 06261 return NULL; 06262 case CLI_GENERATE: 06263 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n); 06264 } 06265 06266 memset(&counters, 0, sizeof(counters)); 06267 06268 if (a->argc != 2 && a->argc != 3) 06269 return CLI_SHOWUSAGE; 06270 06271 /* we obtain [exten@]context? if yes, split them ... */ 06272 if (a->argc == 3) { 06273 if (strchr(a->argv[2], '@')) { /* split into exten & context */ 06274 context = ast_strdupa(a->argv[2]); 06275 exten = strsep(&context, "@"); 06276 /* change empty strings to NULL */ 06277 if (ast_strlen_zero(exten)) 06278 exten = NULL; 06279 } else { /* no '@' char, only context given */ 06280 context = ast_strdupa(a->argv[2]); 06281 } 06282 if (ast_strlen_zero(context)) 06283 context = NULL; 06284 } 06285 /* else Show complete dial plan, context and exten are NULL */ 06286 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack); 06287 06288 /* check for input failure and throw some error messages */ 06289 if (context && !counters.context_existence) { 06290 ast_cli(a->fd, "There is no existence of '%s' context\n", context); 06291 return CLI_FAILURE; 06292 } 06293 06294 if (exten && !counters.extension_existence) { 06295 if (context) 06296 ast_cli(a->fd, "There is no existence of %s@%s extension\n", 06297 exten, context); 06298 else 06299 ast_cli(a->fd, 06300 "There is no existence of '%s' extension in all contexts\n", 06301 exten); 06302 return CLI_FAILURE; 06303 } 06304 06305 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n", 06306 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions", 06307 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities", 06308 counters.total_context, counters.total_context == 1 ? "context" : "contexts"); 06309 06310 /* everything ok */ 06311 return CLI_SUCCESS; 06312 }
static char* handle_show_function | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3217 of file pbx.c.
References ast_custom_function::acflist, ast_cli_args::argc, ast_custom_function::arguments, ast_cli_args::argv, ast_cli(), ast_custom_function_find(), ast_free, ast_malloc, AST_MAX_APP, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, ast_xmldoc_printable(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_CYAN, COLOR_MAGENTA, ast_cli_entry::command, ast_custom_function::desc, ast_custom_function::docsrc, ast_cli_args::fd, ast_cli_args::n, ast_custom_function::name, S_OR, ast_custom_function::seealso, ast_custom_function::synopsis, synopsis, ast_custom_function::syntax, term_color(), ast_cli_entry::usage, and ast_cli_args::word.
03218 { 03219 struct ast_custom_function *acf; 03220 /* Maximum number of characters added by terminal coloring is 22 */ 03221 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40]; 03222 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL; 03223 char stxtitle[40], *syntax = NULL, *arguments = NULL; 03224 int syntax_size, description_size, synopsis_size, arguments_size, seealso_size; 03225 char *ret = NULL; 03226 int which = 0; 03227 int wordlen; 03228 03229 switch (cmd) { 03230 case CLI_INIT: 03231 e->command = "core show function"; 03232 e->usage = 03233 "Usage: core show function <function>\n" 03234 " Describe a particular dialplan function.\n"; 03235 return NULL; 03236 case CLI_GENERATE: 03237 wordlen = strlen(a->word); 03238 /* case-insensitive for convenience in this 'complete' function */ 03239 AST_RWLIST_RDLOCK(&acf_root); 03240 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03241 if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) { 03242 ret = ast_strdup(acf->name); 03243 break; 03244 } 03245 } 03246 AST_RWLIST_UNLOCK(&acf_root); 03247 03248 return ret; 03249 } 03250 03251 if (a->argc < 4) { 03252 return CLI_SHOWUSAGE; 03253 } 03254 03255 if (!(acf = ast_custom_function_find(a->argv[3]))) { 03256 ast_cli(a->fd, "No function by that name registered.\n"); 03257 return CLI_FAILURE; 03258 } 03259 03260 syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03261 if (!(syntax = ast_malloc(syntax_size))) { 03262 ast_cli(a->fd, "Memory allocation failure!\n"); 03263 return CLI_FAILURE; 03264 } 03265 03266 snprintf(info, sizeof(info), "\n -= Info about function '%s' =- \n\n", acf->name); 03267 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 03268 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 03269 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 03270 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 03271 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 03272 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 03273 term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 03274 #ifdef AST_XML_DOCS 03275 if (acf->docsrc == AST_XML_DOC) { 03276 arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1); 03277 synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1); 03278 description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1); 03279 seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1); 03280 } else 03281 #endif 03282 { 03283 synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03284 synopsis = ast_malloc(synopsis_size); 03285 03286 description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03287 description = ast_malloc(description_size); 03288 03289 arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03290 arguments = ast_malloc(arguments_size); 03291 03292 seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 03293 seealso = ast_malloc(seealso_size); 03294 03295 /* check allocated memory. */ 03296 if (!synopsis || !description || !arguments || !seealso) { 03297 ast_free(synopsis); 03298 ast_free(description); 03299 ast_free(arguments); 03300 ast_free(seealso); 03301 ast_free(syntax); 03302 return CLI_FAILURE; 03303 } 03304 03305 term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 03306 term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 03307 term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size); 03308 term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 03309 } 03310 03311 ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 03312 infotitle, syntitle, synopsis, destitle, description, 03313 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 03314 03315 ast_free(arguments); 03316 ast_free(synopsis); 03317 ast_free(description); 03318 ast_free(seealso); 03319 ast_free(syntax); 03320 03321 return CLI_SUCCESS; 03322 }
static char* handle_show_functions | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3175 of file pbx.c.
References ast_custom_function::acflist, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_custom_function::name, S_OR, ast_custom_function::synopsis, ast_custom_function::syntax, and ast_cli_entry::usage.
03176 { 03177 struct ast_custom_function *acf; 03178 int count_acf = 0; 03179 int like = 0; 03180 03181 switch (cmd) { 03182 case CLI_INIT: 03183 e->command = "core show functions [like]"; 03184 e->usage = 03185 "Usage: core show functions [like <text>]\n" 03186 " List builtin functions, optionally only those matching a given string\n"; 03187 return NULL; 03188 case CLI_GENERATE: 03189 return NULL; 03190 } 03191 03192 if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) { 03193 like = 1; 03194 } else if (a->argc != 3) { 03195 return CLI_SHOWUSAGE; 03196 } 03197 03198 ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); 03199 03200 AST_RWLIST_RDLOCK(&acf_root); 03201 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03202 if (!like || strstr(acf->name, a->argv[4])) { 03203 count_acf++; 03204 ast_cli(a->fd, "%-20.20s %-35.35s %s\n", 03205 S_OR(acf->name, ""), 03206 S_OR(acf->syntax, ""), 03207 S_OR(acf->synopsis, "")); 03208 } 03209 } 03210 AST_RWLIST_UNLOCK(&acf_root); 03211 03212 ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); 03213 03214 return CLI_SUCCESS; 03215 }
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 6571 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.
06572 { 06573 int i = 0; 06574 struct ast_var_t *newvariable; 06575 06576 switch (cmd) { 06577 case CLI_INIT: 06578 e->command = "dialplan show globals"; 06579 e->usage = 06580 "Usage: dialplan show globals\n" 06581 " List current global dialplan variables and their values\n"; 06582 return NULL; 06583 case CLI_GENERATE: 06584 return NULL; 06585 } 06586 06587 ast_rwlock_rdlock(&globalslock); 06588 AST_LIST_TRAVERSE (&globals, newvariable, entries) { 06589 i++; 06590 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable)); 06591 } 06592 ast_rwlock_unlock(&globalslock); 06593 ast_cli(a->fd, "\n -- %d variable(s)\n", i); 06594 06595 return CLI_SUCCESS; 06596 }
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 5822 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_core_show_hint(), ast_hint::exten, ast_cli_args::fd, hints, ast_hint::laststate, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
05823 { 05824 struct ast_hint *hint; 05825 int watchers; 05826 int num = 0, extenlen; 05827 struct ao2_iterator i; 05828 05829 switch (cmd) { 05830 case CLI_INIT: 05831 e->command = "core show hint"; 05832 e->usage = 05833 "Usage: core show hint <exten>\n" 05834 " List registered hint\n"; 05835 return NULL; 05836 case CLI_GENERATE: 05837 return complete_core_show_hint(a->line, a->word, a->pos, a->n); 05838 } 05839 05840 if (a->argc < 4) 05841 return CLI_SHOWUSAGE; 05842 05843 if (ao2_container_count(hints) == 0) { 05844 ast_cli(a->fd, "There are no registered dialplan hints\n"); 05845 return CLI_SUCCESS; 05846 } 05847 05848 extenlen = strlen(a->argv[3]); 05849 i = ao2_iterator_init(hints, 0); 05850 for (hint = ao2_iterator_next(&i); hint; ao2_unlock(hint), ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) { 05851 ao2_lock(hint); 05852 if (!strncasecmp(hint->exten ? ast_get_extension_name(hint->exten) : "", a->argv[3], extenlen)) { 05853 watchers = ao2_container_count(hint->callbacks); 05854 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 05855 ast_get_extension_name(hint->exten), 05856 ast_get_context_name(ast_get_extension_context(hint->exten)), 05857 ast_get_extension_app(hint->exten), 05858 ast_extension_state2str(hint->laststate), watchers); 05859 num++; 05860 } 05861 } 05862 ao2_iterator_destroy(&i); 05863 if (!num) 05864 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]); 05865 else 05866 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]); 05867 return CLI_SUCCESS; 05868 }
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 5749 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_hint::exten, ast_cli_args::fd, hints, ast_hint::laststate, and ast_cli_entry::usage.
05750 { 05751 struct ast_hint *hint; 05752 int num = 0; 05753 int watchers; 05754 struct ao2_iterator i; 05755 05756 switch (cmd) { 05757 case CLI_INIT: 05758 e->command = "core show hints"; 05759 e->usage = 05760 "Usage: core show hints\n" 05761 " List registered hints\n"; 05762 return NULL; 05763 case CLI_GENERATE: 05764 return NULL; 05765 } 05766 05767 if (ao2_container_count(hints) == 0) { 05768 ast_cli(a->fd, "There are no registered dialplan hints\n"); 05769 return CLI_SUCCESS; 05770 } 05771 /* ... we have hints ... */ 05772 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n"); 05773 05774 i = ao2_iterator_init(hints, 0); 05775 for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) { 05776 05777 watchers = ao2_container_count(hint->callbacks); 05778 ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n", 05779 ast_get_extension_name(hint->exten), 05780 ast_get_context_name(ast_get_extension_context(hint->exten)), 05781 ast_get_extension_app(hint->exten), 05782 ast_extension_state2str(hint->laststate), watchers); 05783 num++; 05784 } 05785 05786 ao2_iterator_destroy(&i); 05787 ast_cli(a->fd, "----------------\n"); 05788 ast_cli(a->fd, "- %d hints registered\n", num); 05789 return CLI_SUCCESS; 05790 }
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 5872 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.
05873 { 05874 struct ast_switch *sw; 05875 05876 switch (cmd) { 05877 case CLI_INIT: 05878 e->command = "core show switches"; 05879 e->usage = 05880 "Usage: core show switches\n" 05881 " List registered switches\n"; 05882 return NULL; 05883 case CLI_GENERATE: 05884 return NULL; 05885 } 05886 05887 AST_RWLIST_RDLOCK(&switches); 05888 05889 if (AST_RWLIST_EMPTY(&switches)) { 05890 AST_RWLIST_UNLOCK(&switches); 05891 ast_cli(a->fd, "There are no registered alternative switches\n"); 05892 return CLI_SUCCESS; 05893 } 05894 05895 ast_cli(a->fd, "\n -= Registered Asterisk Alternative Switches =-\n"); 05896 AST_RWLIST_TRAVERSE(&switches, sw, list) 05897 ast_cli(a->fd, "%s: %s\n", sw->name, sw->description); 05898 05899 AST_RWLIST_UNLOCK(&switches); 05900 05901 return CLI_SUCCESS; 05902 }
static int handle_statechange | ( | void * | datap | ) | [static] |
Definition at line 4229 of file pbx.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_extension_state2(), ast_free, ast_get_extension_app(), ast_str_create(), ast_str_set(), ast_hint::callbacks, statechange::dev, ast_exten::exten, ast_hint::exten, hints, ast_hint::laststate, ast_context::name, ast_exten::parent, parse(), statecbs, str, and strsep().
04230 { 04231 struct ast_hint *hint; 04232 struct ast_str *str; 04233 struct statechange *sc = datap; 04234 struct ao2_iterator i; 04235 struct ao2_iterator cb_iter; 04236 04237 if (!(str = ast_str_create(1024))) { 04238 return -1; 04239 } 04240 04241 i = ao2_iterator_init(hints, 0); 04242 for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) { 04243 struct ast_state_cb *state_cb; 04244 char *cur, *parse; 04245 int state; 04246 04247 ast_str_set(&str, 0, "%s", ast_get_extension_app(hint->exten)); 04248 parse = str->str; 04249 04250 while ( (cur = strsep(&parse, "&")) ) { 04251 if (!strcasecmp(cur, sc->dev)) { 04252 break; 04253 } 04254 } 04255 04256 if (!cur) { 04257 continue; 04258 } 04259 04260 /* Get device state for this hint */ 04261 state = ast_extension_state2(hint->exten); 04262 04263 if ((state == -1) || (state == hint->laststate)) { 04264 continue; 04265 } 04266 04267 /* Device state changed since last check - notify the watchers */ 04268 04269 ao2_lock(hints); 04270 ao2_lock(hint); 04271 04272 if (hint->exten == NULL) { 04273 /* the extension has been destroyed */ 04274 ao2_unlock(hint); 04275 ao2_unlock(hints); 04276 continue; 04277 } 04278 04279 /* For general callbacks */ 04280 cb_iter = ao2_iterator_init(statecbs, 0); 04281 for (state_cb = ao2_iterator_next(&cb_iter); state_cb; ao2_ref(state_cb, -1), state_cb = ao2_iterator_next(&cb_iter)) { 04282 state_cb->callback(hint->exten->parent->name, hint->exten->exten, state, state_cb->data); 04283 } 04284 ao2_iterator_destroy(&cb_iter); 04285 04286 /* For extension callbacks */ 04287 cb_iter = ao2_iterator_init(hint->callbacks, 0); 04288 for (state_cb = ao2_iterator_next(&cb_iter); state_cb; ao2_ref(state_cb, -1), state_cb = ao2_iterator_next(&cb_iter)) { 04289 state_cb->callback(hint->exten->parent->name, hint->exten->exten, state, state_cb->data); 04290 } 04291 ao2_iterator_destroy(&cb_iter); 04292 04293 hint->laststate = state; /* record we saw the change */ 04294 ao2_unlock(hint); 04295 ao2_unlock(hints); 04296 } 04297 ao2_iterator_destroy(&i); 04298 ast_free(str); 04299 ast_free(sc); 04300 return 0; 04301 }
static char* handle_unset_extenpatternmatchnew | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 6751 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.
06752 { 06753 int oldval = 0; 06754 06755 switch (cmd) { 06756 case CLI_INIT: 06757 e->command = "dialplan set extenpatternmatchnew false"; 06758 e->usage = 06759 "Usage: dialplan set extenpatternmatchnew true|false\n" 06760 " Use the NEW extension pattern matching algorithm, true or false.\n"; 06761 return NULL; 06762 case CLI_GENERATE: 06763 return NULL; 06764 } 06765 06766 if (a->argc != 4) 06767 return CLI_SHOWUSAGE; 06768 06769 oldval = pbx_set_extenpatternmatchnew(0); 06770 06771 if (!oldval) 06772 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n"); 06773 else 06774 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n"); 06775 06776 return CLI_SUCCESS; 06777 }
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 1075 of file pbx.c.
References ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
01076 { 01077 const struct ast_exten *ac = ah_a; 01078 const struct ast_exten *bc = ah_b; 01079 return ac->priority != bc->priority; 01080 }
static int hashtab_compare_extens | ( | const void * | ha_a, | |
const void * | ah_b | |||
) | [static] |
Definition at line 1056 of file pbx.c.
References ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.
Referenced by ast_add_extension2_lockopt().
01057 { 01058 const struct ast_exten *ac = ah_a; 01059 const struct ast_exten *bc = ah_b; 01060 int x = strcmp(ac->exten, bc->exten); 01061 if (x) { /* if exten names are diff, then return */ 01062 return x; 01063 } 01064 01065 /* but if they are the same, do the cidmatch values match? */ 01066 if (ac->matchcid && bc->matchcid) { 01067 return strcmp(ac->cidmatch,bc->cidmatch); 01068 } else if (!ac->matchcid && !bc->matchcid) { 01069 return 0; /* if there's no matchcid on either side, then this is a match */ 01070 } else { 01071 return 1; /* if there's matchcid on one but not the other, they are different */ 01072 } 01073 }
static unsigned int hashtab_hash_extens | ( | const void * | obj | ) | [static] |
Definition at line 1095 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().
01096 { 01097 const struct ast_exten *ac = obj; 01098 unsigned int x = ast_hashtab_hash_string(ac->exten); 01099 unsigned int y = 0; 01100 if (ac->matchcid) 01101 y = ast_hashtab_hash_string(ac->cidmatch); 01102 return x+y; 01103 }
static unsigned int hashtab_hash_labels | ( | const void * | obj | ) | [static] |
Definition at line 1111 of file pbx.c.
References ast_hashtab_hash_string(), ast_exten::label, and S_OR.
Referenced by ast_add_extension2_lockopt().
01112 { 01113 const struct ast_exten *ac = obj; 01114 return ast_hashtab_hash_string(S_OR(ac->label, "")); 01115 }
static unsigned int hashtab_hash_priority | ( | const void * | obj | ) | [static] |
Definition at line 1105 of file pbx.c.
References ast_hashtab_hash_int(), and ast_exten::priority.
Referenced by ast_add_extension2_lockopt().
01106 { 01107 const struct ast_exten *ac = obj; 01108 return ast_hashtab_hash_int(ac->priority); 01109 }
static int hint_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
static int hint_hash | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 10221 of file pbx.c.
References ast_get_extension_name(), ast_str_case_hash(), and ast_hint::exten.
Referenced by ast_pbx_init().
10222 { 10223 const struct ast_hint *hint = obj; 10224 10225 int res = -1; 10226 10227 if (ast_get_extension_name(hint->exten)) { 10228 res = ast_str_case_hash(ast_get_extension_name(hint->exten)); 10229 } 10230 10231 return res; 10232 }
static int hint_id_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 4443 of file pbx.c.
References CMP_MATCH, CMP_STOP, and ast_state_cb::id.
Referenced by ast_add_hint().
04444 { 04445 const struct ast_state_cb *cb = obj; 04446 int *id = arg; 04447 04448 return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0; 04449 }
static int hints_data_provider_get | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 9821 of file pbx.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_data_add_int(), ast_data_add_node(), ast_data_add_str(), ast_data_remove_node(), ast_data_search_match(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::callbacks, ast_hint::exten, hints, and ast_hint::laststate.
09823 { 09824 struct ast_data *data_hint; 09825 struct ast_hint *hint; 09826 int watchers; 09827 struct ao2_iterator i; 09828 09829 if (ao2_container_count(hints) == 0) { 09830 return 0; 09831 } 09832 09833 i = ao2_iterator_init(hints, 0); 09834 for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) { 09835 watchers = ao2_container_count(hint->callbacks); 09836 data_hint = ast_data_add_node(data_root, "hint"); 09837 if (!data_hint) { 09838 continue; 09839 } 09840 ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten)); 09841 ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten))); 09842 ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten)); 09843 ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate)); 09844 ast_data_add_int(data_hint, "watchers", watchers); 09845 09846 if (!ast_data_search_match(search, data_hint)) { 09847 ast_data_remove_node(data_root, data_hint); 09848 } 09849 } 09850 ao2_iterator_destroy(&i); 09851 09852 return 0; 09853 }
static int include_valid | ( | struct ast_include * | i | ) | [inline, static] |
Definition at line 1450 of file pbx.c.
References ast_check_timing(), ast_include::hastime, and ast_include::timing.
Referenced by pbx_find_extension().
01451 { 01452 if (!i->hastime) 01453 return 1; 01454 01455 return ast_check_timing(&(i->timing)); 01456 }
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 4936 of file pbx.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, countcalls, getloadavg(), LOG_WARNING, maxcalllock, ast_channel::name, option_maxcalls, option_maxload, option_minmemfree, and totalcalls.
Referenced by ast_pbx_run_args(), and ast_pbx_start().
04937 { 04938 int failed = 0; 04939 double curloadavg; 04940 #if defined(HAVE_SYSINFO) 04941 long curfreemem; 04942 struct sysinfo sys_info; 04943 #endif 04944 04945 ast_mutex_lock(&maxcalllock); 04946 if (option_maxcalls) { 04947 if (countcalls >= option_maxcalls) { 04948 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name); 04949 failed = -1; 04950 } 04951 } 04952 if (option_maxload) { 04953 getloadavg(&curloadavg, 1); 04954 if (curloadavg >= option_maxload) { 04955 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg); 04956 failed = -1; 04957 } 04958 } 04959 #if defined(HAVE_SYSINFO) 04960 if (option_minmemfree) { 04961 if (!sysinfo(&sys_info)) { 04962 /* make sure that the free system memory is above the configured low watermark 04963 * convert the amount of freeram from mem_units to MB */ 04964 curfreemem = sys_info.freeram / sys_info.mem_unit; 04965 curfreemem /= 1024 * 1024; 04966 if (curfreemem < option_minmemfree) { 04967 ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree); 04968 failed = -1; 04969 } 04970 } 04971 } 04972 #endif 04973 04974 if (!failed) { 04975 countcalls++; 04976 totalcalls++; 04977 } 04978 ast_mutex_unlock(&maxcalllock); 04979 04980 return failed; 04981 }
static void insert_in_next_chars_alt_char_list | ( | struct match_char ** | parent_ptr, | |
struct match_char * | node | |||
) | [static] |
Definition at line 1867 of file pbx.c.
References match_char::alt_char, and match_char::specificity.
Referenced by add_pattern_node().
01868 { 01869 struct match_char *curr, *lcurr; 01870 01871 /* insert node into the tree at "current", so the alt_char list from current is 01872 sorted in increasing value as you go to the leaves */ 01873 if (!(*parent_ptr)) { 01874 *parent_ptr = node; 01875 return; 01876 } 01877 01878 if ((*parent_ptr)->specificity > node->specificity) { 01879 /* insert at head */ 01880 node->alt_char = (*parent_ptr); 01881 *parent_ptr = node; 01882 return; 01883 } 01884 01885 lcurr = *parent_ptr; 01886 for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) { 01887 if (curr->specificity > node->specificity) { 01888 node->alt_char = curr; 01889 lcurr->alt_char = node; 01890 break; 01891 } 01892 lcurr = curr; 01893 } 01894 01895 if (!curr) { 01896 lcurr->alt_char = node; 01897 } 01898 01899 }
int load_pbx | ( | void | ) |
Provided by pbx.c
Definition at line 9864 of file pbx.c.
References __ast_custom_function_register(), ARRAY_LEN, ast_cli_register_multiple(), ast_data_register_multiple_core, AST_EVENT_DEVICE_STATE, AST_EVENT_IE_END, ast_event_subscribe(), ast_log(), ast_manager_register_xml, ast_register_application2(), ast_taskprocessor_get(), ast_verb, builtins, device_state_cb(), device_state_sub, device_state_tps, EVENT_FLAG_CONFIG, EVENT_FLAG_REPORTING, exception_function, LOG_ERROR, LOG_WARNING, manager_show_dialplan(), pbx_cli, pbx_data_providers, and testtime_function.
Referenced by main().
09865 { 09866 int x; 09867 09868 /* Initialize the PBX */ 09869 ast_verb(1, "Asterisk PBX Core Initializing\n"); 09870 if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) { 09871 ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n"); 09872 } 09873 09874 ast_verb(1, "Registering builtin applications:\n"); 09875 ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli)); 09876 ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers)); 09877 __ast_custom_function_register(&exception_function, NULL); 09878 __ast_custom_function_register(&testtime_function, NULL); 09879 09880 /* Register builtin applications */ 09881 for (x = 0; x < ARRAY_LEN(builtins); x++) { 09882 ast_verb(1, "[%s]\n", builtins[x].name); 09883 if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) { 09884 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 09885 return -1; 09886 } 09887 } 09888 09889 /* Register manager application */ 09890 ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan); 09891 09892 if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL, 09893 AST_EVENT_IE_END))) { 09894 return -1; 09895 } 09896 09897 return 0; 09898 }
static int lookup_name | ( | const char * | s, | |
const char *const | names[], | |||
int | max | |||
) | [static] |
Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values.
Definition at line 7214 of file pbx.c.
Referenced by get_range().
07215 { 07216 int i; 07217 07218 if (names && *s > '9') { 07219 for (i = 0; names[i]; i++) { 07220 if (!strcasecmp(s, names[i])) { 07221 return i; 07222 } 07223 } 07224 } 07225 07226 /* Allow months and weekdays to be specified as numbers, as well */ 07227 if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) { 07228 /* What the array offset would have been: "1" would be at offset 0 */ 07229 return i - 1; 07230 } 07231 return -1; /* error return */ 07232 }
static void manager_dpsendack | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Send ack once.
Definition at line 6371 of file pbx.c.
References astman_send_listack().
Referenced by manager_show_dialplan_helper().
06372 { 06373 astman_send_listack(s, m, "DialPlan list will follow", "start"); 06374 }
static int manager_show_dialplan | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager listing of dial plan.
Definition at line 6517 of file pbx.c.
References ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), exten, and manager_show_dialplan_helper().
Referenced by load_pbx().
06518 { 06519 const char *exten, *context; 06520 const char *id = astman_get_header(m, "ActionID"); 06521 char idtext[256]; 06522 int res; 06523 06524 /* Variables used for different counters */ 06525 struct dialplan_counters counters; 06526 06527 if (!ast_strlen_zero(id)) 06528 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 06529 else 06530 idtext[0] = '\0'; 06531 06532 memset(&counters, 0, sizeof(counters)); 06533 06534 exten = astman_get_header(m, "Extension"); 06535 context = astman_get_header(m, "Context"); 06536 06537 res = manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL); 06538 06539 if (context && !counters.context_existence) { 06540 char errorbuf[BUFSIZ]; 06541 06542 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context); 06543 astman_send_error(s, m, errorbuf); 06544 return 0; 06545 } 06546 if (exten && !counters.extension_existence) { 06547 char errorbuf[BUFSIZ]; 06548 06549 if (context) 06550 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context); 06551 else 06552 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten); 06553 astman_send_error(s, m, errorbuf); 06554 return 0; 06555 } 06556 06557 astman_append(s, "Event: ShowDialPlanComplete\r\n" 06558 "EventList: Complete\r\n" 06559 "ListItems: %d\r\n" 06560 "ListExtensions: %d\r\n" 06561 "ListPriorities: %d\r\n" 06562 "ListContexts: %d\r\n" 06563 "%s" 06564 "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext); 06565 06566 /* everything ok */ 06567 return 0; 06568 }
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 6380 of file pbx.c.
References ast_debug, ast_extension_match(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_app_data(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_priority(), ast_get_extension_registrar(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_log(), AST_MAX_EXTENSION, ast_rdlock_context(), ast_rdlock_contexts(), ast_strlen_zero(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), ast_walk_contexts(), ast_walk_extension_priorities(), astman_append(), astman_send_error(), dialplan_counters::context_existence, dialplan_counters::extension_existence, LOG_WARNING, manager_dpsendack(), PRIORITY_HINT, dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.
Referenced by manager_show_dialplan().
06384 { 06385 struct ast_context *c; 06386 int res = 0, old_total_exten = dpc->total_exten; 06387 06388 if (ast_strlen_zero(exten)) 06389 exten = NULL; 06390 if (ast_strlen_zero(context)) 06391 context = NULL; 06392 06393 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten); 06394 06395 /* try to lock contexts */ 06396 if (ast_rdlock_contexts()) { 06397 astman_send_error(s, m, "Failed to lock contexts"); 06398 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n"); 06399 return -1; 06400 } 06401 06402 c = NULL; /* walk all contexts ... */ 06403 while ( (c = ast_walk_contexts(c)) ) { 06404 struct ast_exten *e; 06405 struct ast_include *i; 06406 struct ast_ignorepat *ip; 06407 06408 if (context && strcmp(ast_get_context_name(c), context) != 0) 06409 continue; /* not the name we want */ 06410 06411 dpc->context_existence = 1; 06412 06413 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c)); 06414 06415 if (ast_rdlock_context(c)) { /* failed to lock */ 06416 ast_debug(3, "manager_show_dialplan: Failed to lock context\n"); 06417 continue; 06418 } 06419 06420 /* XXX note- an empty context is not printed */ 06421 e = NULL; /* walk extensions in context */ 06422 while ( (e = ast_walk_context_extensions(c, e)) ) { 06423 struct ast_exten *p; 06424 06425 /* looking for extension? is this our extension? */ 06426 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) { 06427 /* not the one we are looking for, continue */ 06428 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e)); 06429 continue; 06430 } 06431 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e)); 06432 06433 dpc->extension_existence = 1; 06434 06435 /* may we print context info? */ 06436 dpc->total_context++; 06437 dpc->total_exten++; 06438 06439 p = NULL; /* walk next extension peers */ 06440 while ( (p = ast_walk_extension_priorities(e, p)) ) { 06441 int prio = ast_get_extension_priority(p); 06442 06443 dpc->total_prio++; 06444 if (!dpc->total_items++) 06445 manager_dpsendack(s, m); 06446 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06447 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) ); 06448 06449 /* XXX maybe make this conditional, if p != e ? */ 06450 if (ast_get_extension_label(p)) 06451 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p)); 06452 06453 if (prio == PRIORITY_HINT) { 06454 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p)); 06455 } else { 06456 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)); 06457 } 06458 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e)); 06459 } 06460 } 06461 06462 i = NULL; /* walk included and write info ... */ 06463 while ( (i = ast_walk_context_includes(c, i)) ) { 06464 if (exten) { 06465 /* Check all includes for the requested extension */ 06466 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i); 06467 } else { 06468 if (!dpc->total_items++) 06469 manager_dpsendack(s, m); 06470 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06471 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)); 06472 astman_append(s, "\r\n"); 06473 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i)); 06474 } 06475 } 06476 06477 ip = NULL; /* walk ignore patterns and write info ... */ 06478 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 06479 const char *ipname = ast_get_ignorepat_name(ip); 06480 char ignorepat[AST_MAX_EXTENSION]; 06481 06482 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 06483 if (!exten || ast_extension_match(ignorepat, exten)) { 06484 if (!dpc->total_items++) 06485 manager_dpsendack(s, m); 06486 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06487 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip)); 06488 astman_append(s, "\r\n"); 06489 } 06490 } 06491 if (!rinclude) { 06492 struct ast_sw *sw = NULL; 06493 while ( (sw = ast_walk_context_switches(c, sw)) ) { 06494 if (!dpc->total_items++) 06495 manager_dpsendack(s, m); 06496 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext); 06497 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)); 06498 astman_append(s, "\r\n"); 06499 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw)); 06500 } 06501 } 06502 06503 ast_unlock_context(c); 06504 } 06505 ast_unlock_contexts(); 06506 06507 if (dpc->total_exten == old_total_exten) { 06508 ast_debug(3, "manager_show_dialplan: Found nothing new\n"); 06509 /* Nothing new under the sun */ 06510 return -1; 06511 } else { 06512 return res; 06513 } 06514 }
static int matchcid | ( | const char * | cidpattern, | |
const char * | callerid | |||
) | [static] |
Definition at line 2538 of file pbx.c.
References ast_extension_match(), and ast_strlen_zero().
Referenced by pbx_find_extension().
02539 { 02540 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so 02541 failing to get a number should count as a match, otherwise not */ 02542 02543 if (ast_strlen_zero(callerid)) { 02544 return ast_strlen_zero(cidpattern) ? 1 : 0; 02545 } 02546 02547 return ast_extension_match(cidpattern, callerid); 02548 }
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 1691 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, match_char::is_pattern, ast_exten::label, LOG_NOTICE, NEW_MATCHER_CHK_MATCH, match_char::specificity, update_scoreboard(), and match_char::x.
Referenced by pbx_find_extension().
01692 { 01693 struct match_char *p; /* note minimal stack storage requirements */ 01694 struct ast_exten pattern = { .label = label }; 01695 #ifdef DEBUG_THIS 01696 if (tree) 01697 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action)); 01698 else 01699 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action)); 01700 #endif 01701 for (p = tree; p; p = p->alt_char) { 01702 if (p->is_pattern) { 01703 if (p->x[0] == 'N') { 01704 if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) { 01705 #define NEW_MATCHER_CHK_MATCH \ 01706 if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */ \ 01707 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \ 01708 update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \ 01709 if (!p->deleted) { \ 01710 if (action == E_FINDLABEL) { \ 01711 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \ 01712 ast_debug(4, "Found label in preferred extension\n"); \ 01713 return; \ 01714 } \ 01715 } else { \ 01716 ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten); \ 01717 return; /* the first match, by definition, will be the best, because of the sorted tree */ \ 01718 } \ 01719 } \ 01720 } \ 01721 } 01722 01723 #define NEW_MATCHER_RECURSE \ 01724 if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \ 01725 || p->next_char->x[0] == '!')) { \ 01726 if (*(str + 1) || p->next_char->x[0] == '!') { \ 01727 new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01728 if (score->exten) { \ 01729 ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten); \ 01730 return; /* the first match is all we need */ \ 01731 } \ 01732 } else { \ 01733 new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \ 01734 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \ 01735 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \ 01736 "NULL"); \ 01737 return; /* the first match is all we need */ \ 01738 } \ 01739 } \ 01740 } else if (p->next_char && !*(str + 1)) { \ 01741 score->canmatch = 1; \ 01742 score->canmatch_exten = get_canmatch_exten(p); \ 01743 if (action == E_CANMATCH || action == E_MATCHMORE) { \ 01744 ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \ 01745 return; \ 01746 } \ 01747 } 01748 01749 NEW_MATCHER_CHK_MATCH; 01750 NEW_MATCHER_RECURSE; 01751 } 01752 } else if (p->x[0] == 'Z') { 01753 if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) { 01754 NEW_MATCHER_CHK_MATCH; 01755 NEW_MATCHER_RECURSE; 01756 } 01757 } else if (p->x[0] == 'X') { 01758 if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) { 01759 NEW_MATCHER_CHK_MATCH; 01760 NEW_MATCHER_RECURSE; 01761 } 01762 } else if (p->x[0] == '.' && p->x[1] == 0) { 01763 /* how many chars will the . match against? */ 01764 int i = 0; 01765 const char *str2 = str; 01766 while (*str2 && *str2 != '/') { 01767 str2++; 01768 i++; 01769 } 01770 if (p->exten && *str2 != '/') { 01771 update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p); 01772 if (score->exten) { 01773 ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten); 01774 return; /* the first match is all we need */ 01775 } 01776 } 01777 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01778 new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action); 01779 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01780 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL"); 01781 return; /* the first match is all we need */ 01782 } 01783 } 01784 } else if (p->x[0] == '!' && p->x[1] == 0) { 01785 /* how many chars will the . match against? */ 01786 int i = 1; 01787 const char *str2 = str; 01788 while (*str2 && *str2 != '/') { 01789 str2++; 01790 i++; 01791 } 01792 if (p->exten && *str2 != '/') { 01793 update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p); 01794 if (score->exten) { 01795 ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten); 01796 return; /* the first match is all we need */ 01797 } 01798 } 01799 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { 01800 new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action); 01801 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01802 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01803 return; /* the first match is all we need */ 01804 } 01805 } 01806 } else if (p->x[0] == '/' && p->x[1] == 0) { 01807 /* the pattern in the tree includes the cid match! */ 01808 if (p->next_char && callerid && *callerid) { 01809 new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action); 01810 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { 01811 ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL"); 01812 return; /* the first match is all we need */ 01813 } 01814 } 01815 } else if (strchr(p->x, *str)) { 01816 ast_debug(4, "Nothing strange about this match\n"); 01817 NEW_MATCHER_CHK_MATCH; 01818 NEW_MATCHER_RECURSE; 01819 } 01820 } else if (strchr(p->x, *str)) { 01821 ast_debug(4, "Nothing strange about this match\n"); 01822 NEW_MATCHER_CHK_MATCH; 01823 NEW_MATCHER_RECURSE; 01824 } 01825 } 01826 ast_debug(4, "return at end of func\n"); 01827 }
static int parse_variable_name | ( | char * | var, | |
int * | offset, | |||
int * | length, | |||
int * | isfunc | |||
) | [static] |
extract offset:length from variable name.
Definition at line 2852 of file pbx.c.
Referenced by ast_str_retrieve_variable(), ast_str_substitute_variables_full(), and pbx_substitute_variables_helper_full().
02853 { 02854 int parens = 0; 02855 02856 *offset = 0; 02857 *length = INT_MAX; 02858 *isfunc = 0; 02859 for (; *var; var++) { 02860 if (*var == '(') { 02861 (*isfunc)++; 02862 parens++; 02863 } else if (*var == ')') { 02864 parens--; 02865 } else if (*var == ':' && parens == 0) { 02866 *var++ = '\0'; 02867 sscanf(var, "%30d:%30d", offset, length); 02868 return 1; /* offset:length valid */ 02869 } 02870 } 02871 return 0; 02872 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 9697 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().
09698 { 09699 struct ast_var_t *vardata; 09700 09701 ast_rwlock_wrlock(&globalslock); 09702 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 09703 ast_var_delete(vardata); 09704 ast_rwlock_unlock(&globalslock); 09705 }
const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
const char * | name | |||
) |
Return a pointer to the value of the corresponding channel variable.
This function will return a pointer to the buffer inside the channel variable. This value should only be accessed with the channel locked. If the value needs to be kept around, it should be done by using the following thread-safe code:
const char *var; ast_channel_lock(chan); if ((var = pbx_builtin_getvar_helper(chan, "MYVAR"))) { var = ast_strdupa(var); } ast_channel_unlock(chan);
Definition at line 9459 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_rwlock_rdlock, ast_rwlock_unlock, ast_var_name(), ast_var_value(), globals, and globalslock.
Referenced by _macro_exec(), _while_exec(), agentmonitoroutgoing_exec(), analog_call(), append_channel_vars(), array(), ast_bridge_call(), ast_bridge_timelimit(), ast_call_forward(), ast_channel_connected_line_macro(), ast_channel_redirecting_macro(), ast_eivr_getvariable(), ast_hangup(), ast_monitor_stop(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_run(), confbridge_exec(), crement_function_read(), dahdi_hangup(), dahdi_r2_answer(), dahdi_r2_get_channel_category(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_interpret(), find_by_mark(), findparkinglotname(), func_channel_read(), generic_fax_exec(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_attended_transfer(), local_hangup(), local_read(), login_exec(), macro_fixup(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), park_space_reserve(), pbx_builtin_background(), pbx_builtin_gotoiftime(), queue_exec(), real_ctx(), receivefax_exec(), retrydial_exec(), ring_entry(), run_agi(), sendfax_exec(), set_config_flags(), set_local_info(), sig_pri_call(), sig_pri_hangup(), sip_addheader(), sla_trunk_exec(), speech_background(), try_suggested_sip_codec(), and update_bridge_vars().
09460 { 09461 struct ast_var_t *variables; 09462 const char *ret = NULL; 09463 int i; 09464 struct varshead *places[2] = { NULL, &globals }; 09465 09466 if (!name) 09467 return NULL; 09468 09469 if (chan) { 09470 ast_channel_lock(chan); 09471 places[0] = &chan->varshead; 09472 } 09473 09474 for (i = 0; i < 2; i++) { 09475 if (!places[i]) 09476 continue; 09477 if (places[i] == &globals) 09478 ast_rwlock_rdlock(&globalslock); 09479 AST_LIST_TRAVERSE(places[i], variables, entries) { 09480 if (!strcmp(name, ast_var_name(variables))) { 09481 ret = ast_var_value(variables); 09482 break; 09483 } 09484 } 09485 if (places[i] == &globals) 09486 ast_rwlock_unlock(&globalslock); 09487 if (ret) 09488 break; 09489 } 09490 09491 if (chan) 09492 ast_channel_unlock(chan); 09493 09494 return ret; 09495 }
static int pbx_builtin_gotoif | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 9719 of file pbx.c.
References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_goto(), pbx_checkcondition(), and strsep().
09720 { 09721 char *condition, *branch1, *branch2, *branch; 09722 char *stringp; 09723 09724 if (ast_strlen_zero(data)) { 09725 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n"); 09726 return 0; 09727 } 09728 09729 stringp = ast_strdupa(data); 09730 condition = strsep(&stringp,"?"); 09731 branch1 = strsep(&stringp,":"); 09732 branch2 = strsep(&stringp,""); 09733 branch = pbx_checkcondition(condition) ? branch1 : branch2; 09734 09735 if (ast_strlen_zero(branch)) { 09736 ast_debug(1, "Not taking any branch\n"); 09737 return 0; 09738 } 09739 09740 return pbx_builtin_goto(chan, branch); 09741 }
int pbx_builtin_importvar | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 9655 of file pbx.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), strsep(), value, and VAR_BUF_SIZE.
09656 { 09657 char *name; 09658 char *value; 09659 char *channel; 09660 char tmp[VAR_BUF_SIZE]; 09661 static int deprecation_warning = 0; 09662 09663 if (ast_strlen_zero(data)) { 09664 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n"); 09665 return 0; 09666 } 09667 tmp[0] = 0; 09668 if (!deprecation_warning) { 09669 ast_log(LOG_WARNING, "ImportVar is deprecated. Please use Set(varname=${IMPORT(channel,variable)}) instead.\n"); 09670 deprecation_warning = 1; 09671 } 09672 09673 value = ast_strdupa(data); 09674 name = strsep(&value,"="); 09675 channel = strsep(&value,","); 09676 if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */ 09677 struct ast_channel *chan2 = ast_channel_get_by_name(channel); 09678 if (chan2) { 09679 char *s = alloca(strlen(value) + 4); 09680 if (s) { 09681 sprintf(s, "${%s}", value); 09682 pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1); 09683 } 09684 chan2 = ast_channel_unref(chan2); 09685 } 09686 pbx_builtin_setvar_helper(chan, name, tmp); 09687 } 09688 09689 return(0); 09690 }
static int pbx_builtin_incomplete | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 8993 of file pbx.c.
References __ast_answer(), ast_channel::_state, ast_check_hangup(), AST_PBX_INCOMPLETE, AST_STATE_UP, and ast_strlen_zero().
08994 { 08995 const char *options = data; 08996 int answer = 1; 08997 08998 /* Some channels can receive DTMF in unanswered state; some cannot */ 08999 if (!ast_strlen_zero(options) && strchr(options, 'n')) { 09000 answer = 0; 09001 } 09002 09003 /* If the channel is hungup, stop waiting */ 09004 if (ast_check_hangup(chan)) { 09005 return -1; 09006 } else if (chan->_state != AST_STATE_UP && answer) { 09007 __ast_answer(chan, 0, 1); 09008 } 09009 09010 return AST_PBX_INCOMPLETE; 09011 }
static int pbx_builtin_noop | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
void pbx_builtin_pushvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Add a variable to the channel variable stack, without removing any previously set value.
Definition at line 9497 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, ast_log(), ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_verb, globals, globalslock, and LOG_WARNING.
Referenced by acf_odbc_read(), acf_odbc_write(), and frame_set_var().
09498 { 09499 struct ast_var_t *newvariable; 09500 struct varshead *headp; 09501 09502 if (name[strlen(name)-1] == ')') { 09503 char *function = ast_strdupa(name); 09504 09505 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 09506 ast_func_write(chan, function, value); 09507 return; 09508 } 09509 09510 if (chan) { 09511 ast_channel_lock(chan); 09512 headp = &chan->varshead; 09513 } else { 09514 ast_rwlock_wrlock(&globalslock); 09515 headp = &globals; 09516 } 09517 09518 if (value) { 09519 if (headp == &globals) 09520 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09521 newvariable = ast_var_assign(name, value); 09522 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09523 } 09524 09525 if (chan) 09526 ast_channel_unlock(chan); 09527 else 09528 ast_rwlock_unlock(&globalslock); 09529 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
const char * | reason | |||
) |
Definition at line 3124 of file pbx.c.
References ast_calloc_with_stringfields, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), ast_string_field_set, ast_channel::context, ast_datastore::data, exception_store_info, ast_channel::exten, exten, ast_channel::priority, pbx_exception::priority, and set_ext_pri().
Referenced by __ast_pbx_run().
03125 { 03126 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03127 struct pbx_exception *exception = NULL; 03128 03129 if (!ds) { 03130 ds = ast_datastore_alloc(&exception_store_info, NULL); 03131 if (!ds) 03132 return -1; 03133 if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) { 03134 ast_datastore_free(ds); 03135 return -1; 03136 } 03137 ds->data = exception; 03138 ast_channel_datastore_add(chan, ds); 03139 } else 03140 exception = ds->data; 03141 03142 ast_string_field_set(exception, reason, reason); 03143 ast_string_field_set(exception, context, chan->context); 03144 ast_string_field_set(exception, exten, chan->exten); 03145 exception->priority = chan->priority; 03146 set_ext_pri(chan, "e", 0); 03147 return 0; 03148 }
static int pbx_builtin_saycharacters | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 9780 of file pbx.c.
References ast_say_character_str(), and ast_channel::language.
09781 { 09782 int res = 0; 09783 09784 if (data) 09785 res = ast_say_character_str(chan, data, "", chan->language); 09786 return res; 09787 }
static int pbx_builtin_saydigits | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 9771 of file pbx.c.
References ast_say_digit_str(), and ast_channel::language.
09772 { 09773 int res = 0; 09774 09775 if (data) 09776 res = ast_say_digit_str(chan, data, "", chan->language); 09777 return res; 09778 }
static int pbx_builtin_saynumber | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 9743 of file pbx.c.
References ast_copy_string(), ast_log(), ast_say_number(), ast_strlen_zero(), ast_channel::language, LOG_WARNING, and strsep().
09744 { 09745 char tmp[256]; 09746 char *number = tmp; 09747 char *options; 09748 09749 if (ast_strlen_zero(data)) { 09750 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n"); 09751 return -1; 09752 } 09753 ast_copy_string(tmp, data, sizeof(tmp)); 09754 strsep(&number, ","); 09755 options = strsep(&number, ","); 09756 if (options) { 09757 if ( strcasecmp(options, "f") && strcasecmp(options, "m") && 09758 strcasecmp(options, "c") && strcasecmp(options, "n") ) { 09759 ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n"); 09760 return -1; 09761 } 09762 } 09763 09764 if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) { 09765 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp); 09766 } 09767 09768 return 0; 09769 }
static int pbx_builtin_sayphonetic | ( | struct ast_channel * | , | |
const char * | ||||
) | [static] |
Definition at line 9789 of file pbx.c.
References ast_say_phonetic_str(), and ast_channel::language.
09790 { 09791 int res = 0; 09792 09793 if (data) 09794 res = ast_say_phonetic_str(chan, data, "", chan->language); 09795 return res; 09796 }
int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
struct ast_str ** | buf | |||
) |
Create a human-readable string, specifying all variables and their corresponding values.
chan | Channel from which to read variables | |
buf | Dynamic string in which to place the result (should be allocated with ast_str_create). |
Definition at line 9428 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_reset(), ast_var_name(), ast_var_value(), ast_var_t::entries, LOG_ERROR, total, var, and ast_channel::varshead.
Referenced by ast_var_channels_table(), dumpchan_exec(), handle_show_chanvar(), handle_showchan(), and vars2manager().
09429 { 09430 struct ast_var_t *variables; 09431 const char *var, *val; 09432 int total = 0; 09433 09434 if (!chan) 09435 return 0; 09436 09437 ast_str_reset(*buf); 09438 09439 ast_channel_lock(chan); 09440 09441 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 09442 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 09443 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 09444 ) { 09445 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 09446 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 09447 break; 09448 } else 09449 total++; 09450 } else 09451 break; 09452 } 09453 09454 ast_channel_unlock(chan); 09455 09456 return total; 09457 }
int pbx_builtin_setvar | ( | struct ast_channel * | chan, | |
const char * | data | |||
) |
Parse and set a single channel variable, where the name and value are separated with an '=' character.
Definition at line 9589 of file pbx.c.
References ast_compat_app_set, ast_log(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, pbx_builtin_setvar_helper(), pbx_builtin_setvar_multiple(), strsep(), and value.
Referenced by ast_compile_ael2(), and rpt_exec().
09590 { 09591 char *name, *value, *mydata; 09592 09593 if (ast_compat_app_set) { 09594 return pbx_builtin_setvar_multiple(chan, data); 09595 } 09596 09597 if (ast_strlen_zero(data)) { 09598 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 09599 return 0; 09600 } 09601 09602 mydata = ast_strdupa(data); 09603 name = strsep(&mydata, "="); 09604 value = mydata; 09605 if (!value) { 09606 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 09607 return 0; 09608 } 09609 09610 if (strchr(name, ' ')) { 09611 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 09612 } 09613 09614 pbx_builtin_setvar_helper(chan, name, value); 09615 09616 return 0; 09617 }
int pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Add a variable to the channel variable stack, removing the most recently set value for the same name.
Definition at line 9531 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, ast_channel::name, and ast_channel::uniqueid.
Referenced by __analog_ss_thread(), __oh323_new(), _macro_exec(), _while_exec(), acf_curl_helper(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_setvar(), admin_exec(), agi_exec_full(), aji_status_exec(), analog_ss_thread(), aqm_exec(), array(), ast_bridge_call(), ast_cc_agent_set_interfaces_chanvar(), ast_cel_fabricate_channel_from_event(), ast_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_rtp_instance_set_stats_vars(), ast_set_cc_interfaces_chanvar(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), bridge_play_sounds(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), ccreq_exec(), chanavail_exec(), channel_spy(), commit_exec(), conf_run(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmf(), dahdi_new(), dial_exec_full(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parkinglot(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), my_handle_dtmf(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_exec_full(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), receivefax_exec(), record_exec(), reload_module(), return_exec(), rollback_exec(), rotate_file(), rpt_exec(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), shift_pop(), sig_pri_new_ast_channel(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), start_monitor_exec(), system_exec_helper(), testtime_write(), transfer_exec(), transmit(), tryexec_exec(), unshift_push(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().
09532 { 09533 struct ast_var_t *newvariable; 09534 struct varshead *headp; 09535 const char *nametail = name; 09536 09537 if (name[strlen(name) - 1] == ')') { 09538 char *function = ast_strdupa(name); 09539 09540 return ast_func_write(chan, function, value); 09541 } 09542 09543 if (chan) { 09544 ast_channel_lock(chan); 09545 headp = &chan->varshead; 09546 } else { 09547 ast_rwlock_wrlock(&globalslock); 09548 headp = &globals; 09549 } 09550 09551 /* For comparison purposes, we have to strip leading underscores */ 09552 if (*nametail == '_') { 09553 nametail++; 09554 if (*nametail == '_') 09555 nametail++; 09556 } 09557 09558 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 09559 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 09560 /* there is already such a variable, delete it */ 09561 AST_LIST_REMOVE_CURRENT(entries); 09562 ast_var_delete(newvariable); 09563 break; 09564 } 09565 } 09566 AST_LIST_TRAVERSE_SAFE_END; 09567 09568 if (value) { 09569 if (headp == &globals) 09570 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09571 newvariable = ast_var_assign(name, value); 09572 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09573 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 09574 "Channel: %s\r\n" 09575 "Variable: %s\r\n" 09576 "Value: %s\r\n" 09577 "Uniqueid: %s\r\n", 09578 chan ? chan->name : "none", name, value, 09579 chan ? chan->uniqueid : "none"); 09580 } 09581 09582 if (chan) 09583 ast_channel_unlock(chan); 09584 else 09585 ast_rwlock_unlock(&globalslock); 09586 return 0; 09587 }
int pbx_builtin_setvar_multiple | ( | struct ast_channel * | chan, | |
const char * | data | |||
) |
Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
Definition at line 9619 of file pbx.c.
References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::name, pbx_builtin_setvar_helper(), ast_channel::priority, and value.
Referenced by pbx_builtin_setvar(), queue_function_var(), and set_queue_variables().
09620 { 09621 char *data; 09622 int x; 09623 AST_DECLARE_APP_ARGS(args, 09624 AST_APP_ARG(pair)[24]; 09625 ); 09626 AST_DECLARE_APP_ARGS(pair, 09627 AST_APP_ARG(name); 09628 AST_APP_ARG(value); 09629 ); 09630 09631 if (ast_strlen_zero(vdata)) { 09632 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 09633 return 0; 09634 } 09635 09636 data = ast_strdupa(vdata); 09637 AST_STANDARD_APP_ARGS(args, data); 09638 09639 for (x = 0; x < args.argc; x++) { 09640 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 09641 if (pair.argc == 2) { 09642 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 09643 if (strchr(pair.name, ' ')) 09644 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); 09645 } else if (!chan) { 09646 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 09647 } else { 09648 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 09649 } 09650 } 09651 09652 return 0; 09653 }
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 9707 of file pbx.c.
References ast_strlen_zero().
Referenced by _macro_exec(), _while_exec(), acf_if(), execif_exec(), gosubif_exec(), macroif_exec(), pbx_builtin_gotoif(), and testtime_write().
09708 { 09709 int res; 09710 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 09711 return 0; 09712 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 09713 return res; 09714 } else { /* Strings are true */ 09715 return 1; 09716 } 09717 }
static void pbx_destroy | ( | struct ast_pbx * | p | ) | [static] |
int pbx_exec | ( | struct ast_channel * | c, | |
struct ast_app * | app, | |||
const char * | data | |||
) |
Execute an application.
c | channel to execute on | |
app | which app to execute | |
data | the data passed into the app |
0 | success | |
-1 | failure |
c | Channel |
app | Application |
data | Data for execution |
Definition at line 1378 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), app, ast_channel::appl, ast_cdr_setapp(), AST_CEL_APP_END, AST_CEL_APP_START, ast_cel_report_event(), ast_check_hangup(), ast_log(), ast_opt_dont_warn, ast_strlen_zero(), ast_channel::cdr, ast_channel::data, LOG_WARNING, and S_OR.
Referenced by answer_exec_run(), ast_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), and tryexec_exec().
01381 { 01382 int res; 01383 struct ast_module_user *u = NULL; 01384 const char *saved_c_appl; 01385 const char *saved_c_data; 01386 01387 if (c->cdr && !ast_check_hangup(c)) 01388 ast_cdr_setapp(c->cdr, app->name, data); 01389 01390 /* save channel values */ 01391 saved_c_appl= c->appl; 01392 saved_c_data= c->data; 01393 01394 c->appl = app->name; 01395 c->data = data; 01396 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01397 01398 if (app->module) 01399 u = __ast_module_user_add(app->module, c); 01400 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01401 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01402 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01403 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01404 app->name, (char *) data); 01405 } 01406 res = app->execute(c, S_OR(data, "")); 01407 if (app->module && u) 01408 __ast_module_user_remove(app->module, u); 01409 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01410 /* restore channel values */ 01411 c->appl = saved_c_appl; 01412 c->data = saved_c_data; 01413 return res; 01414 }
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 4021 of file pbx.c.
References ast_exten::app, app, ast_copy_string(), ast_debug, ast_log(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_verb, ast_exten::cached_app, COLOR_BRCYAN, COLOR_BRMAGENTA, ast_channel::context, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCH, E_MATCHMORE, EVENT_FLAG_DIALPLAN, ast_switch::exec, EXT_DATA_SIZE, ast_channel::exten, pbx_find_info::foundcontext, LOG_NOTICE, LOG_WARNING, manager_event, ast_switch::name, ast_channel::name, pbx_exec(), pbx_find_extension(), pbx_findapp(), pbx_substitute_variables(), ast_channel::priority, ast_exten::priority, S_OR, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, pbx_find_info::swo, term_color(), ast_channel::uniqueid, and VERBOSITY_ATLEAST.
Referenced by ast_canmatch_extension(), ast_exists_extension(), ast_findlabel_extension(), ast_findlabel_extension2(), ast_matchmore_extension(), and ast_spawn_extension().
04024 { 04025 struct ast_exten *e; 04026 struct ast_app *app; 04027 int res; 04028 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */ 04029 char passdata[EXT_DATA_SIZE]; 04030 04031 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE); 04032 04033 ast_rdlock_contexts(); 04034 if (found) 04035 *found = 0; 04036 04037 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action); 04038 if (e) { 04039 if (found) 04040 *found = 1; 04041 if (matching_action) { 04042 ast_unlock_contexts(); 04043 return -1; /* success, we found it */ 04044 } else if (action == E_FINDLABEL) { /* map the label to a priority */ 04045 res = e->priority; 04046 ast_unlock_contexts(); 04047 return res; /* the priority we were looking for */ 04048 } else { /* spawn */ 04049 if (!e->cached_app) 04050 e->cached_app = pbx_findapp(e->app); 04051 app = e->cached_app; 04052 ast_unlock_contexts(); 04053 if (!app) { 04054 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); 04055 return -1; 04056 } 04057 if (c->context != context) 04058 ast_copy_string(c->context, context, sizeof(c->context)); 04059 if (c->exten != exten) 04060 ast_copy_string(c->exten, exten, sizeof(c->exten)); 04061 c->priority = priority; 04062 pbx_substitute_variables(passdata, sizeof(passdata), c, e); 04063 #ifdef CHANNEL_TRACE 04064 ast_channel_trace_update(c); 04065 #endif 04066 ast_debug(1, "Launching '%s'\n", app->name); 04067 if (VERBOSITY_ATLEAST(3)) { 04068 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE]; 04069 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n", 04070 exten, context, priority, 04071 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)), 04072 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 04073 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)), 04074 "in new stack"); 04075 } 04076 manager_event(EVENT_FLAG_DIALPLAN, "Newexten", 04077 "Channel: %s\r\n" 04078 "Context: %s\r\n" 04079 "Extension: %s\r\n" 04080 "Priority: %d\r\n" 04081 "Application: %s\r\n" 04082 "AppData: %s\r\n" 04083 "Uniqueid: %s\r\n", 04084 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid); 04085 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */ 04086 } 04087 } else if (q.swo) { /* not found here, but in another switch */ 04088 if (found) 04089 *found = 1; 04090 ast_unlock_contexts(); 04091 if (matching_action) { 04092 return -1; 04093 } else { 04094 if (!q.swo->exec) { 04095 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name); 04096 res = -1; 04097 } 04098 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data); 04099 } 04100 } else { /* not found anywhere, see what happened */ 04101 ast_unlock_contexts(); 04102 /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */ 04103 switch (q.status) { 04104 case STATUS_NO_CONTEXT: 04105 if (!matching_action && !combined_find_spawn) 04106 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, "")); 04107 break; 04108 case STATUS_NO_EXTENSION: 04109 if (!matching_action && !combined_find_spawn) 04110 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, "")); 04111 break; 04112 case STATUS_NO_PRIORITY: 04113 if (!matching_action && !combined_find_spawn) 04114 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, "")); 04115 break; 04116 case STATUS_NO_LABEL: 04117 if (context && !combined_find_spawn) 04118 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, "")); 04119 break; 04120 default: 04121 ast_debug(1, "Shouldn't happen!\n"); 04122 } 04123 04124 return (matching_action) ? 0 : -1; 04125 } 04126 }
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 2550 of file pbx.c.
References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_buffer(), ast_str_size(), ast_str_thread_get(), ast_strdupa, ast_strlen_zero(), ast_walk_context_extensions(), ast_switch::canmatch, scoreboard::canmatch_exten, contexts_table, create_match_char_tree(), ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, scoreboard::exten, extenpatternmatchnew, extension_match_core(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_context::name, ast_sw::name, fake_context::name, new_find_extension(), ast_include::next, scoreboard::node, overrideswitch, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, strsep(), switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().
Referenced by ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), ast_parking_ext_valid(), check_goto(), check_pval_item(), pbx_extension_helper(), pbx_find_extension(), and register_peer_exten().
02554 { 02555 int x, res; 02556 struct ast_context *tmp = NULL; 02557 struct ast_exten *e = NULL, *eroot = NULL; 02558 struct ast_include *i = NULL; 02559 struct ast_sw *sw = NULL; 02560 struct ast_exten pattern = {NULL, }; 02561 struct scoreboard score = {0, }; 02562 struct ast_str *tmpdata = NULL; 02563 02564 pattern.label = label; 02565 pattern.priority = priority; 02566 #ifdef NEED_DEBUG_HERE 02567 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02568 #endif 02569 02570 /* Initialize status if appropriate */ 02571 if (q->stacklen == 0) { 02572 q->status = STATUS_NO_CONTEXT; 02573 q->swo = NULL; 02574 q->data = NULL; 02575 q->foundcontext = NULL; 02576 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02577 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02578 return NULL; 02579 } 02580 02581 /* Check first to see if we've already been checked */ 02582 for (x = 0; x < q->stacklen; x++) { 02583 if (!strcasecmp(q->incstack[x], context)) 02584 return NULL; 02585 } 02586 02587 if (bypass) { /* bypass means we only look there */ 02588 tmp = bypass; 02589 } else { /* look in contexts */ 02590 struct fake_context item; 02591 02592 ast_copy_string(item.name, context, sizeof(item.name)); 02593 02594 tmp = ast_hashtab_lookup(contexts_table, &item); 02595 if (!tmp) { 02596 return NULL; 02597 } 02598 } 02599 02600 if (q->status < STATUS_NO_EXTENSION) 02601 q->status = STATUS_NO_EXTENSION; 02602 02603 /* Do a search for matching extension */ 02604 02605 eroot = NULL; 02606 score.total_specificity = 0; 02607 score.exten = 0; 02608 score.total_length = 0; 02609 if (!tmp->pattern_tree && tmp->root_table) { 02610 create_match_char_tree(tmp); 02611 #ifdef NEED_DEBUG 02612 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 02613 log_match_char_tree(tmp->pattern_tree," "); 02614 #endif 02615 } 02616 #ifdef NEED_DEBUG 02617 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 02618 log_match_char_tree(tmp->pattern_tree, ":: "); 02619 #endif 02620 02621 do { 02622 if (!ast_strlen_zero(overrideswitch)) { 02623 char *osw = ast_strdupa(overrideswitch), *name; 02624 struct ast_switch *asw; 02625 ast_switch_f *aswf = NULL; 02626 char *datap; 02627 int eval = 0; 02628 02629 name = strsep(&osw, "/"); 02630 asw = pbx_findswitch(name); 02631 02632 if (!asw) { 02633 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 02634 break; 02635 } 02636 02637 if (osw && strchr(osw, '$')) { 02638 eval = 1; 02639 } 02640 02641 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02642 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!"); 02643 break; 02644 } else if (eval) { 02645 /* Substitute variables now */ 02646 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02647 datap = ast_str_buffer(tmpdata); 02648 } else { 02649 datap = osw; 02650 } 02651 02652 /* equivalent of extension_match_core() at the switch level */ 02653 if (action == E_CANMATCH) 02654 aswf = asw->canmatch; 02655 else if (action == E_MATCHMORE) 02656 aswf = asw->matchmore; 02657 else /* action == E_MATCH */ 02658 aswf = asw->exists; 02659 if (!aswf) { 02660 res = 0; 02661 } else { 02662 if (chan) { 02663 ast_autoservice_start(chan); 02664 } 02665 res = aswf(chan, context, exten, priority, callerid, datap); 02666 if (chan) { 02667 ast_autoservice_stop(chan); 02668 } 02669 } 02670 if (res) { /* Got a match */ 02671 q->swo = asw; 02672 q->data = datap; 02673 q->foundcontext = context; 02674 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02675 return NULL; 02676 } 02677 } 02678 } while (0); 02679 02680 if (extenpatternmatchnew) { 02681 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02682 eroot = score.exten; 02683 02684 if (score.last_char == '!' && action == E_MATCHMORE) { 02685 /* We match an extension ending in '!'. 02686 * The decision in this case is final and is NULL (no match). 02687 */ 02688 #ifdef NEED_DEBUG_HERE 02689 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02690 #endif 02691 return NULL; 02692 } 02693 02694 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02695 q->status = STATUS_SUCCESS; 02696 #ifdef NEED_DEBUG_HERE 02697 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02698 #endif 02699 return score.canmatch_exten; 02700 } 02701 02702 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02703 if (score.node) { 02704 struct ast_exten *z = trie_find_next_match(score.node); 02705 if (z) { 02706 #ifdef NEED_DEBUG_HERE 02707 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02708 #endif 02709 } else { 02710 if (score.canmatch_exten) { 02711 #ifdef NEED_DEBUG_HERE 02712 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02713 #endif 02714 return score.canmatch_exten; 02715 } else { 02716 #ifdef NEED_DEBUG_HERE 02717 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02718 #endif 02719 } 02720 } 02721 return z; 02722 } 02723 #ifdef NEED_DEBUG_HERE 02724 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02725 #endif 02726 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02727 } 02728 02729 if (eroot) { 02730 /* found entry, now look for the right priority */ 02731 if (q->status < STATUS_NO_PRIORITY) 02732 q->status = STATUS_NO_PRIORITY; 02733 e = NULL; 02734 if (action == E_FINDLABEL && label ) { 02735 if (q->status < STATUS_NO_LABEL) 02736 q->status = STATUS_NO_LABEL; 02737 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02738 } else { 02739 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02740 } 02741 if (e) { /* found a valid match */ 02742 q->status = STATUS_SUCCESS; 02743 q->foundcontext = context; 02744 #ifdef NEED_DEBUG_HERE 02745 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 02746 #endif 02747 return e; 02748 } 02749 } 02750 } else { /* the old/current default exten pattern match algorithm */ 02751 02752 /* scan the list trying to match extension and CID */ 02753 eroot = NULL; 02754 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 02755 int match = extension_match_core(eroot->exten, exten, action); 02756 /* 0 on fail, 1 on match, 2 on earlymatch */ 02757 02758 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 02759 continue; /* keep trying */ 02760 if (match == 2 && action == E_MATCHMORE) { 02761 /* We match an extension ending in '!'. 02762 * The decision in this case is final and is NULL (no match). 02763 */ 02764 return NULL; 02765 } 02766 /* found entry, now look for the right priority */ 02767 if (q->status < STATUS_NO_PRIORITY) 02768 q->status = STATUS_NO_PRIORITY; 02769 e = NULL; 02770 if (action == E_FINDLABEL && label ) { 02771 if (q->status < STATUS_NO_LABEL) 02772 q->status = STATUS_NO_LABEL; 02773 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02774 } else { 02775 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02776 } 02777 if (e) { /* found a valid match */ 02778 q->status = STATUS_SUCCESS; 02779 q->foundcontext = context; 02780 return e; 02781 } 02782 } 02783 } 02784 02785 /* Check alternative switches */ 02786 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 02787 struct ast_switch *asw = pbx_findswitch(sw->name); 02788 ast_switch_f *aswf = NULL; 02789 char *datap; 02790 02791 if (!asw) { 02792 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 02793 continue; 02794 } 02795 02796 /* Substitute variables now */ 02797 if (sw->eval) { 02798 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02799 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 02800 continue; 02801 } 02802 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02803 } 02804 02805 /* equivalent of extension_match_core() at the switch level */ 02806 if (action == E_CANMATCH) 02807 aswf = asw->canmatch; 02808 else if (action == E_MATCHMORE) 02809 aswf = asw->matchmore; 02810 else /* action == E_MATCH */ 02811 aswf = asw->exists; 02812 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 02813 if (!aswf) 02814 res = 0; 02815 else { 02816 if (chan) 02817 ast_autoservice_start(chan); 02818 res = aswf(chan, context, exten, priority, callerid, datap); 02819 if (chan) 02820 ast_autoservice_stop(chan); 02821 } 02822 if (res) { /* Got a match */ 02823 q->swo = asw; 02824 q->data = datap; 02825 q->foundcontext = context; 02826 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02827 return NULL; 02828 } 02829 } 02830 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 02831 /* Now try any includes we have in this context */ 02832 for (i = tmp->includes; i; i = i->next) { 02833 if (include_valid(i)) { 02834 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 02835 #ifdef NEED_DEBUG_HERE 02836 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 02837 #endif 02838 return e; 02839 } 02840 if (q->swo) 02841 return NULL; 02842 } 02843 } 02844 return NULL; 02845 }
struct ast_app* pbx_findapp | ( | const char * | app | ) |
Look up an application.
app | name of the app |
Definition at line 1422 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_app_run_macro(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), do_magic_pickup(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), and tryexec_exec().
01423 { 01424 struct ast_app *tmp; 01425 01426 AST_RWLIST_RDLOCK(&apps); 01427 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01428 if (!strcasecmp(tmp->name, app)) 01429 break; 01430 } 01431 AST_RWLIST_UNLOCK(&apps); 01432 01433 return tmp; 01434 }
static struct ast_switch* pbx_findswitch | ( | const char * | sw | ) | [static] |
Definition at line 1436 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().
01437 { 01438 struct ast_switch *asw; 01439 01440 AST_RWLIST_RDLOCK(&switches); 01441 AST_RWLIST_TRAVERSE(&switches, asw, list) { 01442 if (!strcasecmp(asw->name, sw)) 01443 break; 01444 } 01445 AST_RWLIST_UNLOCK(&switches); 01446 01447 return asw; 01448 }
static int pbx_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string, | |||
int | async | |||
) | [static] |
Definition at line 10137 of file pbx.c.
References ast_async_goto(), ast_explicit_goto(), ast_findlabel_extension(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_channel::caller, ast_channel::context, ast_channel::exten, ast_party_caller::id, LOG_WARNING, ast_party_id::number, ast_channel::priority, S_COR, ast_party_number::str, strsep(), and ast_party_number::valid.
Referenced by ast_async_parseable_goto(), and ast_parseable_goto().
10138 { 10139 char *exten, *pri, *context; 10140 char *stringp; 10141 int ipri; 10142 int mode = 0; 10143 10144 if (ast_strlen_zero(goto_string)) { 10145 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n"); 10146 return -1; 10147 } 10148 stringp = ast_strdupa(goto_string); 10149 context = strsep(&stringp, ","); /* guaranteed non-null */ 10150 exten = strsep(&stringp, ","); 10151 pri = strsep(&stringp, ","); 10152 if (!exten) { /* Only a priority in this one */ 10153 pri = context; 10154 exten = NULL; 10155 context = NULL; 10156 } else if (!pri) { /* Only an extension and priority in this one */ 10157 pri = exten; 10158 exten = context; 10159 context = NULL; 10160 } 10161 if (*pri == '+') { 10162 mode = 1; 10163 pri++; 10164 } else if (*pri == '-') { 10165 mode = -1; 10166 pri++; 10167 } 10168 if (sscanf(pri, "%30d", &ipri) != 1) { 10169 ipri = ast_findlabel_extension(chan, context ? context : chan->context, 10170 exten ? exten : chan->exten, pri, 10171 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)); 10172 if (ipri < 1) { 10173 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 10174 return -1; 10175 } else 10176 mode = 0; 10177 } 10178 /* At this point we have a priority and maybe an extension and a context */ 10179 10180 if (mode) 10181 ipri = chan->priority + (ipri * mode); 10182 10183 if (async) 10184 ast_async_goto(chan, context, exten, ipri); 10185 else 10186 ast_explicit_goto(chan, context, exten, ipri); 10187 10188 return 0; 10189 10190 }
void pbx_retrieve_variable | ( | struct ast_channel * | c, | |
const char * | var, | |||
char ** | ret, | |||
char * | workspace, | |||
int | workspacelen, | |||
struct varshead * | headp | |||
) |
Retrieve the value of a builtin variable or variable from the channel variable stack.
Definition at line 2975 of file pbx.c.
References ast_copy_string(), ast_free, ast_str_buffer(), ast_str_create(), ast_str_retrieve_variable(), and str.
Referenced by action_getvar(), action_status(), handle_getvariable(), lua_get_variable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
02976 { 02977 struct ast_str *str = ast_str_create(16); 02978 const char *cret; 02979 02980 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 02981 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 02982 *ret = cret ? workspace : NULL; 02983 ast_free(str); 02984 }
int pbx_set_autofallthrough | ( | int | newval | ) |
Set "autofallthrough" flag, if newval is <0, does not actually set. If set to 1, sets to auto fall through. If newval set to 0, sets to no auto fall through (reads extension instead). Returns previous value.
Definition at line 5077 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05078 { 05079 int oldval = autofallthrough; 05080 autofallthrough = newval; 05081 return oldval; 05082 }
int pbx_set_extenpatternmatchnew | ( | int | newval | ) |
Set "extenpatternmatchnew" flag, if newval is <0, does not actually set. If set to 1, sets to use the new Trie-based pattern matcher. If newval set to 0, sets to use the old linear-search algorithm. Returns previous value.
Definition at line 5084 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05085 { 05086 int oldval = extenpatternmatchnew; 05087 extenpatternmatchnew = newval; 05088 return oldval; 05089 }
void pbx_set_overrideswitch | ( | const char * | newval | ) |
Set "overrideswitch" field. If set and of nonzero length, all contexts will be tried directly through the named switch prior to any other matching within that context.
Definition at line 5091 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05092 { 05093 if (overrideswitch) { 05094 ast_free(overrideswitch); 05095 } 05096 if (!ast_strlen_zero(newval)) { 05097 overrideswitch = ast_strdup(newval); 05098 } else { 05099 overrideswitch = NULL; 05100 } 05101 }
static void pbx_substitute_variables | ( | char * | passdata, | |
int | datalen, | |||
struct ast_channel * | c, | |||
struct ast_exten * | e | |||
) | [static] |
Definition at line 3984 of file pbx.c.
References ast_copy_string(), ast_exten::data, and pbx_substitute_variables_helper().
Referenced by pbx_extension_helper().
03985 { 03986 const char *tmp; 03987 03988 /* Nothing more to do */ 03989 if (!e->data) { 03990 *passdata = '\0'; 03991 return; 03992 } 03993 03994 /* No variables or expressions in e->data, so why scan it? */ 03995 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) { 03996 ast_copy_string(passdata, e->data, datalen); 03997 return; 03998 } 03999 04000 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1); 04001 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 3972 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by add_extensions(), ast_add_extension2_lockopt(), function_eval(), get_manager_event_info(), get_mapping_weight(), import_helper(), launch_monitor_thread(), manager_log(), pbx_builtin_importvar(), pbx_find_extension(), pbx_load_config(), pbx_substitute_variables(), rotate_file(), rpt_do_lstats(), rpt_exec(), substituted(), and write_cdr().
03973 { 03974 size_t used; 03975 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 03976 }
void pbx_substitute_variables_helper_full | ( | struct ast_channel * | c, | |
struct varshead * | headp, | |||
const char * | cp1, | |||
char * | cp2, | |||
int | count, | |||
size_t * | used | |||
) |
Definition at line 3776 of file pbx.c.
References ast_channel_release(), ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_expr(), ast_func_read(), ast_log(), ast_strlen_zero(), len(), LOG_ERROR, LOG_WARNING, parse_variable_name(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full(), substring(), var, VAR_BUF_SIZE, and ast_channel::varshead.
Referenced by pbx_substitute_variables_helper(), pbx_substitute_variables_helper_full(), and pbx_substitute_variables_varshead().
03777 { 03778 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 03779 char *cp4 = NULL; 03780 const char *tmp, *whereweare, *orig_cp2 = cp2; 03781 int length, offset, offset2, isfunction; 03782 char *workspace = NULL; 03783 char *ltmp = NULL, *var = NULL; 03784 char *nextvar, *nextexp, *nextthing; 03785 char *vars, *vare; 03786 int pos, brackets, needsub, len; 03787 03788 *cp2 = 0; /* just in case nothing ends up there */ 03789 whereweare=tmp=cp1; 03790 while (!ast_strlen_zero(whereweare) && count) { 03791 /* Assume we're copying the whole remaining string */ 03792 pos = strlen(whereweare); 03793 nextvar = NULL; 03794 nextexp = NULL; 03795 nextthing = strchr(whereweare, '$'); 03796 if (nextthing) { 03797 switch (nextthing[1]) { 03798 case '{': 03799 nextvar = nextthing; 03800 pos = nextvar - whereweare; 03801 break; 03802 case '[': 03803 nextexp = nextthing; 03804 pos = nextexp - whereweare; 03805 break; 03806 default: 03807 pos = 1; 03808 } 03809 } 03810 03811 if (pos) { 03812 /* Can't copy more than 'count' bytes */ 03813 if (pos > count) 03814 pos = count; 03815 03816 /* Copy that many bytes */ 03817 memcpy(cp2, whereweare, pos); 03818 03819 count -= pos; 03820 cp2 += pos; 03821 whereweare += pos; 03822 *cp2 = 0; 03823 } 03824 03825 if (nextvar) { 03826 /* We have a variable. Find the start and end, and determine 03827 if we are going to have to recursively call ourselves on the 03828 contents */ 03829 vars = vare = nextvar + 2; 03830 brackets = 1; 03831 needsub = 0; 03832 03833 /* Find the end of it */ 03834 while (brackets && *vare) { 03835 if ((vare[0] == '$') && (vare[1] == '{')) { 03836 needsub++; 03837 } else if (vare[0] == '{') { 03838 brackets++; 03839 } else if (vare[0] == '}') { 03840 brackets--; 03841 } else if ((vare[0] == '$') && (vare[1] == '[')) 03842 needsub++; 03843 vare++; 03844 } 03845 if (brackets) 03846 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 03847 len = vare - vars - 1; 03848 03849 /* Skip totally over variable string */ 03850 whereweare += (len + 3); 03851 03852 if (!var) 03853 var = alloca(VAR_BUF_SIZE); 03854 03855 /* Store variable name (and truncate) */ 03856 ast_copy_string(var, vars, len + 1); 03857 03858 /* Substitute if necessary */ 03859 if (needsub) { 03860 size_t used; 03861 if (!ltmp) 03862 ltmp = alloca(VAR_BUF_SIZE); 03863 03864 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 03865 vars = ltmp; 03866 } else { 03867 vars = var; 03868 } 03869 03870 if (!workspace) 03871 workspace = alloca(VAR_BUF_SIZE); 03872 03873 workspace[0] = '\0'; 03874 03875 parse_variable_name(vars, &offset, &offset2, &isfunction); 03876 if (isfunction) { 03877 /* Evaluate function */ 03878 if (c || !headp) 03879 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03880 else { 03881 struct varshead old; 03882 struct ast_channel *c = ast_dummy_channel_alloc(); 03883 if (c) { 03884 memcpy(&old, &c->varshead, sizeof(old)); 03885 memcpy(&c->varshead, headp, sizeof(c->varshead)); 03886 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03887 /* Don't deallocate the varshead that was passed in */ 03888 memcpy(&c->varshead, &old, sizeof(c->varshead)); 03889 c = ast_channel_release(c); 03890 } else { 03891 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03892 } 03893 } 03894 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03895 } else { 03896 /* Retrieve variable value */ 03897 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 03898 } 03899 if (cp4) { 03900 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 03901 03902 length = strlen(cp4); 03903 if (length > count) 03904 length = count; 03905 memcpy(cp2, cp4, length); 03906 count -= length; 03907 cp2 += length; 03908 *cp2 = 0; 03909 } 03910 } else if (nextexp) { 03911 /* We have an expression. Find the start and end, and determine 03912 if we are going to have to recursively call ourselves on the 03913 contents */ 03914 vars = vare = nextexp + 2; 03915 brackets = 1; 03916 needsub = 0; 03917 03918 /* Find the end of it */ 03919 while (brackets && *vare) { 03920 if ((vare[0] == '$') && (vare[1] == '[')) { 03921 needsub++; 03922 brackets++; 03923 vare++; 03924 } else if (vare[0] == '[') { 03925 brackets++; 03926 } else if (vare[0] == ']') { 03927 brackets--; 03928 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03929 needsub++; 03930 vare++; 03931 } 03932 vare++; 03933 } 03934 if (brackets) 03935 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03936 len = vare - vars - 1; 03937 03938 /* Skip totally over expression */ 03939 whereweare += (len + 3); 03940 03941 if (!var) 03942 var = alloca(VAR_BUF_SIZE); 03943 03944 /* Store variable name (and truncate) */ 03945 ast_copy_string(var, vars, len + 1); 03946 03947 /* Substitute if necessary */ 03948 if (needsub) { 03949 size_t used; 03950 if (!ltmp) 03951 ltmp = alloca(VAR_BUF_SIZE); 03952 03953 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 03954 vars = ltmp; 03955 } else { 03956 vars = var; 03957 } 03958 03959 length = ast_expr(vars, cp2, count, c); 03960 03961 if (length) { 03962 ast_debug(1, "Expression result is '%s'\n", cp2); 03963 count -= length; 03964 cp2 += length; 03965 *cp2 = 0; 03966 } 03967 } 03968 } 03969 *used = cp2 - orig_cp2; 03970 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 3978 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by dundi_lookup_local(), and loopback_subst().
03979 { 03980 size_t used; 03981 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 03982 }
static void* pbx_thread | ( | void * | data | ) | [static] |
Definition at line 5005 of file pbx.c.
References __ast_pbx_run(), and decrease_call_count().
Referenced by ast_pbx_start().
05006 { 05007 /* Oh joyeous kernel, we're a new thread, with nothing to do but 05008 answer this channel and get it going. 05009 */ 05010 /* NOTE: 05011 The launcher of this function _MUST_ increment 'countcalls' 05012 before invoking the function; it will be decremented when the 05013 PBX has finished running on the channel 05014 */ 05015 struct ast_channel *c = data; 05016 05017 __ast_pbx_run(c, NULL); 05018 decrease_call_count(); 05019 05020 pthread_exit(NULL); 05021 05022 return NULL; 05023 }
static void print_app_docs | ( | struct ast_app * | aa, | |
int | fd | |||
) | [static] |
Definition at line 5623 of file pbx.c.
References ast_app::arguments, ast_cli(), ast_free, ast_malloc, AST_MAX_APP, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, ast_xmldoc_printable(), COLOR_CYAN, COLOR_MAGENTA, ast_app::description, ast_app::docsrc, ast_app::name, S_OR, ast_app::seealso, ast_app::synopsis, synopsis, ast_app::syntax, and term_color().
Referenced by handle_show_application().
05624 { 05625 /* Maximum number of characters added by terminal coloring is 22 */ 05626 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40]; 05627 char seealsotitle[40]; 05628 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL; 05629 char *seealso = NULL; 05630 int syntax_size, synopsis_size, description_size, arguments_size, seealso_size; 05631 05632 snprintf(info, sizeof(info), "\n -= Info about application '%s' =- \n\n", aa->name); 05633 term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle)); 05634 05635 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 05636 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40); 05637 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 05638 term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 05639 term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40); 05640 05641 #ifdef AST_XML_DOCS 05642 if (aa->docsrc == AST_XML_DOC) { 05643 description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1); 05644 arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1); 05645 synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1); 05646 seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1); 05647 05648 if (!synopsis || !description || !arguments || !seealso) { 05649 goto return_cleanup; 05650 } 05651 } else 05652 #endif 05653 { 05654 synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05655 synopsis = ast_malloc(synopsis_size); 05656 05657 description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05658 description = ast_malloc(description_size); 05659 05660 arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05661 arguments = ast_malloc(arguments_size); 05662 05663 seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05664 seealso = ast_malloc(seealso_size); 05665 05666 if (!synopsis || !description || !arguments || !seealso) { 05667 goto return_cleanup; 05668 } 05669 05670 term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size); 05671 term_color(description, S_OR(aa->description, "Not available"), COLOR_CYAN, 0, description_size); 05672 term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size); 05673 term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size); 05674 } 05675 05676 /* Handle the syntax the same for both XML and raw docs */ 05677 syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS; 05678 if (!(syntax = ast_malloc(syntax_size))) { 05679 goto return_cleanup; 05680 } 05681 term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size); 05682 05683 ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n", 05684 infotitle, syntitle, synopsis, destitle, description, 05685 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso); 05686 05687 return_cleanup: 05688 ast_free(description); 05689 ast_free(arguments); 05690 ast_free(synopsis); 05691 ast_free(seealso); 05692 ast_free(syntax); 05693 }
static void print_ext | ( | struct ast_exten * | e, | |
char * | buf, | |||
int | buflen | |||
) | [static] |
helper function to print an extension
Definition at line 6030 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().
06031 { 06032 int prio = ast_get_extension_priority(e); 06033 if (prio == PRIORITY_HINT) { 06034 snprintf(buf, buflen, "hint: %s", 06035 ast_get_extension_app(e)); 06036 } else { 06037 snprintf(buf, buflen, "%d. %s(%s)", 06038 prio, ast_get_extension_app(e), 06039 (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : "")); 06040 } 06041 }
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 4612 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().
04613 { 04614 ast_channel_lock(c); 04615 ast_copy_string(c->exten, exten, sizeof(c->exten)); 04616 c->priority = pri; 04617 ast_channel_unlock(c); 04618 }
static int show_debug_helper | ( | int | fd, | |
const char * | context, | |||
const char * | exten, | |||
struct dialplan_counters * | dpc, | |||
struct ast_include * | rinclude, | |||
int | includecount, | |||
const char * | includes[] | |||
) | [static] |
Definition at line 6195 of file pbx.c.
References ast_cli(), ast_exists_extension(), ast_get_context_name(), ast_get_context_registrar(), ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_contexts(), cli_match_char_tree(), dialplan_counters::context_existence, ast_context::name, ast_context::pattern_tree, dialplan_counters::total_context, and dialplan_counters::total_exten.
Referenced by handle_debug_dialplan().
06196 { 06197 struct ast_context *c = NULL; 06198 int res = 0, old_total_exten = dpc->total_exten; 06199 06200 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n"); 06201 06202 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n"); 06203 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n"); 06204 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n"); 06205 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n"); 06206 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n"); 06207 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n"); 06208 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n"); 06209 ast_rdlock_contexts(); 06210 06211 /* walk all contexts ... */ 06212 while ( (c = ast_walk_contexts(c)) ) { 06213 int context_info_printed = 0; 06214 06215 if (context && strcmp(ast_get_context_name(c), context)) 06216 continue; /* skip this one, name doesn't match */ 06217 06218 dpc->context_existence = 1; 06219 06220 if (!c->pattern_tree) 06221 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */ 06222 06223 ast_rdlock_context(c); 06224 06225 dpc->total_context++; 06226 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06227 ast_get_context_name(c), ast_get_context_registrar(c)); 06228 context_info_printed = 1; 06229 06230 if (c->pattern_tree) 06231 { 06232 cli_match_char_tree(c->pattern_tree, " ", fd); 06233 } else { 06234 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n"); 06235 } 06236 06237 ast_unlock_context(c); 06238 06239 /* if we print something in context, make an empty line */ 06240 if (context_info_printed) 06241 ast_cli(fd, "\n"); 06242 } 06243 ast_unlock_contexts(); 06244 06245 return (dpc->total_exten == old_total_exten) ? -1 : res; 06246 }
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 6044 of file pbx.c.
References ast_cli(), ast_extension_match(), ast_get_context_name(), ast_get_context_registrar(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_registrar(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_log(), AST_MAX_EXTENSION, AST_PBX_MAX_STACK, ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), ast_walk_contexts(), ast_walk_extension_priorities(), buf2, ast_exten::cidmatch, dialplan_counters::context_existence, el, dialplan_counters::extension_existence, LOG_WARNING, ast_exten::matchcid, print_ext(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.
Referenced by handle_show_dialplan().
06045 { 06046 struct ast_context *c = NULL; 06047 int res = 0, old_total_exten = dpc->total_exten; 06048 06049 ast_rdlock_contexts(); 06050 06051 /* walk all contexts ... */ 06052 while ( (c = ast_walk_contexts(c)) ) { 06053 struct ast_exten *e; 06054 struct ast_include *i; 06055 struct ast_ignorepat *ip; 06056 char buf[256], buf2[256]; 06057 int context_info_printed = 0; 06058 06059 if (context && strcmp(ast_get_context_name(c), context)) 06060 continue; /* skip this one, name doesn't match */ 06061 06062 dpc->context_existence = 1; 06063 06064 ast_rdlock_context(c); 06065 06066 /* are we looking for exten too? if yes, we print context 06067 * only if we find our extension. 06068 * Otherwise print context even if empty ? 06069 * XXX i am not sure how the rinclude is handled. 06070 * I think it ought to go inside. 06071 */ 06072 if (!exten) { 06073 dpc->total_context++; 06074 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06075 ast_get_context_name(c), ast_get_context_registrar(c)); 06076 context_info_printed = 1; 06077 } 06078 06079 /* walk extensions ... */ 06080 e = NULL; 06081 while ( (e = ast_walk_context_extensions(c, e)) ) { 06082 struct ast_exten *p; 06083 06084 if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) 06085 continue; /* skip, extension match failed */ 06086 06087 dpc->extension_existence = 1; 06088 06089 /* may we print context info? */ 06090 if (!context_info_printed) { 06091 dpc->total_context++; 06092 if (rinclude) { /* TODO Print more info about rinclude */ 06093 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n", 06094 ast_get_context_name(c), ast_get_context_registrar(c)); 06095 } else { 06096 ast_cli(fd, "[ Context '%s' created by '%s' ]\n", 06097 ast_get_context_name(c), ast_get_context_registrar(c)); 06098 } 06099 context_info_printed = 1; 06100 } 06101 dpc->total_prio++; 06102 06103 /* write extension name and first peer */ 06104 if (e->matchcid) 06105 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch); 06106 else 06107 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e)); 06108 06109 print_ext(e, buf2, sizeof(buf2)); 06110 06111 ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2, 06112 ast_get_extension_registrar(e)); 06113 06114 dpc->total_exten++; 06115 /* walk next extension peers */ 06116 p = e; /* skip the first one, we already got it */ 06117 while ( (p = ast_walk_extension_priorities(e, p)) ) { 06118 const char *el = ast_get_extension_label(p); 06119 dpc->total_prio++; 06120 if (el) 06121 snprintf(buf, sizeof(buf), " [%s]", el); 06122 else 06123 buf[0] = '\0'; 06124 print_ext(p, buf2, sizeof(buf2)); 06125 06126 ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2, 06127 ast_get_extension_registrar(p)); 06128 } 06129 } 06130 06131 /* walk included and write info ... */ 06132 i = NULL; 06133 while ( (i = ast_walk_context_includes(c, i)) ) { 06134 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i)); 06135 if (exten) { 06136 /* Check all includes for the requested extension */ 06137 if (includecount >= AST_PBX_MAX_STACK) { 06138 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n"); 06139 } else { 06140 int dupe = 0; 06141 int x; 06142 for (x = 0; x < includecount; x++) { 06143 if (!strcasecmp(includes[x], ast_get_include_name(i))) { 06144 dupe++; 06145 break; 06146 } 06147 } 06148 if (!dupe) { 06149 includes[includecount] = ast_get_include_name(i); 06150 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes); 06151 } else { 06152 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context); 06153 } 06154 } 06155 } else { 06156 ast_cli(fd, " Include => %-45s [%s]\n", 06157 buf, ast_get_include_registrar(i)); 06158 } 06159 } 06160 06161 /* walk ignore patterns and write info ... */ 06162 ip = NULL; 06163 while ( (ip = ast_walk_context_ignorepats(c, ip)) ) { 06164 const char *ipname = ast_get_ignorepat_name(ip); 06165 char ignorepat[AST_MAX_EXTENSION]; 06166 snprintf(buf, sizeof(buf), "'%s'", ipname); 06167 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname); 06168 if (!exten || ast_extension_match(ignorepat, exten)) { 06169 ast_cli(fd, " Ignore pattern => %-45s [%s]\n", 06170 buf, ast_get_ignorepat_registrar(ip)); 06171 } 06172 } 06173 if (!rinclude) { 06174 struct ast_sw *sw = NULL; 06175 while ( (sw = ast_walk_context_switches(c, sw)) ) { 06176 snprintf(buf, sizeof(buf), "'%s/%s'", 06177 ast_get_switch_name(sw), 06178 ast_get_switch_data(sw)); 06179 ast_cli(fd, " Alt. Switch => %-45s [%s]\n", 06180 buf, ast_get_switch_registrar(sw)); 06181 } 06182 } 06183 06184 ast_unlock_context(c); 06185 06186 /* if we print something in context, make an empty line */ 06187 if (context_info_printed) 06188 ast_cli(fd, "\n"); 06189 } 06190 ast_unlock_contexts(); 06191 06192 return (dpc->total_exten == old_total_exten) ? -1 : res; 06193 }
static int statecbs_cmp | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 10242 of file pbx.c.
References ast_state_cb::callback, CMP_MATCH, and CMP_STOP.
Referenced by ast_pbx_init().
10243 { 10244 const struct ast_state_cb *state_cb = obj; 10245 const struct ast_state_cb *callback = arg; 10246 10247 return (state_cb == callback) ? CMP_MATCH | CMP_STOP : 0; 10248 }
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 2885 of file pbx.c.
References ast_copy_string().
Referenced by pbx_substitute_variables_helper_full().
02886 { 02887 char *ret = workspace; 02888 int lr; /* length of the input string after the copy */ 02889 02890 ast_copy_string(workspace, value, workspace_len); /* always make a copy */ 02891 02892 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ 02893 02894 /* Quick check if no need to do anything */ 02895 if (offset == 0 && length >= lr) /* take the whole string */ 02896 return ret; 02897 02898 if (offset < 0) { /* translate negative offset into positive ones */ 02899 offset = lr + offset; 02900 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */ 02901 offset = 0; 02902 } 02903 02904 /* too large offset result in empty string so we know what to return */ 02905 if (offset >= lr) 02906 return ret + lr; /* the final '\0' */ 02907 02908 ret += offset; /* move to the start position */ 02909 if (length >= 0 && length < lr - offset) /* truncate if necessary */ 02910 ret[length] = '\0'; 02911 else if (length < 0) { 02912 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */ 02913 ret[lr + length - offset] = '\0'; 02914 else 02915 ret[0] = '\0'; 02916 } 02917 02918 return ret; 02919 }
static struct ast_exten* trie_find_next_match | ( | struct match_char * | node | ) | [static] |
Definition at line 1632 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().
01633 { 01634 struct match_char *m3; 01635 struct match_char *m4; 01636 struct ast_exten *e3; 01637 01638 if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */ 01639 return node->exten; 01640 } 01641 01642 if (node && node->x[0] == '!' && !node->x[1]) { 01643 return node->exten; 01644 } 01645 01646 if (!node || !node->next_char) { 01647 return NULL; 01648 } 01649 01650 m3 = node->next_char; 01651 01652 if (m3->exten) { 01653 return m3->exten; 01654 } 01655 for (m4 = m3->alt_char; m4; m4 = m4->alt_char) { 01656 if (m4->exten) { 01657 return m4->exten; 01658 } 01659 } 01660 for (m4 = m3; m4; m4 = m4->alt_char) { 01661 e3 = trie_find_next_match(m3); 01662 if (e3) { 01663 return e3; 01664 } 01665 } 01666 01667 return NULL; 01668 }
static void unreference_cached_app | ( | struct ast_app * | app | ) | [static] |
Definition at line 6803 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().
06804 { 06805 struct ast_context *context = NULL; 06806 struct ast_exten *eroot = NULL, *e = NULL; 06807 06808 ast_rdlock_contexts(); 06809 while ((context = ast_walk_contexts(context))) { 06810 while ((eroot = ast_walk_context_extensions(context, eroot))) { 06811 while ((e = ast_walk_extension_priorities(eroot, e))) { 06812 if (e->cached_app == app) 06813 e->cached_app = NULL; 06814 } 06815 } 06816 } 06817 ast_unlock_contexts(); 06818 06819 return; 06820 }
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 1537 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().
01538 { 01539 /* if this extension is marked as deleted, then skip this -- if it never shows 01540 on the scoreboard, it will never be found, nor will halt the traversal. */ 01541 if (deleted) 01542 return; 01543 board->total_specificity = spec; 01544 board->total_length = length; 01545 board->exten = exten; 01546 board->last_char = last; 01547 board->node = node; 01548 #ifdef NEED_DEBUG_HERE 01549 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec); 01550 #endif 01551 }
static void wait_for_hangup | ( | struct ast_channel * | chan, | |
const void * | data | |||
) | [static] |
Definition at line 8879 of file pbx.c.
References ast_frfree, ast_read(), ast_safe_sleep(), ast_strlen_zero(), ast_waitfor(), and f.
Referenced by pbx_builtin_busy(), and pbx_builtin_congestion().
08880 { 08881 int res; 08882 struct ast_frame *f; 08883 double waitsec; 08884 int waittime; 08885 08886 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0)) 08887 waitsec = -1; 08888 if (waitsec > -1) { 08889 waittime = waitsec * 1000.0; 08890 ast_safe_sleep(chan, waittime); 08891 } else do { 08892 res = ast_waitfor(chan, -1); 08893 if (res < 0) 08894 return; 08895 f = ast_read(chan); 08896 if (f) 08897 ast_frfree(f); 08898 } while(f); 08899 }
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_mutex_t conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Lock for the ast_context list This lock MUST be recursive, or a deadlock on reload may result. See https://issues.asterisk.org/view.php?id=17643.
Definition at line 1178 of file pbx.c.
Referenced by ast_rdlock_contexts(), ast_unlock_contexts(), and ast_wrlock_contexts().
struct ast_context* contexts [static] |
Definition at line 1171 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 1172 of file pbx.c.
Referenced by ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_unlockmacro(), ast_merge_contexts_and_delete(), find_context(), find_context_locked(), and pbx_find_extension().
int countcalls [static] |
Definition at line 1129 of file pbx.c.
Referenced by ast_active_calls(), decrease_call_count(), and increase_call_count().
const char* const days[] [static] |
struct ast_event_sub* device_state_sub [static] |
struct ast_taskprocessor* device_state_tps [static] |
struct ast_custom_function exception_function [static] |
Initial value:
{ .name = "EXCEPTION", .read = acf_exception_read, }
Definition at line 3170 of file pbx.c.
Referenced by load_pbx().
struct ast_datastore_info exception_store_info [static] |
Initial value:
{ .type = "EXCEPTION", .destroy = exception_store_free, }
Definition at line 3119 of file pbx.c.
Referenced by acf_exception_read(), and pbx_builtin_raise_exception().
int extenpatternmatchnew = 0 [static] |
Definition at line 1122 of file pbx.c.
Referenced by pbx_find_extension(), and pbx_set_extenpatternmatchnew().
struct cfextension_states extension_states[] [static] |
Referenced by ast_extension_state2str().
struct ast_threadstorage extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , } [static] |
ast_rwlock_t globalslock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } [static] |
Definition at line 1118 of file pbx.c.
Referenced by ast_str_retrieve_variable(), handle_show_globals(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
const int HASH_EXTENHINT_SIZE = 563 [static] |
struct ao2_container* hints [static] |
Definition at line 1191 of file pbx.c.
Referenced by ast_add_hint(), ast_change_hint(), ast_extension_state_add(), ast_extension_state_del(), ast_merge_contexts_and_delete(), ast_pbx_init(), ast_remove_hint(), complete_core_show_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), and hints_data_provider_get().
struct ast_data_handler hints_data_provider [static] |
Initial value:
{ .version = AST_DATA_HANDLER_VERSION, .get = hints_data_provider_get }
ast_mutex_t maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 1128 of file pbx.c.
Referenced by decrease_call_count(), and increase_call_count().
const char* const months[] [static] |
char* overrideswitch = NULL [static] |
Definition at line 1123 of file pbx.c.
Referenced by handle_cli_dialplan_save(), pbx_find_extension(), and pbx_set_overrideswitch().
struct ast_cli_entry pbx_cli[] [static] |
struct ast_data_entry pbx_data_providers[] [static] |
Initial value:
{ AST_DATA_ENTRY("asterisk/core/hints", &hints_data_provider), }
Definition at line 9860 of file pbx.c.
Referenced by load_pbx().
struct ast_app_option resetcdr_opts[128] = { [ 'w' ] = { .flag = AST_CDR_FLAG_POSTED }, [ 'a' ] = { .flag = AST_CDR_FLAG_LOCKED }, [ 'v' ] = { .flag = AST_CDR_FLAG_KEEP_VARS }, [ 'e' ] = { .flag = AST_CDR_FLAG_POST_ENABLE },} [static] |
struct ao2_container* statecbs [static] |
Definition at line 1193 of file pbx.c.
Referenced by ast_extension_state_add(), ast_extension_state_del(), ast_pbx_init(), and handle_statechange().
int stateid = 1 [static] |
struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , } [static] |
struct ast_custom_function testtime_function [static] |
Initial value:
{ .name = "TESTTIME", .write = testtime_write, }
Definition at line 9107 of file pbx.c.
Referenced by load_pbx().
int totalcalls [static] |
Definition at line 1130 of file pbx.c.
Referenced by ast_processed_calls(), increase_call_count(), and timing_read().
struct ast_app_option waitexten_opts[128] = { [ 'm' ] = { .flag = (1 << 0) , .arg_index = 0 + 1 }, [ 'd' ] = { .flag = (1 << 1) , .arg_index = 0 + 1 },} [static] |