#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 3414 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().
03415 { 03416 struct ast_custom_function *cur; 03417 char tmps[80]; 03418 03419 if (!acf) { 03420 return -1; 03421 } 03422 03423 acf->mod = mod; 03424 #ifdef AST_XML_DOCS 03425 acf->docsrc = AST_STATIC_DOC; 03426 #endif 03427 03428 if (acf_retrieve_docs(acf)) { 03429 return -1; 03430 } 03431 03432 AST_RWLIST_WRLOCK(&acf_root); 03433 03434 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03435 if (!strcmp(acf->name, cur->name)) { 03436 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03437 AST_RWLIST_UNLOCK(&acf_root); 03438 return -1; 03439 } 03440 } 03441 03442 /* Store in alphabetical order */ 03443 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03444 if (strcasecmp(acf->name, cur->name) < 0) { 03445 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03446 break; 03447 } 03448 } 03449 AST_RWLIST_TRAVERSE_SAFE_END; 03450 03451 if (!cur) { 03452 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03453 } 03454 03455 AST_RWLIST_UNLOCK(&acf_root); 03456 03457 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03458 03459 return 0; 03460 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5064 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05065 { 05066 return countcalls; 05067 }
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 7736 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().
07739 { 07740 int ret = -1; 07741 struct ast_context *c = find_context_locked(context); 07742 07743 if (c) { 07744 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 07745 application, data, datad, registrar); 07746 ast_unlock_contexts(); 07747 } 07748 07749 return ret; 07750 }
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 8057 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().
08061 { 08062 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1); 08063 }
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 7775 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().
07776 { 07777 int res = 0; 07778 07779 ast_channel_lock(chan); 07780 07781 if (chan->pbx) { /* This channel is currently in the PBX */ 07782 ast_explicit_goto(chan, context, exten, priority + 1); 07783 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 07784 } else { 07785 /* In order to do it when the channel doesn't really exist within 07786 the PBX, we have to make a new channel, masquerade, and start the PBX 07787 at the new location */ 07788 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); 07789 if (!tmpchan) { 07790 res = -1; 07791 } else { 07792 if (chan->cdr) { 07793 ast_cdr_discard(tmpchan->cdr); 07794 tmpchan->cdr = ast_cdr_dup(chan->cdr); /* share the love */ 07795 } 07796 /* Make formats okay */ 07797 tmpchan->readformat = chan->readformat; 07798 tmpchan->writeformat = chan->writeformat; 07799 /* Setup proper location */ 07800 ast_explicit_goto(tmpchan, 07801 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 07802 07803 /* Masquerade into temp channel */ 07804 if (ast_channel_masquerade(tmpchan, chan)) { 07805 /* Failed to set up the masquerade. It's probably chan_local 07806 * in the middle of optimizing itself out. Sad. :( */ 07807 ast_hangup(tmpchan); 07808 tmpchan = NULL; 07809 res = -1; 07810 } else { 07811 /* it may appear odd to unlock chan here since the masquerade is on 07812 * tmpchan, but no channel locks should be held when doing a masquerade 07813 * since a masquerade requires a lock on the channels ao2 container. */ 07814 ast_channel_unlock(chan); 07815 ast_do_masquerade(tmpchan); 07816 ast_channel_lock(chan); 07817 /* Start the PBX going on our stolen channel */ 07818 if (ast_pbx_start(tmpchan)) { 07819 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 07820 ast_hangup(tmpchan); 07821 res = -1; 07822 } 07823 } 07824 } 07825 } 07826 ast_channel_unlock(chan); 07827 return res; 07828 }
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 7830 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
07831 { 07832 struct ast_channel *chan; 07833 int res = -1; 07834 07835 if ((chan = ast_channel_get_by_name(channame))) { 07836 res = ast_async_goto(chan, context, exten, priority); 07837 chan = ast_channel_unref(chan); 07838 } 07839 07840 return res; 07841 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10133 of file pbx.c.
References __ast_goto_if_exists().
10134 { 10135 return __ast_goto_if_exists(chan, context, exten, priority, 1); 10136 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10198 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
10199 { 10200 return pbx_parseable_goto(chan, goto_string, 1); 10201 }
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 7366 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().
07367 { 07368 char *info_save, *info; 07369 int j, num_fields, last_sep = -1; 07370 07371 /* Check for empty just in case */ 07372 if (ast_strlen_zero(info_in)) { 07373 return 0; 07374 } 07375 07376 /* make a copy just in case we were passed a static string */ 07377 info_save = info = ast_strdupa(info_in); 07378 07379 /* count the number of fields in the timespec */ 07380 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 07381 if (info[j] == ',') { 07382 last_sep = j; 07383 num_fields++; 07384 } 07385 } 07386 07387 /* save the timezone, if it is specified */ 07388 if (num_fields == 5) { 07389 i->timezone = ast_strdup(info + last_sep + 1); 07390 } else { 07391 i->timezone = NULL; 07392 } 07393 07394 /* Assume everything except time */ 07395 i->monthmask = 0xfff; /* 12 bits */ 07396 i->daymask = 0x7fffffffU; /* 31 bits */ 07397 i->dowmask = 0x7f; /* 7 bits */ 07398 /* on each call, use strsep() to move info to the next argument */ 07399 get_timerange(i, strsep(&info, "|,")); 07400 if (info) 07401 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 07402 if (info) 07403 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 07404 if (info) 07405 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 07406 return 1; 07407 }
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 4593 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().
04594 { 04595 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 04596 }
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 7409 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
07410 { 07411 return ast_check_timing2(i, ast_tvnow()); 07412 }
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 7414 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().
07415 { 07416 struct ast_tm tm; 07417 07418 ast_localtime(&tv, &tm, i->timezone); 07419 07420 /* If it's not the right month, return */ 07421 if (!(i->monthmask & (1 << tm.tm_mon))) 07422 return 0; 07423 07424 /* If it's not that time of the month.... */ 07425 /* Warning, tm_mday has range 1..31! */ 07426 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 07427 return 0; 07428 07429 /* If it's not the right day of the week */ 07430 if (!(i->dowmask & (1 << tm.tm_wday))) 07431 return 0; 07432 07433 /* Sanity check the hour just to be safe */ 07434 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 07435 ast_log(LOG_WARNING, "Insane time...\n"); 07436 return 0; 07437 } 07438 07439 /* Now the tough part, we calculate if it fits 07440 in the right time based on min/hour */ 07441 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)))) 07442 return 0; 07443 07444 /* If we got this far, then we're good */ 07445 return 1; 07446 }
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 10203 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().
10204 { 10205 struct ast_app *app = NULL; 10206 int which = 0; 10207 char *ret = NULL; 10208 size_t wordlen = strlen(word); 10209 10210 AST_RWLIST_RDLOCK(&apps); 10211 AST_RWLIST_TRAVERSE(&apps, app, list) { 10212 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 10213 ret = ast_strdup(app->name); 10214 break; 10215 } 10216 } 10217 AST_RWLIST_UNLOCK(&apps); 10218 10219 return ret; 10220 }
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 7648 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
07649 { 07650 int ret = -1; 07651 struct ast_context *c = find_context_locked(context); 07652 07653 if (c) { 07654 ret = ast_context_add_ignorepat2(c, value, registrar); 07655 ast_unlock_contexts(); 07656 } 07657 return ret; 07658 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 7660 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().
07661 { 07662 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 07663 int length; 07664 char *pattern; 07665 length = sizeof(struct ast_ignorepat); 07666 length += strlen(value) + 1; 07667 if (!(ignorepat = ast_calloc(1, length))) 07668 return -1; 07669 /* The cast to char * is because we need to write the initial value. 07670 * The field is not supposed to be modified otherwise. Also, gcc 4.2 07671 * sees the cast as dereferencing a type-punned pointer and warns about 07672 * it. This is the workaround (we're telling gcc, yes, that's really 07673 * what we wanted to do). 07674 */ 07675 pattern = (char *) ignorepat->pattern; 07676 strcpy(pattern, value); 07677 ignorepat->next = NULL; 07678 ignorepat->registrar = registrar; 07679 ast_wrlock_context(con); 07680 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 07681 ignorepatl = ignorepatc; 07682 if (!strcasecmp(ignorepatc->pattern, value)) { 07683 /* Already there */ 07684 ast_unlock_context(con); 07685 errno = EEXIST; 07686 return -1; 07687 } 07688 } 07689 if (ignorepatl) 07690 ignorepatl->next = ignorepat; 07691 else 07692 con->ignorepats = ignorepat; 07693 ast_unlock_context(con); 07694 return 0; 07695 07696 }
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 7195 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
07196 { 07197 int ret = -1; 07198 struct ast_context *c = find_context_locked(context); 07199 07200 if (c) { 07201 ret = ast_context_add_include2(c, include, registrar); 07202 ast_unlock_contexts(); 07203 } 07204 return ret; 07205 }
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 7463 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().
07465 { 07466 struct ast_include *new_include; 07467 char *c; 07468 struct ast_include *i, *il = NULL; /* include, include_last */ 07469 int length; 07470 char *p; 07471 07472 length = sizeof(struct ast_include); 07473 length += 2 * (strlen(value) + 1); 07474 07475 /* allocate new include structure ... */ 07476 if (!(new_include = ast_calloc(1, length))) 07477 return -1; 07478 /* Fill in this structure. Use 'p' for assignments, as the fields 07479 * in the structure are 'const char *' 07480 */ 07481 p = new_include->stuff; 07482 new_include->name = p; 07483 strcpy(p, value); 07484 p += strlen(value) + 1; 07485 new_include->rname = p; 07486 strcpy(p, value); 07487 /* Strip off timing info, and process if it is there */ 07488 if ( (c = strchr(p, ',')) ) { 07489 *c++ = '\0'; 07490 new_include->hastime = ast_build_timing(&(new_include->timing), c); 07491 } 07492 new_include->next = NULL; 07493 new_include->registrar = registrar; 07494 07495 ast_wrlock_context(con); 07496 07497 /* ... go to last include and check if context is already included too... */ 07498 for (i = con->includes; i; i = i->next) { 07499 if (!strcasecmp(i->name, new_include->name)) { 07500 ast_destroy_timing(&(new_include->timing)); 07501 ast_free(new_include); 07502 ast_unlock_context(con); 07503 errno = EEXIST; 07504 return -1; 07505 } 07506 il = i; 07507 } 07508 07509 /* ... include new context into context list, unlock, return */ 07510 if (il) 07511 il->next = new_include; 07512 else 07513 con->includes = new_include; 07514 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 07515 07516 ast_unlock_context(con); 07517 07518 return 0; 07519 }
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 7526 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
07527 { 07528 int ret = -1; 07529 struct ast_context *c = find_context_locked(context); 07530 07531 if (c) { /* found, add switch to this context */ 07532 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 07533 ast_unlock_contexts(); 07534 } 07535 return ret; 07536 }
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 7545 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().
07547 { 07548 struct ast_sw *new_sw; 07549 struct ast_sw *i; 07550 int length; 07551 char *p; 07552 07553 length = sizeof(struct ast_sw); 07554 length += strlen(value) + 1; 07555 if (data) 07556 length += strlen(data); 07557 length++; 07558 07559 /* allocate new sw structure ... */ 07560 if (!(new_sw = ast_calloc(1, length))) 07561 return -1; 07562 /* ... fill in this structure ... */ 07563 p = new_sw->stuff; 07564 new_sw->name = p; 07565 strcpy(new_sw->name, value); 07566 p += strlen(value) + 1; 07567 new_sw->data = p; 07568 if (data) { 07569 strcpy(new_sw->data, data); 07570 p += strlen(data) + 1; 07571 } else { 07572 strcpy(new_sw->data, ""); 07573 p++; 07574 } 07575 new_sw->eval = eval; 07576 new_sw->registrar = registrar; 07577 07578 /* ... try to lock this context ... */ 07579 ast_wrlock_context(con); 07580 07581 /* ... go to last sw and check if context is already swd too... */ 07582 AST_LIST_TRAVERSE(&con->alts, i, list) { 07583 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 07584 ast_free(new_sw); 07585 ast_unlock_context(con); 07586 errno = EEXIST; 07587 return -1; 07588 } 07589 } 07590 07591 /* ... sw new context into context list, unlock, return */ 07592 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 07593 07594 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 07595 07596 ast_unlock_context(con); 07597 07598 return 0; 07599 }
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 8869 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().
08870 { 08871 ast_wrlock_contexts(); 08872 __ast_context_destroy(contexts, contexts_table, con,registrar); 08873 ast_unlock_contexts(); 08874 }
struct ast_context* ast_context_find | ( | const char * | name | ) |
Find a context.
name | name of the context to find |
Definition at line 2512 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().
02513 { 02514 struct ast_context *tmp = NULL; 02515 struct fake_context item; 02516 02517 ast_copy_string(item.name, name, sizeof(item.name)); 02518 02519 ast_rdlock_contexts(); 02520 if( contexts_table ) { 02521 tmp = ast_hashtab_lookup(contexts_table,&item); 02522 } else { 02523 while ( (tmp = ast_walk_contexts(tmp)) ) { 02524 if (!name || !strcasecmp(name, tmp->name)) { 02525 break; 02526 } 02527 } 02528 } 02529 ast_unlock_contexts(); 02530 return tmp; 02531 }
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 6848 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().
06849 { 06850 struct ast_context *tmp, **local_contexts; 06851 struct fake_context search; 06852 int length = sizeof(struct ast_context) + strlen(name) + 1; 06853 06854 if (!contexts_table) { 06855 contexts_table = ast_hashtab_create(17, 06856 ast_hashtab_compare_contexts, 06857 ast_hashtab_resize_java, 06858 ast_hashtab_newsize_java, 06859 ast_hashtab_hash_contexts, 06860 0); 06861 } 06862 06863 ast_copy_string(search.name, name, sizeof(search.name)); 06864 if (!extcontexts) { 06865 ast_rdlock_contexts(); 06866 local_contexts = &contexts; 06867 tmp = ast_hashtab_lookup(contexts_table, &search); 06868 ast_unlock_contexts(); 06869 if (tmp) { 06870 tmp->refcount++; 06871 return tmp; 06872 } 06873 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 06874 local_contexts = extcontexts; 06875 tmp = ast_hashtab_lookup(exttable, &search); 06876 if (tmp) { 06877 tmp->refcount++; 06878 return tmp; 06879 } 06880 } 06881 06882 if ((tmp = ast_calloc(1, length))) { 06883 ast_rwlock_init(&tmp->lock); 06884 ast_mutex_init(&tmp->macrolock); 06885 strcpy(tmp->name, name); 06886 tmp->root = NULL; 06887 tmp->root_table = NULL; 06888 tmp->registrar = ast_strdup(registrar); 06889 tmp->includes = NULL; 06890 tmp->ignorepats = NULL; 06891 tmp->refcount = 1; 06892 } else { 06893 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 06894 return NULL; 06895 } 06896 06897 if (!extcontexts) { 06898 ast_wrlock_contexts(); 06899 tmp->next = *local_contexts; 06900 *local_contexts = tmp; 06901 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 06902 ast_unlock_contexts(); 06903 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 06904 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 06905 } else { 06906 tmp->next = *local_contexts; 06907 if (exttable) 06908 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 06909 06910 *local_contexts = tmp; 06911 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 06912 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 06913 } 06914 return tmp; 06915 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 5444 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().
05445 { 05446 struct ast_context *c = NULL; 05447 int ret = -1; 05448 struct fake_context item; 05449 05450 ast_rdlock_contexts(); 05451 05452 ast_copy_string(item.name, context, sizeof(item.name)); 05453 05454 c = ast_hashtab_lookup(contexts_table,&item); 05455 if (c) 05456 ret = 0; 05457 ast_unlock_contexts(); 05458 05459 /* if we found context, lock macrolock */ 05460 if (ret == 0) { 05461 ret = ast_mutex_lock(&c->macrolock); 05462 } 05463 05464 return ret; 05465 }
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 5252 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), unregister_exten(), and UnregisterExtension().
05253 { 05254 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 05255 }
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 5279 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by manage_parkinglot(), park_exec_full(), and unload_module().
05280 { 05281 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 05282 }
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 5257 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().
05258 { 05259 int ret = -1; /* default error return */ 05260 struct ast_context *c = find_context_locked(context); 05261 05262 if (c) { /* ... remove extension ... */ 05263 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcallerid, registrar, 1); 05264 ast_unlock_contexts(); 05265 } 05266 return ret; 05267 }
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 5284 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().
05285 { 05286 struct ast_exten *exten, *prev_exten = NULL; 05287 struct ast_exten *peer; 05288 struct ast_exten ex, *exten2, *exten3; 05289 char dummy_name[1024]; 05290 struct ast_exten *previous_peer = NULL; 05291 struct ast_exten *next_peer = NULL; 05292 int found = 0; 05293 05294 if (!already_locked) 05295 ast_wrlock_context(con); 05296 05297 /* Handle this is in the new world */ 05298 05299 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 05300 * peers, not just those matching the callerid. */ 05301 #ifdef NEED_DEBUG 05302 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 05303 #endif 05304 #ifdef CONTEXT_DEBUG 05305 check_contexts(__FILE__, __LINE__); 05306 #endif 05307 /* find this particular extension */ 05308 ex.exten = dummy_name; 05309 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 05310 ex.cidmatch = callerid; 05311 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 05312 exten = ast_hashtab_lookup(con->root_table, &ex); 05313 if (exten) { 05314 if (priority == 0) { 05315 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05316 if (!exten2) 05317 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); 05318 if (con->pattern_tree) { 05319 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05320 05321 if (x->exten) { /* this test for safety purposes */ 05322 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05323 x->exten = 0; /* get rid of what will become a bad pointer */ 05324 } else { 05325 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 05326 } 05327 } 05328 } else { 05329 ex.priority = priority; 05330 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 05331 if (exten2) { 05332 05333 if (exten2->label) { /* if this exten has a label, remove that, too */ 05334 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 05335 if (!exten3) 05336 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); 05337 } 05338 05339 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 05340 if (!exten3) 05341 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); 05342 if (exten2 == exten && exten2->peer) { 05343 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05344 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 05345 } 05346 if (ast_hashtab_size(exten->peer_table) == 0) { 05347 /* well, if the last priority of an exten is to be removed, 05348 then, the extension is removed, too! */ 05349 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 05350 if (!exten3) 05351 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 05352 if (con->pattern_tree) { 05353 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05354 if (x->exten) { /* this test for safety purposes */ 05355 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05356 x->exten = 0; /* get rid of what will become a bad pointer */ 05357 } 05358 } 05359 } 05360 } else { 05361 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 05362 priority, exten->exten, con->name); 05363 } 05364 } 05365 } else { 05366 /* hmmm? this exten is not in this pattern tree? */ 05367 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 05368 extension, con->name); 05369 } 05370 #ifdef NEED_DEBUG 05371 if (con->pattern_tree) { 05372 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 05373 log_match_char_tree(con->pattern_tree, " "); 05374 } 05375 #endif 05376 05377 /* scan the extension list to find first matching extension-registrar */ 05378 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 05379 if (!strcmp(exten->exten, extension) && 05380 (!registrar || !strcmp(exten->registrar, registrar)) && 05381 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 05382 break; 05383 } 05384 if (!exten) { 05385 /* we can't find right extension */ 05386 if (!already_locked) 05387 ast_unlock_context(con); 05388 return -1; 05389 } 05390 05391 /* scan the priority list to remove extension with exten->priority == priority */ 05392 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 05393 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))); 05394 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 05395 if ((priority == 0 || peer->priority == priority) && 05396 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 05397 (!registrar || !strcmp(peer->registrar, registrar) )) { 05398 found = 1; 05399 05400 /* we are first priority extension? */ 05401 if (!previous_peer) { 05402 /* 05403 * We are first in the priority chain, so must update the extension chain. 05404 * The next node is either the next priority or the next extension 05405 */ 05406 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 05407 if (peer->peer) { 05408 /* move the peer_table and peer_label_table down to the next peer, if 05409 it is there */ 05410 peer->peer->peer_table = peer->peer_table; 05411 peer->peer->peer_label_table = peer->peer_label_table; 05412 peer->peer_table = NULL; 05413 peer->peer_label_table = NULL; 05414 } 05415 if (!prev_exten) { /* change the root... */ 05416 con->root = next_node; 05417 } else { 05418 prev_exten->next = next_node; /* unlink */ 05419 } 05420 if (peer->peer) { /* update the new head of the pri list */ 05421 peer->peer->next = peer->next; 05422 } 05423 } else { /* easy, we are not first priority in extension */ 05424 previous_peer->peer = peer->peer; 05425 } 05426 05427 /* now, free whole priority extension */ 05428 destroy_exten(peer); 05429 } else { 05430 previous_peer = peer; 05431 } 05432 } 05433 if (!already_locked) 05434 ast_unlock_context(con); 05435 return found ? 0 : -1; 05436 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 7605 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
07606 { 07607 int ret = -1; 07608 struct ast_context *c = find_context_locked(context); 07609 07610 if (c) { 07611 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 07612 ast_unlock_contexts(); 07613 } 07614 return ret; 07615 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 7617 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().
07618 { 07619 struct ast_ignorepat *ip, *ipl = NULL; 07620 07621 ast_wrlock_context(con); 07622 07623 for (ip = con->ignorepats; ip; ip = ip->next) { 07624 if (!strcmp(ip->pattern, ignorepat) && 07625 (!registrar || (registrar == ip->registrar))) { 07626 if (ipl) { 07627 ipl->next = ip->next; 07628 ast_free(ip); 07629 } else { 07630 con->ignorepats = ip->next; 07631 ast_free(ip); 07632 } 07633 ast_unlock_context(con); 07634 return 0; 07635 } 07636 ipl = ip; 07637 } 07638 07639 ast_unlock_context(con); 07640 errno = EINVAL; 07641 return -1; 07642 }
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 5143 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
05144 { 05145 int ret = -1; 05146 struct ast_context *c = find_context_locked(context); 05147 05148 if (c) { 05149 /* found, remove include from this context ... */ 05150 ret = ast_context_remove_include2(c, include, registrar); 05151 ast_unlock_contexts(); 05152 } 05153 return ret; 05154 }
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 5165 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().
05166 { 05167 struct ast_include *i, *pi = NULL; 05168 int ret = -1; 05169 05170 ast_wrlock_context(con); 05171 05172 /* find our include */ 05173 for (i = con->includes; i; pi = i, i = i->next) { 05174 if (!strcmp(i->name, include) && 05175 (!registrar || !strcmp(i->registrar, registrar))) { 05176 /* remove from list */ 05177 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 05178 if (pi) 05179 pi->next = i->next; 05180 else 05181 con->includes = i->next; 05182 /* free include and return */ 05183 ast_destroy_timing(&(i->timing)); 05184 ast_free(i); 05185 ret = 0; 05186 break; 05187 } 05188 } 05189 05190 ast_unlock_context(con); 05191 05192 return ret; 05193 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 5200 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
05201 { 05202 int ret = -1; /* default error return */ 05203 struct ast_context *c = find_context_locked(context); 05204 05205 if (c) { 05206 /* remove switch from this context ... */ 05207 ret = ast_context_remove_switch2(c, sw, data, registrar); 05208 ast_unlock_contexts(); 05209 } 05210 return ret; 05211 }
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 5221 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().
05222 { 05223 struct ast_sw *i; 05224 int ret = -1; 05225 05226 ast_wrlock_context(con); 05227 05228 /* walk switches */ 05229 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 05230 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 05231 (!registrar || !strcmp(i->registrar, registrar))) { 05232 /* found, remove from list */ 05233 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 05234 AST_LIST_REMOVE_CURRENT(list); 05235 ast_free(i); /* free switch and return */ 05236 ret = 0; 05237 break; 05238 } 05239 } 05240 AST_LIST_TRAVERSE_SAFE_END; 05241 05242 ast_unlock_context(con); 05243 05244 return ret; 05245 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 5472 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().
05473 { 05474 struct ast_context *c = NULL; 05475 int ret = -1; 05476 struct fake_context item; 05477 05478 ast_rdlock_contexts(); 05479 05480 ast_copy_string(item.name, context, sizeof(item.name)); 05481 05482 c = ast_hashtab_lookup(contexts_table,&item); 05483 if (c) 05484 ret = 0; 05485 ast_unlock_contexts(); 05486 05487 /* if we found context, unlock macrolock */ 05488 if (ret == 0) { 05489 ret = ast_mutex_unlock(&c->macrolock); 05490 } 05491 05492 return ret; 05493 }
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 10088 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().
10089 { 10090 struct ast_include *inc = NULL; 10091 int res = 0; 10092 10093 while ( (inc = ast_walk_context_includes(con, inc)) ) { 10094 if (ast_context_find(inc->rname)) 10095 continue; 10096 10097 res = -1; 10098 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 10099 ast_get_context_name(con), inc->rname); 10100 break; 10101 } 10102 10103 return res; 10104 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) |
Definition at line 3325 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().
03326 { 03327 struct ast_custom_function *acf = NULL; 03328 03329 AST_RWLIST_RDLOCK(&acf_root); 03330 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03331 if (!strcmp(name, acf->name)) 03332 break; 03333 } 03334 AST_RWLIST_UNLOCK(&acf_root); 03335 03336 return acf; 03337 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3339 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().
03340 { 03341 struct ast_custom_function *cur; 03342 03343 if (!acf) { 03344 return -1; 03345 } 03346 03347 AST_RWLIST_WRLOCK(&acf_root); 03348 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03349 #ifdef AST_XML_DOCS 03350 if (cur->docsrc == AST_XML_DOC) { 03351 ast_string_field_free_memory(acf); 03352 } 03353 #endif 03354 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03355 } 03356 AST_RWLIST_UNLOCK(&acf_root); 03357 03358 return cur ? 0 : -1; 03359 }
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 7448 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().
07449 { 07450 if (i->timezone) { 07451 ast_free(i->timezone); 07452 i->timezone = NULL; 07453 } 07454 return 0; 07455 }
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 4145 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().
04146 { 04147 switch (devstate) { 04148 case AST_DEVICE_ONHOLD: 04149 return AST_EXTENSION_ONHOLD; 04150 case AST_DEVICE_BUSY: 04151 return AST_EXTENSION_BUSY; 04152 case AST_DEVICE_UNKNOWN: 04153 return AST_EXTENSION_NOT_INUSE; 04154 case AST_DEVICE_UNAVAILABLE: 04155 case AST_DEVICE_INVALID: 04156 return AST_EXTENSION_UNAVAILABLE; 04157 case AST_DEVICE_RINGINUSE: 04158 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04159 case AST_DEVICE_RINGING: 04160 return AST_EXTENSION_RINGING; 04161 case AST_DEVICE_INUSE: 04162 return AST_EXTENSION_INUSE; 04163 case AST_DEVICE_NOT_INUSE: 04164 return AST_EXTENSION_NOT_INUSE; 04165 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04166 break; 04167 } 04168 04169 return AST_EXTENSION_NOT_INUSE; 04170 }
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 4578 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(), builtin_blindtransfer(), 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().
04579 { 04580 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 04581 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 7752 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().
07753 { 07754 if (!chan) 07755 return -1; 07756 07757 ast_channel_lock(chan); 07758 07759 if (!ast_strlen_zero(context)) 07760 ast_copy_string(chan->context, context, sizeof(chan->context)); 07761 if (!ast_strlen_zero(exten)) 07762 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07763 if (priority > -1) { 07764 chan->priority = priority; 07765 /* see flag description in channel.h for explanation */ 07766 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 07767 chan->priority--; 07768 } 07769 07770 ast_channel_unlock(chan); 07771 07772 return 0; 07773 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 2489 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().
02490 { 02491 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02492 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02493 return extension_match_core(pattern, data, needmore); 02494 }
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 2291 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02292 { 02293 return ext_cmp(a, b); 02294 }
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 2484 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().
02485 { 02486 return extension_match_core(pattern, data, E_MATCH); 02487 }
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 4208 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().
04209 { 04210 struct ast_exten *e; 04211 04212 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04213 return -1; /* No hint, return -1 */ 04214 } 04215 04216 if (e->exten[0] == '_') { 04217 /* Create this hint on-the-fly */ 04218 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04219 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04220 e->registrar); 04221 if (!(e = ast_hint_extension(c, context, exten))) { 04222 /* Improbable, but not impossible */ 04223 return -1; 04224 } 04225 } 04226 04227 return ast_extension_state2(e); /* Check all devices in the hint */ 04228 }
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 4196 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().
04197 { 04198 int i; 04199 04200 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04201 if (extension_states[i].extension_state == extension_state) 04202 return extension_states[i].text; 04203 } 04204 return "Unknown"; 04205 }
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_find, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension(), ast_calloc, ast_free_ptr, ast_hint_extension(), AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_strdup, ast_state_cb::callback, 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, 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 *cblist; 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 AST_LIST_TRAVERSE(&statecbs, cblist, entry) { 04316 if (cblist->callback == callback) { 04317 cblist->data = data; 04318 ao2_unlock(hints); 04319 return 0; 04320 } 04321 } 04322 04323 /* Now insert the callback */ 04324 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 04325 ao2_unlock(hints); 04326 return -1; 04327 } 04328 cblist->id = 0; 04329 cblist->callback = callback; 04330 cblist->data = data; 04331 04332 AST_LIST_INSERT_HEAD(&statecbs, cblist, entry); 04333 04334 ao2_unlock(hints); 04335 return 0; 04336 } 04337 04338 if (!context || !exten) 04339 return -1; 04340 04341 /* This callback type is for only one hint, so get the hint */ 04342 e = ast_hint_extension(NULL, context, exten); 04343 if (!e) { 04344 return -1; 04345 } 04346 04347 /* If this is a pattern, dynamically create a new extension for this 04348 * particular match. Note that this will only happen once for each 04349 * individual extension, because the pattern will no longer match first. 04350 */ 04351 if (e->exten[0] == '_') { 04352 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04353 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04354 e->registrar); 04355 e = ast_hint_extension(NULL, context, exten); 04356 if (!e || e->exten[0] == '_') { 04357 return -1; 04358 } 04359 } 04360 04361 /* Find the hint in the list of hints */ 04362 hint = ao2_find(hints, e, 0); 04363 04364 if (!hint) { 04365 return -1; 04366 } 04367 04368 /* Now insert the callback in the callback list */ 04369 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 04370 ao2_ref(hint, -1); 04371 return -1; 04372 } 04373 04374 cblist->id = stateid++; /* Unique ID for this callback */ 04375 cblist->callback = callback; /* Pointer to callback routine */ 04376 cblist->data = data; /* Data for the callback */ 04377 04378 ao2_lock(hint); 04379 AST_LIST_INSERT_HEAD(&hint->callbacks, cblist, entry); 04380 ao2_unlock(hint); 04381 04382 ao2_ref(hint, -1); 04383 04384 return cblist->id; 04385 }
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 4404 of file pbx.c.
References ao2_callback, ao2_lock, ao2_ref, ao2_unlock, ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_state_cb::callback, ast_state_cb::entry, find_hint_by_cb_id(), hints, and ast_state_cb::id.
Referenced by dialog_unlink_all(), handle_request_subscribe(), skinny_unregister(), and unload_module().
04405 { 04406 struct ast_state_cb *p_cur = NULL; 04407 int ret = -1; 04408 04409 if (!id && !callback) { 04410 return -1; 04411 } 04412 04413 if (!id) { /* id == 0 is a callback without extension */ 04414 ao2_lock(hints); 04415 AST_LIST_TRAVERSE_SAFE_BEGIN(&statecbs, p_cur, entry) { 04416 if (p_cur->callback == callback) { 04417 AST_LIST_REMOVE_CURRENT(entry); 04418 break; 04419 } 04420 } 04421 AST_LIST_TRAVERSE_SAFE_END; 04422 ao2_unlock(hints); 04423 } else { /* callback with extension, find the callback based on ID */ 04424 struct ast_hint *hint; 04425 04426 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 04427 04428 if (hint) { 04429 ao2_lock(hint); 04430 AST_LIST_TRAVERSE_SAFE_BEGIN(&hint->callbacks, p_cur, entry) { 04431 if (p_cur->id == id) { 04432 AST_LIST_REMOVE_CURRENT(entry); 04433 ret = 0; 04434 break; 04435 } 04436 } 04437 AST_LIST_TRAVERSE_SAFE_END; 04438 04439 ao2_unlock(hint); 04440 ao2_ref(hint, -1); 04441 } 04442 } 04443 04444 if (p_cur) { 04445 ast_free(p_cur); 04446 } 04447 04448 return ret; 04449 }
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 4583 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().
04584 { 04585 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04586 }
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 4588 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
04589 { 04590 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 04591 }
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 3483 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().
03484 { 03485 char *copy = ast_strdupa(function); 03486 char *args = func_args(copy); 03487 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03488 int res; 03489 struct ast_module_user *u = NULL; 03490 03491 if (acfptr == NULL) { 03492 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03493 } else if (!acfptr->read && !acfptr->read2) { 03494 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03495 } else if (acfptr->read) { 03496 if (acfptr->mod) { 03497 u = __ast_module_user_add(acfptr->mod, chan); 03498 } 03499 res = acfptr->read(chan, copy, args, workspace, len); 03500 if (acfptr->mod && u) { 03501 __ast_module_user_remove(acfptr->mod, u); 03502 } 03503 return res; 03504 } else { 03505 struct ast_str *str = ast_str_create(16); 03506 if (acfptr->mod) { 03507 u = __ast_module_user_add(acfptr->mod, chan); 03508 } 03509 res = acfptr->read2(chan, copy, args, &str, 0); 03510 if (acfptr->mod && u) { 03511 __ast_module_user_remove(acfptr->mod, u); 03512 } 03513 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 03514 ast_free(str); 03515 return res; 03516 } 03517 return -1; 03518 }
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 3520 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().
03521 { 03522 char *copy = ast_strdupa(function); 03523 char *args = func_args(copy); 03524 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03525 int res; 03526 struct ast_module_user *u = NULL; 03527 03528 if (acfptr == NULL) { 03529 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03530 } else if (!acfptr->read && !acfptr->read2) { 03531 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03532 } else { 03533 if (acfptr->mod) { 03534 u = __ast_module_user_add(acfptr->mod, chan); 03535 } 03536 if (acfptr->read2) { 03537 /* ast_str enabled */ 03538 ast_str_reset(*str); 03539 res = acfptr->read2(chan, copy, args, str, maxlen); 03540 } else { 03541 /* Legacy function pointer, allocate buffer for result */ 03542 int maxsize = ast_str_size(*str); 03543 if (maxlen > -1) { 03544 if (maxlen == 0) { 03545 if (acfptr->read_max) { 03546 maxsize = acfptr->read_max; 03547 } else { 03548 maxsize = VAR_BUF_SIZE; 03549 } 03550 } else { 03551 maxsize = maxlen; 03552 } 03553 ast_str_make_space(str, maxsize); 03554 } 03555 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 03556 } 03557 if (acfptr->mod && u) { 03558 __ast_module_user_remove(acfptr->mod, u); 03559 } 03560 return res; 03561 } 03562 return -1; 03563 }
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 3565 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().
03566 { 03567 char *copy = ast_strdupa(function); 03568 char *args = func_args(copy); 03569 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03570 03571 if (acfptr == NULL) 03572 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03573 else if (!acfptr->write) 03574 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 03575 else { 03576 int res; 03577 struct ast_module_user *u = NULL; 03578 if (acfptr->mod) 03579 u = __ast_module_user_add(acfptr->mod, chan); 03580 res = acfptr->write(chan, copy, args, value); 03581 if (acfptr->mod && u) 03582 __ast_module_user_remove(acfptr->mod, u); 03583 return res; 03584 } 03585 03586 return -1; 03587 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 9940 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().
09941 { 09942 return con ? con->name : NULL; 09943 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 9978 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
09979 { 09980 return c ? c->registrar : NULL; 09981 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 10008 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().
10009 { 10010 return e ? e->app : NULL; 10011 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 10013 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().
10014 { 10015 return e ? e->data : NULL; 10016 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 10003 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10004 { 10005 return e ? e->cidmatch : NULL; 10006 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) |
Definition at line 9945 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 9955 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 9998 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
09999 { 10000 return e ? e->matchcid : 0; 10001 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 9950 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 9970 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 9983 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
09984 { 09985 return e ? e->registrar : NULL; 09986 }
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 4540 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().
04541 { 04542 struct ast_exten *e = ast_hint_extension(c, context, exten); 04543 04544 if (e) { 04545 if (hint) 04546 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 04547 if (name) { 04548 const char *tmp = ast_get_extension_app_data(e); 04549 if (tmp) 04550 ast_copy_string(name, tmp, namesize); 04551 } 04552 return -1; 04553 } 04554 return 0; 04555 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 9965 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().
09966 { 09967 return ip ? ip->pattern : NULL; 09968 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 9993 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().
09994 { 09995 return ip ? ip->registrar : NULL; 09996 }
const char* ast_get_include_name | ( | struct ast_include * | include | ) |
Definition at line 9960 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 9988 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().
09989 { 09990 return i ? i->registrar : NULL; 09991 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 10023 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().
10024 { 10025 return sw ? sw->data : NULL; 10026 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 10028 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
10029 { 10030 return sw->eval; 10031 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 10018 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().
10019 { 10020 return sw ? sw->name : NULL; 10021 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 10033 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().
10034 { 10035 return sw ? sw->registrar : NULL; 10036 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10128 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().
10129 { 10130 return __ast_goto_if_exists(chan, context, exten, priority, 0); 10131 }
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 7698 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().
07699 { 07700 struct ast_context *con = ast_context_find(context); 07701 if (con) { 07702 struct ast_ignorepat *pat; 07703 for (pat = con->ignorepats; pat; pat = pat->next) { 07704 if (ast_extension_match(pat->pattern, pattern)) 07705 return 1; 07706 } 07707 } 07708 07709 return 0; 07710 }
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 4598 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().
04599 { 04600 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 04601 }
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 7047 of file pbx.c.
References __ast_internal_context_destroy(), ao2_find, AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, 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_APPEND_LIST, AST_LIST_EMPTY, AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, 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, ast_hint::laststate, store_hint::list, ast_context::name, store_hint::next, ast_context::next, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
07048 { 07049 double ft; 07050 struct ast_context *tmp, *oldcontextslist; 07051 struct ast_hashtab *oldtable; 07052 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 07053 struct store_hint *this; 07054 struct ast_hint *hint; 07055 struct ast_exten *exten; 07056 int length; 07057 struct ast_state_cb *thiscb; 07058 struct ast_hashtab_iter *iter; 07059 struct ao2_iterator i; 07060 07061 /* it is very important that this function hold the hint list lock _and_ the conlock 07062 during its operation; not only do we need to ensure that the list of contexts 07063 and extensions does not change, but also that no hint callbacks (watchers) are 07064 added or removed during the merge/delete process 07065 07066 in addition, the locks _must_ be taken in this order, because there are already 07067 other code paths that use this order 07068 */ 07069 07070 struct timeval begintime, writelocktime, endlocktime, enddeltime; 07071 07072 begintime = ast_tvnow(); 07073 ast_rdlock_contexts(); 07074 iter = ast_hashtab_start_traversal(contexts_table); 07075 while ((tmp = ast_hashtab_next(iter))) { 07076 context_merge(extcontexts, exttable, tmp, registrar); 07077 } 07078 ast_hashtab_end_traversal(iter); 07079 07080 ao2_lock(hints); 07081 writelocktime = ast_tvnow(); 07082 07083 /* preserve all watchers for hints */ 07084 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07085 for (hint = ao2_iterator_next(&i); hint; ao2_ref(hint, -1), hint = ao2_iterator_next(&i)) { 07086 if (!AST_LIST_EMPTY(&hint->callbacks)) { 07087 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 07088 if (!(this = ast_calloc(1, length))) { 07089 continue; 07090 } 07091 ao2_lock(hint); 07092 07093 if (hint->exten == NULL) { 07094 ao2_unlock(hint); 07095 continue; 07096 } 07097 07098 /* this removes all the callbacks from the hint into this. */ 07099 AST_LIST_APPEND_LIST(&this->callbacks, &hint->callbacks, entry); 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 ast_free(thiscb); 07142 } 07143 } else { 07144 ao2_lock(hint); 07145 AST_LIST_APPEND_LIST(&hint->callbacks, &this->callbacks, entry); 07146 hint->laststate = this->laststate; 07147 ao2_unlock(hint); 07148 } 07149 ast_free(this); 07150 if (hint) { 07151 ao2_ref(hint, -1); 07152 } 07153 } 07154 07155 ao2_unlock(hints); 07156 ast_unlock_contexts(); 07157 endlocktime = ast_tvnow(); 07158 07159 /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk 07160 is now freely using the new stuff instead */ 07161 07162 ast_hashtab_destroy(oldtable, NULL); 07163 07164 for (tmp = oldcontextslist; tmp; ) { 07165 struct ast_context *next; /* next starting point */ 07166 next = tmp->next; 07167 __ast_internal_context_destroy(tmp); 07168 tmp = next; 07169 } 07170 enddeltime = ast_tvnow(); 07171 07172 ft = ast_tvdiff_us(writelocktime, begintime); 07173 ft /= 1000000.0; 07174 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 07175 07176 ft = ast_tvdiff_us(endlocktime, writelocktime); 07177 ft /= 1000000.0; 07178 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 07179 07180 ft = ast_tvdiff_us(enddeltime, endlocktime); 07181 ft /= 1000000.0; 07182 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 07183 07184 ft = ast_tvdiff_us(enddeltime, begintime); 07185 ft /= 1000000.0; 07186 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 07187 return; 07188 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10193 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().
10194 { 10195 return pbx_parseable_goto(chan, goto_string, 0); 10196 }
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 8541 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().
08542 { 08543 struct ast_channel *chan; 08544 struct app_tmp *tmp; 08545 int res = -1, cdr_res = -1; 08546 struct outgoing_helper oh; 08547 08548 memset(&oh, 0, sizeof(oh)); 08549 oh.vars = vars; 08550 oh.account = account; 08551 08552 if (locked_channel) 08553 *locked_channel = NULL; 08554 if (ast_strlen_zero(app)) { 08555 res = -1; 08556 goto outgoing_app_cleanup; 08557 } 08558 if (synchronous) { 08559 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08560 if (chan) { 08561 ast_set_variables(chan, vars); 08562 if (account) 08563 ast_cdr_setaccount(chan, account); 08564 if (chan->_state == AST_STATE_UP) { 08565 res = 0; 08566 ast_verb(4, "Channel %s was answered.\n", chan->name); 08567 tmp = ast_calloc(1, sizeof(*tmp)); 08568 if (!tmp) 08569 res = -1; 08570 else { 08571 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 08572 if (appdata) 08573 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 08574 tmp->chan = chan; 08575 if (synchronous > 1) { 08576 if (locked_channel) 08577 ast_channel_unlock(chan); 08578 ast_pbx_run_app(tmp); 08579 } else { 08580 if (locked_channel) 08581 ast_channel_lock(chan); 08582 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 08583 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 08584 ast_free(tmp); 08585 if (locked_channel) 08586 ast_channel_unlock(chan); 08587 ast_hangup(chan); 08588 res = -1; 08589 } else { 08590 if (locked_channel) 08591 *locked_channel = chan; 08592 } 08593 } 08594 } 08595 } else { 08596 ast_verb(4, "Channel %s was never answered.\n", chan->name); 08597 if (chan->cdr) { /* update the cdr */ 08598 /* here we update the status of the call, which sould be busy. 08599 * if that fails then we set the status to failed */ 08600 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 08601 ast_cdr_failed(chan->cdr); 08602 } 08603 ast_hangup(chan); 08604 } 08605 } 08606 08607 if (res < 0) { /* the call failed for some reason */ 08608 if (*reason == 0) { /* if the call failed (not busy or no answer) 08609 * update the cdr with the failed message */ 08610 cdr_res = ast_pbx_outgoing_cdr_failed(); 08611 if (cdr_res != 0) { 08612 res = cdr_res; 08613 goto outgoing_app_cleanup; 08614 } 08615 } 08616 } 08617 08618 } else { 08619 struct async_stat *as; 08620 if (!(as = ast_calloc(1, sizeof(*as)))) { 08621 res = -1; 08622 goto outgoing_app_cleanup; 08623 } 08624 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08625 if (!chan) { 08626 ast_free(as); 08627 res = -1; 08628 goto outgoing_app_cleanup; 08629 } 08630 as->chan = chan; 08631 ast_copy_string(as->app, app, sizeof(as->app)); 08632 if (appdata) 08633 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 08634 as->timeout = timeout; 08635 ast_set_variables(chan, vars); 08636 if (account) 08637 ast_cdr_setaccount(chan, account); 08638 /* Start a new thread, and get something handling this channel. */ 08639 if (locked_channel) 08640 ast_channel_lock(chan); 08641 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 08642 ast_log(LOG_WARNING, "Failed to start async wait\n"); 08643 ast_free(as); 08644 if (locked_channel) 08645 ast_channel_unlock(chan); 08646 ast_hangup(chan); 08647 res = -1; 08648 goto outgoing_app_cleanup; 08649 } else { 08650 if (locked_channel) 08651 *locked_channel = chan; 08652 } 08653 res = 0; 08654 } 08655 outgoing_app_cleanup: 08656 ast_variables_destroy(vars); 08657 return res; 08658 }
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 8375 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().
08376 { 08377 struct ast_channel *chan; 08378 struct async_stat *as; 08379 int res = -1, cdr_res = -1; 08380 struct outgoing_helper oh; 08381 08382 if (synchronous) { 08383 oh.context = context; 08384 oh.exten = exten; 08385 oh.priority = priority; 08386 oh.cid_num = cid_num; 08387 oh.cid_name = cid_name; 08388 oh.account = account; 08389 oh.vars = vars; 08390 oh.parent_channel = NULL; 08391 08392 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 08393 if (channel) { 08394 *channel = chan; 08395 if (chan) 08396 ast_channel_lock(chan); 08397 } 08398 if (chan) { 08399 if (chan->_state == AST_STATE_UP) { 08400 res = 0; 08401 ast_verb(4, "Channel %s was answered.\n", chan->name); 08402 08403 if (synchronous > 1) { 08404 if (channel) 08405 ast_channel_unlock(chan); 08406 if (ast_pbx_run(chan)) { 08407 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08408 if (channel) 08409 *channel = NULL; 08410 ast_hangup(chan); 08411 chan = NULL; 08412 res = -1; 08413 } 08414 } else { 08415 if (ast_pbx_start(chan)) { 08416 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 08417 if (channel) { 08418 *channel = NULL; 08419 ast_channel_unlock(chan); 08420 } 08421 ast_hangup(chan); 08422 res = -1; 08423 } 08424 chan = NULL; 08425 } 08426 } else { 08427 ast_verb(4, "Channel %s was never answered.\n", chan->name); 08428 08429 if (chan->cdr) { /* update the cdr */ 08430 /* here we update the status of the call, which sould be busy. 08431 * if that fails then we set the status to failed */ 08432 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 08433 ast_cdr_failed(chan->cdr); 08434 } 08435 08436 if (channel) { 08437 *channel = NULL; 08438 ast_channel_unlock(chan); 08439 } 08440 ast_hangup(chan); 08441 chan = NULL; 08442 } 08443 } 08444 08445 if (res < 0) { /* the call failed for some reason */ 08446 if (*reason == 0) { /* if the call failed (not busy or no answer) 08447 * update the cdr with the failed message */ 08448 cdr_res = ast_pbx_outgoing_cdr_failed(); 08449 if (cdr_res != 0) { 08450 res = cdr_res; 08451 goto outgoing_exten_cleanup; 08452 } 08453 } 08454 08455 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 08456 /* check if "failed" exists */ 08457 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 08458 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 08459 if (chan) { 08460 char failed_reason[4] = ""; 08461 if (!ast_strlen_zero(context)) 08462 ast_copy_string(chan->context, context, sizeof(chan->context)); 08463 set_ext_pri(chan, "failed", 1); 08464 ast_set_variables(chan, vars); 08465 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 08466 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 08467 if (account) 08468 ast_cdr_setaccount(chan, account); 08469 if (ast_pbx_run(chan)) { 08470 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 08471 ast_hangup(chan); 08472 } 08473 chan = NULL; 08474 } 08475 } 08476 } 08477 } else { 08478 if (!(as = ast_calloc(1, sizeof(*as)))) { 08479 res = -1; 08480 goto outgoing_exten_cleanup; 08481 } 08482 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 08483 if (channel) { 08484 *channel = chan; 08485 if (chan) 08486 ast_channel_lock(chan); 08487 } 08488 if (!chan) { 08489 ast_free(as); 08490 res = -1; 08491 goto outgoing_exten_cleanup; 08492 } 08493 as->chan = chan; 08494 ast_copy_string(as->context, context, sizeof(as->context)); 08495 set_ext_pri(as->chan, exten, priority); 08496 as->timeout = timeout; 08497 ast_set_variables(chan, vars); 08498 if (account) 08499 ast_cdr_setaccount(chan, account); 08500 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 08501 ast_log(LOG_WARNING, "Failed to start async wait\n"); 08502 ast_free(as); 08503 if (channel) { 08504 *channel = NULL; 08505 ast_channel_unlock(chan); 08506 } 08507 ast_hangup(chan); 08508 res = -1; 08509 goto outgoing_exten_cleanup; 08510 } 08511 res = 0; 08512 } 08513 outgoing_exten_cleanup: 08514 ast_variables_destroy(vars); 08515 return res; 08516 }
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 5059 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().
05060 { 05061 return ast_pbx_run_args(c, NULL); 05062 }
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 5044 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().
05045 { 05046 enum ast_pbx_result res = AST_PBX_SUCCESS; 05047 05048 if (increase_call_count(c)) { 05049 return AST_PBX_CALL_LIMIT; 05050 } 05051 05052 res = __ast_pbx_run(c, args); 05053 05054 decrease_call_count(); 05055 05056 return res; 05057 }
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 5022 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(), ss7_start_call(), unistim_new(), and usbradio_new().
05023 { 05024 pthread_t t; 05025 05026 if (!c) { 05027 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05028 return AST_PBX_FAILED; 05029 } 05030 05031 if (increase_call_count(c)) 05032 return AST_PBX_CALL_LIMIT; 05033 05034 /* Start a new thread, and get something handling this channel. */ 05035 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05036 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05037 decrease_call_count(); 05038 return AST_PBX_FAILED; 05039 } 05040 05041 return AST_PBX_SUCCESS; 05042 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5069 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05070 { 05071 return totalcalls; 05072 }
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 9927 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().
09928 { 09929 return ast_rwlock_rdlock(&con->lock); 09930 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 9909 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(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
09910 { 09911 return ast_mutex_lock(&conlock); 09912 }
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 5591 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().
05592 { 05593 struct ast_switch *tmp; 05594 05595 AST_RWLIST_WRLOCK(&switches); 05596 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 05597 if (!strcasecmp(tmp->name, sw->name)) { 05598 AST_RWLIST_UNLOCK(&switches); 05599 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 05600 return -1; 05601 } 05602 } 05603 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 05604 AST_RWLIST_UNLOCK(&switches); 05605 05606 return 0; 05607 }
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 4603 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().
04604 { 04605 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 04606 }
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 4558 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().
04559 { 04560 struct ast_exten *e = ast_hint_extension(c, context, exten); 04561 04562 if (!e) { 04563 return 0; 04564 } 04565 04566 if (hint) { 04567 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 04568 } 04569 if (name) { 04570 const char *tmp = ast_get_extension_app_data(e); 04571 if (tmp) { 04572 ast_str_set(name, namesize, "%s", tmp); 04573 } 04574 } 04575 return -1; 04576 }
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 2987 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().
02988 { 02989 const char not_found = '\0'; 02990 char *tmpvar; 02991 const char *ret; 02992 const char *s; /* the result */ 02993 int offset, length; 02994 int i, need_substring; 02995 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 02996 02997 if (c) { 02998 ast_channel_lock(c); 02999 places[0] = &c->varshead; 03000 } 03001 /* 03002 * Make a copy of var because parse_variable_name() modifies the string. 03003 * Then if called directly, we might need to run substring() on the result; 03004 * remember this for later in 'need_substring', 'offset' and 'length' 03005 */ 03006 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03007 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03008 03009 /* 03010 * Look first into predefined variables, then into variable lists. 03011 * Variable 's' points to the result, according to the following rules: 03012 * s == ¬_found (set at the beginning) means that we did not find a 03013 * matching variable and need to look into more places. 03014 * If s != ¬_found, s is a valid result string as follows: 03015 * s = NULL if the variable does not have a value; 03016 * you typically do this when looking for an unset predefined variable. 03017 * s = workspace if the result has been assembled there; 03018 * typically done when the result is built e.g. with an snprintf(), 03019 * so we don't need to do an additional copy. 03020 * s != workspace in case we have a string, that needs to be copied 03021 * (the ast_copy_string is done once for all at the end). 03022 * Typically done when the result is already available in some string. 03023 */ 03024 s = ¬_found; /* default value */ 03025 if (c) { /* This group requires a valid channel */ 03026 /* Names with common parts are looked up a piece at a time using strncmp. */ 03027 if (!strncmp(var, "CALL", 4)) { 03028 if (!strncmp(var + 4, "ING", 3)) { 03029 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03030 ast_str_set(str, maxlen, "%d", 03031 ast_party_id_presentation(&c->caller.id)); 03032 s = ast_str_buffer(*str); 03033 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03034 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03035 s = ast_str_buffer(*str); 03036 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03037 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03038 s = ast_str_buffer(*str); 03039 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03040 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03041 s = ast_str_buffer(*str); 03042 } 03043 } 03044 } else if (!strcmp(var, "HINT")) { 03045 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03046 } else if (!strcmp(var, "HINTNAME")) { 03047 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03048 } else if (!strcmp(var, "EXTEN")) { 03049 s = c->exten; 03050 } else if (!strcmp(var, "CONTEXT")) { 03051 s = c->context; 03052 } else if (!strcmp(var, "PRIORITY")) { 03053 ast_str_set(str, maxlen, "%d", c->priority); 03054 s = ast_str_buffer(*str); 03055 } else if (!strcmp(var, "CHANNEL")) { 03056 s = c->name; 03057 } else if (!strcmp(var, "UNIQUEID")) { 03058 s = c->uniqueid; 03059 } else if (!strcmp(var, "HANGUPCAUSE")) { 03060 ast_str_set(str, maxlen, "%d", c->hangupcause); 03061 s = ast_str_buffer(*str); 03062 } 03063 } 03064 if (s == ¬_found) { /* look for more */ 03065 if (!strcmp(var, "EPOCH")) { 03066 ast_str_set(str, maxlen, "%u", (int) time(NULL)); 03067 s = ast_str_buffer(*str); 03068 } else if (!strcmp(var, "SYSTEMNAME")) { 03069 s = ast_config_AST_SYSTEM_NAME; 03070 } else if (!strcmp(var, "ENTITYID")) { 03071 char workspace[20]; 03072 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03073 s = workspace; 03074 } 03075 } 03076 /* if not found, look into chanvars or global vars */ 03077 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03078 struct ast_var_t *variables; 03079 if (!places[i]) 03080 continue; 03081 if (places[i] == &globals) 03082 ast_rwlock_rdlock(&globalslock); 03083 AST_LIST_TRAVERSE(places[i], variables, entries) { 03084 if (!strcasecmp(ast_var_name(variables), var)) { 03085 s = ast_var_value(variables); 03086 break; 03087 } 03088 } 03089 if (places[i] == &globals) 03090 ast_rwlock_unlock(&globalslock); 03091 } 03092 if (s == ¬_found || s == NULL) { 03093 ast_debug(5, "Result of '%s' is NULL\n", var); 03094 ret = NULL; 03095 } else { 03096 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03097 if (s != ast_str_buffer(*str)) { 03098 ast_str_set(str, maxlen, "%s", s); 03099 } 03100 ret = ast_str_buffer(*str); 03101 if (need_substring) { 03102 ret = ast_str_substring(*str, offset, length); 03103 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03104 } 03105 } 03106 03107 if (c) { 03108 ast_channel_unlock(c); 03109 } 03110 return ret; 03111 }
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 3765 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().
03766 { 03767 size_t used; 03768 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 03769 }
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 3589 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().
03590 { 03591 /* Substitutes variables into buf, based on string templ */ 03592 char *cp4 = NULL; 03593 const char *tmp, *whereweare; 03594 int orig_size = 0; 03595 int offset, offset2, isfunction; 03596 const char *nextvar, *nextexp, *nextthing; 03597 const char *vars, *vare; 03598 char *finalvars; 03599 int pos, brackets, needsub, len; 03600 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 03601 03602 ast_str_reset(*buf); 03603 whereweare = tmp = templ; 03604 while (!ast_strlen_zero(whereweare)) { 03605 /* Assume we're copying the whole remaining string */ 03606 pos = strlen(whereweare); 03607 nextvar = NULL; 03608 nextexp = NULL; 03609 nextthing = strchr(whereweare, '$'); 03610 if (nextthing) { 03611 switch (nextthing[1]) { 03612 case '{': 03613 nextvar = nextthing; 03614 pos = nextvar - whereweare; 03615 break; 03616 case '[': 03617 nextexp = nextthing; 03618 pos = nextexp - whereweare; 03619 break; 03620 default: 03621 pos = 1; 03622 } 03623 } 03624 03625 if (pos) { 03626 /* Copy that many bytes */ 03627 ast_str_append_substr(buf, maxlen, whereweare, pos); 03628 03629 templ += pos; 03630 whereweare += pos; 03631 } 03632 03633 if (nextvar) { 03634 /* We have a variable. Find the start and end, and determine 03635 if we are going to have to recursively call ourselves on the 03636 contents */ 03637 vars = vare = nextvar + 2; 03638 brackets = 1; 03639 needsub = 0; 03640 03641 /* Find the end of it */ 03642 while (brackets && *vare) { 03643 if ((vare[0] == '$') && (vare[1] == '{')) { 03644 needsub++; 03645 } else if (vare[0] == '{') { 03646 brackets++; 03647 } else if (vare[0] == '}') { 03648 brackets--; 03649 } else if ((vare[0] == '$') && (vare[1] == '[')) 03650 needsub++; 03651 vare++; 03652 } 03653 if (brackets) 03654 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 03655 len = vare - vars - 1; 03656 03657 /* Skip totally over variable string */ 03658 whereweare += (len + 3); 03659 03660 /* Store variable name (and truncate) */ 03661 ast_str_set_substr(&substr1, 0, vars, len); 03662 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 03663 03664 /* Substitute if necessary */ 03665 if (needsub) { 03666 size_t used; 03667 if (!substr2) { 03668 substr2 = ast_str_create(16); 03669 } 03670 03671 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03672 finalvars = ast_str_buffer(substr2); 03673 } else { 03674 finalvars = ast_str_buffer(substr1); 03675 } 03676 03677 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 03678 if (isfunction) { 03679 /* Evaluate function */ 03680 if (c || !headp) { 03681 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03682 } else { 03683 struct varshead old; 03684 struct ast_channel *bogus = ast_dummy_channel_alloc(); 03685 if (bogus) { 03686 memcpy(&old, &bogus->varshead, sizeof(old)); 03687 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 03688 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 03689 /* Don't deallocate the varshead that was passed in */ 03690 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 03691 ast_channel_release(bogus); 03692 } else { 03693 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03694 } 03695 } 03696 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03697 } else { 03698 /* Retrieve variable value */ 03699 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 03700 cp4 = ast_str_buffer(substr3); 03701 } 03702 if (cp4) { 03703 ast_str_substring(substr3, offset, offset2); 03704 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 03705 } 03706 } else if (nextexp) { 03707 /* We have an expression. Find the start and end, and determine 03708 if we are going to have to recursively call ourselves on the 03709 contents */ 03710 vars = vare = nextexp + 2; 03711 brackets = 1; 03712 needsub = 0; 03713 03714 /* Find the end of it */ 03715 while (brackets && *vare) { 03716 if ((vare[0] == '$') && (vare[1] == '[')) { 03717 needsub++; 03718 brackets++; 03719 vare++; 03720 } else if (vare[0] == '[') { 03721 brackets++; 03722 } else if (vare[0] == ']') { 03723 brackets--; 03724 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03725 needsub++; 03726 vare++; 03727 } 03728 vare++; 03729 } 03730 if (brackets) 03731 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03732 len = vare - vars - 1; 03733 03734 /* Skip totally over expression */ 03735 whereweare += (len + 3); 03736 03737 /* Store variable name (and truncate) */ 03738 ast_str_set_substr(&substr1, 0, vars, len); 03739 03740 /* Substitute if necessary */ 03741 if (needsub) { 03742 size_t used; 03743 if (!substr2) { 03744 substr2 = ast_str_create(16); 03745 } 03746 03747 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 03748 finalvars = ast_str_buffer(substr2); 03749 } else { 03750 finalvars = ast_str_buffer(substr1); 03751 } 03752 03753 if (ast_str_expr(&substr3, 0, c, finalvars)) { 03754 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 03755 } 03756 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 03757 } 03758 } 03759 *used = ast_str_strlen(*buf) - orig_size; 03760 ast_free(substr1); 03761 ast_free(substr2); 03762 ast_free(substr3); 03763 }
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 3771 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().
03772 { 03773 size_t used; 03774 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 03775 }
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 9932 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().
09933 { 09934 return ast_rwlock_unlock(&con->lock); 09935 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 9914 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(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
09915 { 09916 return ast_mutex_unlock(&conlock); 09917 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 5609 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().
05610 { 05611 AST_RWLIST_WRLOCK(&switches); 05612 AST_RWLIST_REMOVE(&switches, sw, list); 05613 AST_RWLIST_UNLOCK(&switches); 05614 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | priority | |||
) |
Definition at line 10046 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().
10048 { 10049 if (!exten) 10050 return con ? con->root : NULL; 10051 else 10052 return exten->next; 10053 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) |
Definition at line 10079 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().
10081 { 10082 if (!ip) 10083 return con ? con->ignorepats : NULL; 10084 else 10085 return ip->next; 10086 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) |
Definition at line 10070 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().
10072 { 10073 if (!inc) 10074 return con ? con->includes : NULL; 10075 else 10076 return inc->next; 10077 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) |
Definition at line 10055 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().
10057 { 10058 if (!sw) 10059 return con ? AST_LIST_FIRST(&con->alts) : NULL; 10060 else 10061 return AST_LIST_NEXT(sw, list); 10062 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) |
Definition at line 10041 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 10064 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 9922 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().
09923 { 09924 return ast_rwlock_wrlock(&con->lock); 09925 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 9904 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().
09905 { 09906 return ast_mutex_lock(&conlock); 09907 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 9694 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().
09695 { 09696 struct ast_var_t *vardata; 09697 09698 ast_rwlock_wrlock(&globalslock); 09699 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 09700 ast_var_delete(vardata); 09701 ast_rwlock_unlock(&globalslock); 09702 }
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 9456 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(), sig_ss7_call(), sig_ss7_hangup(), sip_addheader(), sla_trunk_exec(), speech_background(), try_suggested_sip_codec(), and update_bridge_vars().
09457 { 09458 struct ast_var_t *variables; 09459 const char *ret = NULL; 09460 int i; 09461 struct varshead *places[2] = { NULL, &globals }; 09462 09463 if (!name) 09464 return NULL; 09465 09466 if (chan) { 09467 ast_channel_lock(chan); 09468 places[0] = &chan->varshead; 09469 } 09470 09471 for (i = 0; i < 2; i++) { 09472 if (!places[i]) 09473 continue; 09474 if (places[i] == &globals) 09475 ast_rwlock_rdlock(&globalslock); 09476 AST_LIST_TRAVERSE(places[i], variables, entries) { 09477 if (!strcmp(name, ast_var_name(variables))) { 09478 ret = ast_var_value(variables); 09479 break; 09480 } 09481 } 09482 if (places[i] == &globals) 09483 ast_rwlock_unlock(&globalslock); 09484 if (ret) 09485 break; 09486 } 09487 09488 if (chan) 09489 ast_channel_unlock(chan); 09490 09491 return ret; 09492 }
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 9494 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().
09495 { 09496 struct ast_var_t *newvariable; 09497 struct varshead *headp; 09498 09499 if (name[strlen(name)-1] == ')') { 09500 char *function = ast_strdupa(name); 09501 09502 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 09503 ast_func_write(chan, function, value); 09504 return; 09505 } 09506 09507 if (chan) { 09508 ast_channel_lock(chan); 09509 headp = &chan->varshead; 09510 } else { 09511 ast_rwlock_wrlock(&globalslock); 09512 headp = &globals; 09513 } 09514 09515 if (value) { 09516 if (headp == &globals) 09517 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09518 newvariable = ast_var_assign(name, value); 09519 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09520 } 09521 09522 if (chan) 09523 ast_channel_unlock(chan); 09524 else 09525 ast_rwlock_unlock(&globalslock); 09526 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
const char * | data | |||
) |
Definition at line 3125 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().
03126 { 03127 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 03128 struct pbx_exception *exception = NULL; 03129 03130 if (!ds) { 03131 ds = ast_datastore_alloc(&exception_store_info, NULL); 03132 if (!ds) 03133 return -1; 03134 if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) { 03135 ast_datastore_free(ds); 03136 return -1; 03137 } 03138 ds->data = exception; 03139 ast_channel_datastore_add(chan, ds); 03140 } else 03141 exception = ds->data; 03142 03143 ast_string_field_set(exception, reason, reason); 03144 ast_string_field_set(exception, context, chan->context); 03145 ast_string_field_set(exception, exten, chan->exten); 03146 exception->priority = chan->priority; 03147 set_ext_pri(chan, "e", 0); 03148 return 0; 03149 }
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 9425 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().
09426 { 09427 struct ast_var_t *variables; 09428 const char *var, *val; 09429 int total = 0; 09430 09431 if (!chan) 09432 return 0; 09433 09434 ast_str_reset(*buf); 09435 09436 ast_channel_lock(chan); 09437 09438 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 09439 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 09440 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 09441 ) { 09442 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 09443 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 09444 break; 09445 } else 09446 total++; 09447 } else 09448 break; 09449 } 09450 09451 ast_channel_unlock(chan); 09452 09453 return total; 09454 }
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 9586 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().
09587 { 09588 char *name, *value, *mydata; 09589 09590 if (ast_compat_app_set) { 09591 return pbx_builtin_setvar_multiple(chan, data); 09592 } 09593 09594 if (ast_strlen_zero(data)) { 09595 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 09596 return 0; 09597 } 09598 09599 mydata = ast_strdupa(data); 09600 name = strsep(&mydata, "="); 09601 value = mydata; 09602 if (!value) { 09603 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 09604 return 0; 09605 } 09606 09607 if (strchr(name, ' ')) { 09608 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 09609 } 09610 09611 pbx_builtin_setvar_helper(chan, name, value); 09612 09613 return 0; 09614 }
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 9528 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(), 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(), sig_ss7_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(), ss7_start_call(), 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().
09529 { 09530 struct ast_var_t *newvariable; 09531 struct varshead *headp; 09532 const char *nametail = name; 09533 09534 if (name[strlen(name) - 1] == ')') { 09535 char *function = ast_strdupa(name); 09536 09537 return ast_func_write(chan, function, value); 09538 } 09539 09540 if (chan) { 09541 ast_channel_lock(chan); 09542 headp = &chan->varshead; 09543 } else { 09544 ast_rwlock_wrlock(&globalslock); 09545 headp = &globals; 09546 } 09547 09548 /* For comparison purposes, we have to strip leading underscores */ 09549 if (*nametail == '_') { 09550 nametail++; 09551 if (*nametail == '_') 09552 nametail++; 09553 } 09554 09555 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 09556 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 09557 /* there is already such a variable, delete it */ 09558 AST_LIST_REMOVE_CURRENT(entries); 09559 ast_var_delete(newvariable); 09560 break; 09561 } 09562 } 09563 AST_LIST_TRAVERSE_SAFE_END; 09564 09565 if (value) { 09566 if (headp == &globals) 09567 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 09568 newvariable = ast_var_assign(name, value); 09569 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 09570 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 09571 "Channel: %s\r\n" 09572 "Variable: %s\r\n" 09573 "Value: %s\r\n" 09574 "Uniqueid: %s\r\n", 09575 chan ? chan->name : "none", name, value, 09576 chan ? chan->uniqueid : "none"); 09577 } 09578 09579 if (chan) 09580 ast_channel_unlock(chan); 09581 else 09582 ast_rwlock_unlock(&globalslock); 09583 return 0; 09584 }
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 9616 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().
09617 { 09618 char *data; 09619 int x; 09620 AST_DECLARE_APP_ARGS(args, 09621 AST_APP_ARG(pair)[24]; 09622 ); 09623 AST_DECLARE_APP_ARGS(pair, 09624 AST_APP_ARG(name); 09625 AST_APP_ARG(value); 09626 ); 09627 09628 if (ast_strlen_zero(vdata)) { 09629 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 09630 return 0; 09631 } 09632 09633 data = ast_strdupa(vdata); 09634 AST_STANDARD_APP_ARGS(args, data); 09635 09636 for (x = 0; x < args.argc; x++) { 09637 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 09638 if (pair.argc == 2) { 09639 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 09640 if (strchr(pair.name, ' ')) 09641 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); 09642 } else if (!chan) { 09643 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 09644 } else { 09645 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 09646 } 09647 } 09648 09649 return 0; 09650 }
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 9704 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().
09705 { 09706 int res; 09707 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 09708 return 0; 09709 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 09710 return res; 09711 } else { /* Strings are true */ 09712 return 1; 09713 } 09714 }
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 1379 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().
01382 { 01383 int res; 01384 struct ast_module_user *u = NULL; 01385 const char *saved_c_appl; 01386 const char *saved_c_data; 01387 01388 if (c->cdr && !ast_check_hangup(c)) 01389 ast_cdr_setapp(c->cdr, app->name, data); 01390 01391 /* save channel values */ 01392 saved_c_appl= c->appl; 01393 saved_c_data= c->data; 01394 01395 c->appl = app->name; 01396 c->data = data; 01397 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01398 01399 if (app->module) 01400 u = __ast_module_user_add(app->module, c); 01401 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01402 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01403 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01404 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01405 app->name, (char *) data); 01406 } 01407 res = app->execute(c, S_OR(data, "")); 01408 if (app->module && u) 01409 __ast_module_user_remove(app->module, u); 01410 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01411 /* restore channel values */ 01412 c->appl = saved_c_appl; 01413 c->data = saved_c_data; 01414 return res; 01415 }
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 2551 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().
02555 { 02556 int x, res; 02557 struct ast_context *tmp = NULL; 02558 struct ast_exten *e = NULL, *eroot = NULL; 02559 struct ast_include *i = NULL; 02560 struct ast_sw *sw = NULL; 02561 struct ast_exten pattern = {NULL, }; 02562 struct scoreboard score = {0, }; 02563 struct ast_str *tmpdata = NULL; 02564 02565 pattern.label = label; 02566 pattern.priority = priority; 02567 #ifdef NEED_DEBUG_HERE 02568 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02569 #endif 02570 02571 /* Initialize status if appropriate */ 02572 if (q->stacklen == 0) { 02573 q->status = STATUS_NO_CONTEXT; 02574 q->swo = NULL; 02575 q->data = NULL; 02576 q->foundcontext = NULL; 02577 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02578 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02579 return NULL; 02580 } 02581 02582 /* Check first to see if we've already been checked */ 02583 for (x = 0; x < q->stacklen; x++) { 02584 if (!strcasecmp(q->incstack[x], context)) 02585 return NULL; 02586 } 02587 02588 if (bypass) { /* bypass means we only look there */ 02589 tmp = bypass; 02590 } else { /* look in contexts */ 02591 struct fake_context item; 02592 02593 ast_copy_string(item.name, context, sizeof(item.name)); 02594 02595 tmp = ast_hashtab_lookup(contexts_table, &item); 02596 if (!tmp) { 02597 return NULL; 02598 } 02599 } 02600 02601 if (q->status < STATUS_NO_EXTENSION) 02602 q->status = STATUS_NO_EXTENSION; 02603 02604 /* Do a search for matching extension */ 02605 02606 eroot = NULL; 02607 score.total_specificity = 0; 02608 score.exten = 0; 02609 score.total_length = 0; 02610 if (!tmp->pattern_tree && tmp->root_table) { 02611 create_match_char_tree(tmp); 02612 #ifdef NEED_DEBUG 02613 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 02614 log_match_char_tree(tmp->pattern_tree," "); 02615 #endif 02616 } 02617 #ifdef NEED_DEBUG 02618 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 02619 log_match_char_tree(tmp->pattern_tree, ":: "); 02620 #endif 02621 02622 do { 02623 if (!ast_strlen_zero(overrideswitch)) { 02624 char *osw = ast_strdupa(overrideswitch), *name; 02625 struct ast_switch *asw; 02626 ast_switch_f *aswf = NULL; 02627 char *datap; 02628 int eval = 0; 02629 02630 name = strsep(&osw, "/"); 02631 asw = pbx_findswitch(name); 02632 02633 if (!asw) { 02634 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 02635 break; 02636 } 02637 02638 if (osw && strchr(osw, '$')) { 02639 eval = 1; 02640 } 02641 02642 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02643 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!"); 02644 break; 02645 } else if (eval) { 02646 /* Substitute variables now */ 02647 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02648 datap = ast_str_buffer(tmpdata); 02649 } else { 02650 datap = osw; 02651 } 02652 02653 /* equivalent of extension_match_core() at the switch level */ 02654 if (action == E_CANMATCH) 02655 aswf = asw->canmatch; 02656 else if (action == E_MATCHMORE) 02657 aswf = asw->matchmore; 02658 else /* action == E_MATCH */ 02659 aswf = asw->exists; 02660 if (!aswf) { 02661 res = 0; 02662 } else { 02663 if (chan) { 02664 ast_autoservice_start(chan); 02665 } 02666 res = aswf(chan, context, exten, priority, callerid, datap); 02667 if (chan) { 02668 ast_autoservice_stop(chan); 02669 } 02670 } 02671 if (res) { /* Got a match */ 02672 q->swo = asw; 02673 q->data = datap; 02674 q->foundcontext = context; 02675 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02676 return NULL; 02677 } 02678 } 02679 } while (0); 02680 02681 if (extenpatternmatchnew) { 02682 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02683 eroot = score.exten; 02684 02685 if (score.last_char == '!' && action == E_MATCHMORE) { 02686 /* We match an extension ending in '!'. 02687 * The decision in this case is final and is NULL (no match). 02688 */ 02689 #ifdef NEED_DEBUG_HERE 02690 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02691 #endif 02692 return NULL; 02693 } 02694 02695 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02696 q->status = STATUS_SUCCESS; 02697 #ifdef NEED_DEBUG_HERE 02698 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02699 #endif 02700 return score.canmatch_exten; 02701 } 02702 02703 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02704 if (score.node) { 02705 struct ast_exten *z = trie_find_next_match(score.node); 02706 if (z) { 02707 #ifdef NEED_DEBUG_HERE 02708 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02709 #endif 02710 } else { 02711 if (score.canmatch_exten) { 02712 #ifdef NEED_DEBUG_HERE 02713 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02714 #endif 02715 return score.canmatch_exten; 02716 } else { 02717 #ifdef NEED_DEBUG_HERE 02718 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02719 #endif 02720 } 02721 } 02722 return z; 02723 } 02724 #ifdef NEED_DEBUG_HERE 02725 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02726 #endif 02727 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02728 } 02729 02730 if (eroot) { 02731 /* found entry, now look for the right priority */ 02732 if (q->status < STATUS_NO_PRIORITY) 02733 q->status = STATUS_NO_PRIORITY; 02734 e = NULL; 02735 if (action == E_FINDLABEL && label ) { 02736 if (q->status < STATUS_NO_LABEL) 02737 q->status = STATUS_NO_LABEL; 02738 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02739 } else { 02740 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02741 } 02742 if (e) { /* found a valid match */ 02743 q->status = STATUS_SUCCESS; 02744 q->foundcontext = context; 02745 #ifdef NEED_DEBUG_HERE 02746 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 02747 #endif 02748 return e; 02749 } 02750 } 02751 } else { /* the old/current default exten pattern match algorithm */ 02752 02753 /* scan the list trying to match extension and CID */ 02754 eroot = NULL; 02755 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 02756 int match = extension_match_core(eroot->exten, exten, action); 02757 /* 0 on fail, 1 on match, 2 on earlymatch */ 02758 02759 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 02760 continue; /* keep trying */ 02761 if (match == 2 && action == E_MATCHMORE) { 02762 /* We match an extension ending in '!'. 02763 * The decision in this case is final and is NULL (no match). 02764 */ 02765 return NULL; 02766 } 02767 /* found entry, now look for the right priority */ 02768 if (q->status < STATUS_NO_PRIORITY) 02769 q->status = STATUS_NO_PRIORITY; 02770 e = NULL; 02771 if (action == E_FINDLABEL && label ) { 02772 if (q->status < STATUS_NO_LABEL) 02773 q->status = STATUS_NO_LABEL; 02774 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02775 } else { 02776 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02777 } 02778 if (e) { /* found a valid match */ 02779 q->status = STATUS_SUCCESS; 02780 q->foundcontext = context; 02781 return e; 02782 } 02783 } 02784 } 02785 02786 /* Check alternative switches */ 02787 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 02788 struct ast_switch *asw = pbx_findswitch(sw->name); 02789 ast_switch_f *aswf = NULL; 02790 char *datap; 02791 02792 if (!asw) { 02793 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 02794 continue; 02795 } 02796 02797 /* Substitute variables now */ 02798 if (sw->eval) { 02799 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02800 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 02801 continue; 02802 } 02803 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 02804 } 02805 02806 /* equivalent of extension_match_core() at the switch level */ 02807 if (action == E_CANMATCH) 02808 aswf = asw->canmatch; 02809 else if (action == E_MATCHMORE) 02810 aswf = asw->matchmore; 02811 else /* action == E_MATCH */ 02812 aswf = asw->exists; 02813 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 02814 if (!aswf) 02815 res = 0; 02816 else { 02817 if (chan) 02818 ast_autoservice_start(chan); 02819 res = aswf(chan, context, exten, priority, callerid, datap); 02820 if (chan) 02821 ast_autoservice_stop(chan); 02822 } 02823 if (res) { /* Got a match */ 02824 q->swo = asw; 02825 q->data = datap; 02826 q->foundcontext = context; 02827 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02828 return NULL; 02829 } 02830 } 02831 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 02832 /* Now try any includes we have in this context */ 02833 for (i = tmp->includes; i; i = i->next) { 02834 if (include_valid(i)) { 02835 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 02836 #ifdef NEED_DEBUG_HERE 02837 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 02838 #endif 02839 return e; 02840 } 02841 if (q->swo) 02842 return NULL; 02843 } 02844 } 02845 return NULL; 02846 }
struct ast_app* pbx_findapp | ( | const char * | app | ) |
Look up an application.
app | name of the app |
Definition at line 1423 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().
01424 { 01425 struct ast_app *tmp; 01426 01427 AST_RWLIST_RDLOCK(&apps); 01428 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01429 if (!strcasecmp(tmp->name, app)) 01430 break; 01431 } 01432 AST_RWLIST_UNLOCK(&apps); 01433 01434 return tmp; 01435 }
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 2976 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().
02977 { 02978 struct ast_str *str = ast_str_create(16); 02979 const char *cret; 02980 02981 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 02982 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 02983 *ret = cret ? workspace : NULL; 02984 ast_free(str); 02985 }
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 5074 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05075 { 05076 int oldval = autofallthrough; 05077 autofallthrough = newval; 05078 return oldval; 05079 }
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 5081 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05082 { 05083 int oldval = extenpatternmatchnew; 05084 extenpatternmatchnew = newval; 05085 return oldval; 05086 }
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 5088 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05089 { 05090 if (overrideswitch) { 05091 ast_free(overrideswitch); 05092 } 05093 if (!ast_strlen_zero(newval)) { 05094 overrideswitch = ast_strdup(newval); 05095 } else { 05096 overrideswitch = NULL; 05097 } 05098 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 3973 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().
03974 { 03975 size_t used; 03976 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 03977 }
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 3777 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().
03778 { 03779 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 03780 char *cp4 = NULL; 03781 const char *tmp, *whereweare, *orig_cp2 = cp2; 03782 int length, offset, offset2, isfunction; 03783 char *workspace = NULL; 03784 char *ltmp = NULL, *var = NULL; 03785 char *nextvar, *nextexp, *nextthing; 03786 char *vars, *vare; 03787 int pos, brackets, needsub, len; 03788 03789 *cp2 = 0; /* just in case nothing ends up there */ 03790 whereweare=tmp=cp1; 03791 while (!ast_strlen_zero(whereweare) && count) { 03792 /* Assume we're copying the whole remaining string */ 03793 pos = strlen(whereweare); 03794 nextvar = NULL; 03795 nextexp = NULL; 03796 nextthing = strchr(whereweare, '$'); 03797 if (nextthing) { 03798 switch (nextthing[1]) { 03799 case '{': 03800 nextvar = nextthing; 03801 pos = nextvar - whereweare; 03802 break; 03803 case '[': 03804 nextexp = nextthing; 03805 pos = nextexp - whereweare; 03806 break; 03807 default: 03808 pos = 1; 03809 } 03810 } 03811 03812 if (pos) { 03813 /* Can't copy more than 'count' bytes */ 03814 if (pos > count) 03815 pos = count; 03816 03817 /* Copy that many bytes */ 03818 memcpy(cp2, whereweare, pos); 03819 03820 count -= pos; 03821 cp2 += pos; 03822 whereweare += pos; 03823 *cp2 = 0; 03824 } 03825 03826 if (nextvar) { 03827 /* We have a variable. Find the start and end, and determine 03828 if we are going to have to recursively call ourselves on the 03829 contents */ 03830 vars = vare = nextvar + 2; 03831 brackets = 1; 03832 needsub = 0; 03833 03834 /* Find the end of it */ 03835 while (brackets && *vare) { 03836 if ((vare[0] == '$') && (vare[1] == '{')) { 03837 needsub++; 03838 } else if (vare[0] == '{') { 03839 brackets++; 03840 } else if (vare[0] == '}') { 03841 brackets--; 03842 } else if ((vare[0] == '$') && (vare[1] == '[')) 03843 needsub++; 03844 vare++; 03845 } 03846 if (brackets) 03847 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 03848 len = vare - vars - 1; 03849 03850 /* Skip totally over variable string */ 03851 whereweare += (len + 3); 03852 03853 if (!var) 03854 var = alloca(VAR_BUF_SIZE); 03855 03856 /* Store variable name (and truncate) */ 03857 ast_copy_string(var, vars, len + 1); 03858 03859 /* Substitute if necessary */ 03860 if (needsub) { 03861 size_t used; 03862 if (!ltmp) 03863 ltmp = alloca(VAR_BUF_SIZE); 03864 03865 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 03866 vars = ltmp; 03867 } else { 03868 vars = var; 03869 } 03870 03871 if (!workspace) 03872 workspace = alloca(VAR_BUF_SIZE); 03873 03874 workspace[0] = '\0'; 03875 03876 parse_variable_name(vars, &offset, &offset2, &isfunction); 03877 if (isfunction) { 03878 /* Evaluate function */ 03879 if (c || !headp) 03880 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03881 else { 03882 struct varshead old; 03883 struct ast_channel *c = ast_dummy_channel_alloc(); 03884 if (c) { 03885 memcpy(&old, &c->varshead, sizeof(old)); 03886 memcpy(&c->varshead, headp, sizeof(c->varshead)); 03887 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 03888 /* Don't deallocate the varshead that was passed in */ 03889 memcpy(&c->varshead, &old, sizeof(c->varshead)); 03890 c = ast_channel_release(c); 03891 } else { 03892 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03893 } 03894 } 03895 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 03896 } else { 03897 /* Retrieve variable value */ 03898 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 03899 } 03900 if (cp4) { 03901 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 03902 03903 length = strlen(cp4); 03904 if (length > count) 03905 length = count; 03906 memcpy(cp2, cp4, length); 03907 count -= length; 03908 cp2 += length; 03909 *cp2 = 0; 03910 } 03911 } else if (nextexp) { 03912 /* We have an expression. Find the start and end, and determine 03913 if we are going to have to recursively call ourselves on the 03914 contents */ 03915 vars = vare = nextexp + 2; 03916 brackets = 1; 03917 needsub = 0; 03918 03919 /* Find the end of it */ 03920 while (brackets && *vare) { 03921 if ((vare[0] == '$') && (vare[1] == '[')) { 03922 needsub++; 03923 brackets++; 03924 vare++; 03925 } else if (vare[0] == '[') { 03926 brackets++; 03927 } else if (vare[0] == ']') { 03928 brackets--; 03929 } else if ((vare[0] == '$') && (vare[1] == '{')) { 03930 needsub++; 03931 vare++; 03932 } 03933 vare++; 03934 } 03935 if (brackets) 03936 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 03937 len = vare - vars - 1; 03938 03939 /* Skip totally over expression */ 03940 whereweare += (len + 3); 03941 03942 if (!var) 03943 var = alloca(VAR_BUF_SIZE); 03944 03945 /* Store variable name (and truncate) */ 03946 ast_copy_string(var, vars, len + 1); 03947 03948 /* Substitute if necessary */ 03949 if (needsub) { 03950 size_t used; 03951 if (!ltmp) 03952 ltmp = alloca(VAR_BUF_SIZE); 03953 03954 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 03955 vars = ltmp; 03956 } else { 03957 vars = var; 03958 } 03959 03960 length = ast_expr(vars, cp2, count, c); 03961 03962 if (length) { 03963 ast_debug(1, "Expression result is '%s'\n", cp2); 03964 count -= length; 03965 cp2 += length; 03966 *cp2 = 0; 03967 } 03968 } 03969 } 03970 *used = cp2 - orig_cp2; 03971 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 3979 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by dundi_lookup_local(), and loopback_subst().
03980 { 03981 size_t used; 03982 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 03983 }