#include "asterisk/channel.h"
#include "asterisk/sched.h"
#include "asterisk/devicestate.h"
#include "asterisk/chanvars.h"
#include "asterisk/hashtab.h"
#include "asterisk/stringfields.h"
#include "asterisk/xmldoc.h"
#include "asterisk/frame_defs.h"
Go to the source code of this file.
Data Structures | |
struct | ast_custom_function |
Data structure associated with a custom dialplan function. More... | |
struct | ast_pbx |
struct | ast_pbx_args |
Options for ast_pbx_run(). More... | |
struct | ast_switch |
struct | ast_timing |
struct | pbx_find_info |
#define | AST_PBX_ERROR 1 |
#define | AST_PBX_HANGUP -1 |
Special return values from applications to the PBX. | |
#define | AST_PBX_INCOMPLETE 12 |
#define | AST_PBX_OK 0 |
int | ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar) |
Simply remove extension from context. | |
int | ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked) |
This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return. | |
int | ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar) |
int | ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar, int already_locked) |
Functions for returning values from structures | |
const char * | ast_get_context_name (struct ast_context *con) |
ast_context * | ast_get_extension_context (struct ast_exten *exten) |
const char * | ast_get_extension_name (struct ast_exten *exten) |
const char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
const char * | ast_get_include_name (struct ast_include *include) |
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) |
Registrar info functions ... | |
const char * | ast_get_context_registrar (struct ast_context *c) |
const char * | ast_get_extension_registrar (struct ast_exten *e) |
const char * | ast_get_ignorepat_registrar (struct ast_ignorepat *ip) |
const char * | ast_get_include_registrar (struct ast_include *i) |
const char * | ast_get_switch_registrar (struct ast_sw *sw) |
Other Extension stuff | |
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) |
const char * | ast_get_extension_label (struct ast_exten *e) |
int | ast_get_extension_matchcid (struct ast_exten *e) |
int | ast_get_extension_priority (struct ast_exten *exten) |
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) |
Substitution routines, using dynamic string buffers | |
const char * | ast_str_retrieve_variable (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, 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) |
Walking functions ... | |
ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority) |
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) |
Substitution routines, using static string buffers | |
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 cp2_size, size_t *used) |
void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
Defines | |
#define | ast_custom_function_register(acf) __ast_custom_function_register(acf, ast_module_info->self) |
Register a custom function. | |
#define | AST_MAX_APP 32 |
#define | AST_PBX_GOTO_FAILED -3 |
#define | AST_PBX_KEEP 0 |
#define | AST_PBX_MAX_STACK 128 |
#define | AST_PBX_REPLACE 1 |
#define | PRIORITY_HINT -1 |
#define | STATUS_NO_CONTEXT 1 |
#define | STATUS_NO_EXTENSION 2 |
#define | STATUS_NO_LABEL 4 |
#define | STATUS_NO_PRIORITY 3 |
#define | STATUS_SUCCESS 5 |
Typedefs | |
typedef int(*) | ast_state_cb_type (char *context, char *id, enum ast_extension_states state, void *data) |
Typedef for devicestate and hint callbacks. | |
typedef int( | ast_switch_f )(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
All switch functions have the same interface, so define a type for them. | |
Enumerations | |
enum | ast_extension_states { AST_EXTENSION_REMOVED = -2, AST_EXTENSION_DEACTIVATED = -1, AST_EXTENSION_NOT_INUSE = 0, AST_EXTENSION_INUSE = 1 << 0, AST_EXTENSION_BUSY = 1 << 1, AST_EXTENSION_UNAVAILABLE = 1 << 2, AST_EXTENSION_RINGING = 1 << 3, AST_EXTENSION_ONHOLD = 1 << 4 } |
Extension states. More... | |
enum | ast_pbx_result { AST_PBX_SUCCESS = 0, AST_PBX_FAILED = -1, AST_PBX_CALL_LIMIT = -2 } |
The result codes when starting the PBX on a channel with ast_pbx_start. More... | |
enum | ext_match_t { E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22 } |
Functions | |
int | __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod) |
Register a custom function. | |
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 *. | |
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 *chan, 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) |
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. | |
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 *ignorepat, const char *registrar) |
Add an ignorepat. | |
int | ast_context_add_ignorepat2 (struct ast_context *con, const char *ignorepat, 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 *include, 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 *sw, 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 *macrocontext) |
locks the macrolock in the given given context | |
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 *macrocontext) |
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 *extension) |
Determine if a given extension matches a given pattern (in NXX format). | |
int | ast_extension_patmatch (const char *pattern, const char *data) |
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. | |
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 | |
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. | |
int | ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_ignore_pattern (const char *context, const char *pattern) |
Checks to see if a number should be ignored. | |
int | ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Looks to see if adding anything to this extension might match something. (exists ^ canmatch). | |
void | ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar) |
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added. | |
int | ast_parseable_goto (struct ast_channel *chan, const char *goto_string) |
int | ast_pbx_outgoing_app (const char *type, 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) |
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) |
enum ast_pbx_result | ast_pbx_run (struct ast_channel *c) |
Execute the PBX in the current thread. | |
enum ast_pbx_result | ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args) |
Execute the PBX in the current thread. | |
enum ast_pbx_result | ast_pbx_start (struct ast_channel *c) |
Create a new thread and start the PBX. | |
int | ast_processed_calls (void) |
Retrieve the total number of calls processed through the PBX since last restart. | |
int | ast_rdlock_context (struct ast_context *con) |
Read locks a given context. | |
int | ast_rdlock_contexts (void) |
Read locks the context list. | |
int | ast_register_switch (struct ast_switch *sw) |
Register an alternative dialplan switch. | |
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. | |
int | ast_unlock_context (struct ast_context *con) |
int | ast_unlock_contexts (void) |
Unlocks contexts. | |
void | ast_unregister_switch (struct ast_switch *sw) |
Unregister an alternative switch. | |
int | ast_wrlock_context (struct ast_context *con) |
Write locks a given context. | |
int | ast_wrlock_contexts (void) |
Write locks the context list. | |
void | pbx_builtin_clear_globals (void) |
const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
Return a pointer to the value of the corresponding channel variable. | |
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 *data) |
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. | |
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 *data) |
Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character. | |
int | pbx_checkcondition (const char *condition) |
Evaluate a condition. | |
int | pbx_exec (struct ast_channel *c, struct ast_app *app, const char *data) |
Execute an application. | |
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. | |
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) |
Definition in file pbx.h.
#define ast_custom_function_register | ( | acf | ) | __ast_custom_function_register(acf, ast_module_info->self) |
Register a custom function.
Definition at line 1118 of file pbx.h.
Referenced by load_module(), and reload().
#define AST_MAX_APP 32 |
Max length of an application
Definition at line 39 of file pbx.h.
Referenced by destroy_station(), handle_show_function(), and print_app_docs().
#define AST_PBX_GOTO_FAILED -3 |
#define AST_PBX_HANGUP -1 |
#define AST_PBX_INCOMPLETE 12 |
Return to PBX matching, allowing more digits for the extension
Definition at line 50 of file pbx.h.
Referenced by dial_exec_full(), pbx_builtin_incomplete(), and retrydial_exec().
#define PRIORITY_HINT -1 |
Special Priority for a hint
Definition at line 53 of file pbx.h.
Referenced by add_extensions(), ast_add_extension2_lockopt(), ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), destroy_exten(), destroy_station(), handle_cli_dialplan_add_extension(), handle_cli_dialplan_remove_extension(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), park_add_hints(), and print_ext().
typedef int(*) ast_state_cb_type(char *context, char *id, enum ast_extension_states state, void *data) |
typedef int( ast_switch_f)(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
enum ast_extension_states |
Extension states.
Definition at line 60 of file pbx.h.
00060 { 00061 AST_EXTENSION_REMOVED = -2, /*!< Extension removed */ 00062 AST_EXTENSION_DEACTIVATED = -1, /*!< Extension hint removed */ 00063 AST_EXTENSION_NOT_INUSE = 0, /*!< No device INUSE or BUSY */ 00064 AST_EXTENSION_INUSE = 1 << 0, /*!< One or more devices INUSE */ 00065 AST_EXTENSION_BUSY = 1 << 1, /*!< All devices BUSY */ 00066 AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */ 00067 AST_EXTENSION_RINGING = 1 << 3, /*!< All devices RINGING */ 00068 AST_EXTENSION_ONHOLD = 1 << 4, /*!< All devices ONHOLD */ 00069 };
enum ast_pbx_result |
The result codes when starting the PBX on a channel with ast_pbx_start.
Definition at line 286 of file pbx.h.
00286 { 00287 AST_PBX_SUCCESS = 0, 00288 AST_PBX_FAILED = -1, 00289 AST_PBX_CALL_LIMIT = -2, 00290 };
enum ext_match_t |
When looking up extensions, we can have different requests identified by the 'action' argument, as follows.
Definition at line 1187 of file pbx.h.
01187 { 01188 E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */ 01189 E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */ 01190 E_MATCH = 0x02, /* extension is an exact match */ 01191 E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */ 01192 E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */ 01193 E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */ 01194 };
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 }
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 }
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 * | chan, | |
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 }
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 * | ignorepat, | |||
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, fake_context::name, and ast_context::name.
Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_ignore_pattern(), cleanup_stale_contexts(), isexten_function_read(), manage_parkinglot(), park_exec_full(), parkinglot_destroy(), register_exten(), register_peer_exten(), unload_module(), and unregister_exten().
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, name, fake_context::name, ast_context::name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by 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 | matchcid, | |||
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 | matchcid, | |||
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(), exten, ast_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_patmatch | ( | const char * | pattern, | |
const char * | data | |||
) |
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 }
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_state_cb::data, ast_exten::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 * | e | ) |
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 * | include | ) |
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().
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 }
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, ast_hint::exten, ast_exten::exten, store_hint::exten, hints, store_hint::laststate, ast_hint::laststate, store_hint::list, ast_context::name, store_hint::next, ast_context::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_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 }
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, outgoing_helper::context, ast_channel::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, ast_channel::name, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), 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 }
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_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 }
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 }
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 }
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 * | priority | |||
) |
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 }
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 }
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 * | data | |||
) |
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, exten, ast_channel::exten, pbx_exception::priority, ast_channel::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 }
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 }
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 }
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(), pbx_find_info::data, ast_sw::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, scoreboard::exten, ast_exten::exten, extenpatternmatchnew, extension_match_core(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, fake_context::name, ast_sw::name, ast_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 }
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 }
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 | cp2_size, | |||
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 }