Core PBX routines and definitions. More...
#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 |
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 void(* | ast_state_cb_destroy_type )(int id, void *data) |
Typedef for devicestate and hint callback removal indication callback. | |
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, 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). | |
struct ast_context * | ast_context_find (const char *name) |
Find a context. | |
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. | |
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. | |
struct 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 change_cb, void *data) |
Registers a state change callback. | |
int | ast_extension_state_add_destroy (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data) |
Registers a state change callback with destructor. | |
int | ast_extension_state_del (int id, ast_state_cb_type change_cb) |
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. | |
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) |
struct 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) |
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) |
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 ... | |
struct ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority) |
struct ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
struct ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
struct ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
struct ast_context * | ast_walk_contexts (struct ast_context *con) |
struct 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) |
| |
#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) |
const char * | ast_get_context_name (struct ast_context *con) |
struct 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) |
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) |
Core PBX routines and definitions.
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 1144 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(), print_app_docs(), and sla_build_station().
#define AST_PBX_ERROR 1 |
#define AST_PBX_GOTO_FAILED -3 |
Definition at line 41 of file pbx.h.
Referenced by __ast_goto_if_exists().
#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 __ast_pbx_run(), 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(), add_priority(), ast_add_extension2_lockopt(), ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), destroy_exten(), destroy_space(), destroy_station(), handle_cli_dialplan_add_extension(), handle_cli_dialplan_remove_extension(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), park_add_hints(), pbx_load_config(), print_ext(), and sla_build_station().
typedef void(* ast_state_cb_destroy_type)(int id, void *data) |
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 289 of file pbx.h.
00289 { 00290 AST_PBX_SUCCESS = 0, 00291 AST_PBX_FAILED = -1, 00292 AST_PBX_CALL_LIMIT = -2, 00293 };
enum ext_match_t |
When looking up extensions, we can have different requests identified by the 'action' argument, as follows.
E_MATCHMORE | |
E_CANMATCH | |
E_MATCH | |
E_MATCH_MASK | |
E_SPAWN | |
E_FINDLABEL | |
E_MATCHMORE | |
E_CANMATCH | |
E_MATCH | |
E_MATCH_MASK | |
E_SPAWN | |
E_FINDLABEL |
Definition at line 1213 of file pbx.h.
01213 { 01214 E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */ 01215 E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */ 01216 E_MATCH = 0x02, /* extension is an exact match */ 01217 E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */ 01218 E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */ 01219 E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */ 01220 };
int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
struct ast_module * | mod | |||
) |
Register a custom function.
Definition at line 3814 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().
03815 { 03816 struct ast_custom_function *cur; 03817 char tmps[80]; 03818 03819 if (!acf) { 03820 return -1; 03821 } 03822 03823 acf->mod = mod; 03824 #ifdef AST_XML_DOCS 03825 acf->docsrc = AST_STATIC_DOC; 03826 #endif 03827 03828 if (acf_retrieve_docs(acf)) { 03829 return -1; 03830 } 03831 03832 AST_RWLIST_WRLOCK(&acf_root); 03833 03834 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 03835 if (!strcmp(acf->name, cur->name)) { 03836 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 03837 AST_RWLIST_UNLOCK(&acf_root); 03838 return -1; 03839 } 03840 } 03841 03842 /* Store in alphabetical order */ 03843 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 03844 if (strcasecmp(acf->name, cur->name) < 0) { 03845 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 03846 break; 03847 } 03848 } 03849 AST_RWLIST_TRAVERSE_SAFE_END; 03850 03851 if (!cur) { 03852 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 03853 } 03854 03855 AST_RWLIST_UNLOCK(&acf_root); 03856 03857 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 03858 03859 return 0; 03860 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 5631 of file pbx.c.
References countcalls.
Referenced by ast_var_Config(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().
05632 { 05633 return countcalls; 05634 }
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 8364 of file pbx.c.
References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_extension_state(), ast_extension_state_add_destroy(), handle_cli_dialplan_add_extension(), manage_parked_call(), park_add_hints(), park_call_full(), parkinglot_activate(), register_exten(), register_peer_exten(), and RegisterExtension().
08367 { 08368 int ret = -1; 08369 struct ast_context *c; 08370 08371 c = find_context_locked(context); 08372 if (c) { 08373 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 08374 application, data, datad, registrar); 08375 ast_unlock_contexts(); 08376 } 08377 08378 return ret; 08379 }
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 *.
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 8725 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by add_extensions(), ast_add_extension(), context_merge(), load_module(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().
08729 { 08730 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, 08731 application, data, datad, registrar, 1); 08732 }
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 8404 of file pbx.c.
References ast_channel::_state, accountcode, ast_channel::amaflags, 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_strdupa, ast_channel::cdr, ast_channel::context, ast_channel::exten, LOG_WARNING, 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().
08405 { 08406 int res = 0; 08407 struct ast_channel *tmpchan; 08408 struct { 08409 char *accountcode; 08410 char *exten; 08411 char *context; 08412 char *linkedid; 08413 char *name; 08414 struct ast_cdr *cdr; 08415 int amaflags; 08416 int state; 08417 format_t readformat; 08418 format_t writeformat; 08419 } tmpvars = { 0, }; 08420 08421 ast_channel_lock(chan); 08422 if (chan->pbx) { /* This channel is currently in the PBX */ 08423 ast_explicit_goto(chan, context, exten, priority + 1); 08424 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 08425 ast_channel_unlock(chan); 08426 return res; 08427 } 08428 08429 /* In order to do it when the channel doesn't really exist within 08430 * the PBX, we have to make a new channel, masquerade, and start the PBX 08431 * at the new location */ 08432 tmpvars.accountcode = ast_strdupa(chan->accountcode); 08433 tmpvars.exten = ast_strdupa(chan->exten); 08434 tmpvars.context = ast_strdupa(chan->context); 08435 tmpvars.linkedid = ast_strdupa(chan->linkedid); 08436 tmpvars.name = ast_strdupa(chan->name); 08437 tmpvars.amaflags = chan->amaflags; 08438 tmpvars.state = chan->_state; 08439 tmpvars.writeformat = chan->writeformat; 08440 tmpvars.readformat = chan->readformat; 08441 tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL; 08442 08443 ast_channel_unlock(chan); 08444 08445 /* Do not hold any channel locks while calling channel_alloc() since the function 08446 * locks the channel container when linking the new channel in. */ 08447 if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) { 08448 ast_cdr_discard(tmpvars.cdr); 08449 return -1; 08450 } 08451 08452 /* copy the cdr info over */ 08453 if (tmpvars.cdr) { 08454 ast_cdr_discard(tmpchan->cdr); 08455 tmpchan->cdr = tmpvars.cdr; 08456 tmpvars.cdr = NULL; 08457 } 08458 08459 /* Make formats okay */ 08460 tmpchan->readformat = tmpvars.readformat; 08461 tmpchan->writeformat = tmpvars.writeformat; 08462 08463 /* Setup proper location. Never hold another channel lock while calling this function. */ 08464 ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority); 08465 08466 /* Masquerade into tmp channel */ 08467 if (ast_channel_masquerade(tmpchan, chan)) { 08468 /* Failed to set up the masquerade. It's probably chan_local 08469 * in the middle of optimizing itself out. Sad. :( */ 08470 ast_hangup(tmpchan); 08471 tmpchan = NULL; 08472 res = -1; 08473 } else { 08474 ast_do_masquerade(tmpchan); 08475 /* Start the PBX going on our stolen channel */ 08476 if (ast_pbx_start(tmpchan)) { 08477 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 08478 ast_hangup(tmpchan); 08479 res = -1; 08480 } 08481 } 08482 08483 return res; 08484 }
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 8486 of file pbx.c.
References ast_async_goto(), ast_channel_get_by_name(), and ast_channel_unref.
08487 { 08488 struct ast_channel *chan; 08489 int res = -1; 08490 08491 if ((chan = ast_channel_get_by_name(channame))) { 08492 res = ast_async_goto(chan, context, exten, priority); 08493 chan = ast_channel_unref(chan); 08494 } 08495 08496 return res; 08497 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10846 of file pbx.c.
References __ast_goto_if_exists().
10847 { 10848 return __ast_goto_if_exists(chan, context, exten, priority, 1); 10849 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10911 of file pbx.c.
References pbx_parseable_goto().
Referenced by asyncgoto_exec(), and handle_redirect().
10912 { 10913 return pbx_parseable_goto(chan, goto_string, 1); 10914 }
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 7987 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, and ast_timing::timezone.
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
07988 { 07989 char *info; 07990 int j, num_fields, last_sep = -1; 07991 07992 /* Check for empty just in case */ 07993 if (ast_strlen_zero(info_in)) { 07994 return 0; 07995 } 07996 07997 /* make a copy just in case we were passed a static string */ 07998 info = ast_strdupa(info_in); 07999 08000 /* count the number of fields in the timespec */ 08001 for (j = 0, num_fields = 1; info[j] != '\0'; j++) { 08002 if (info[j] == ',') { 08003 last_sep = j; 08004 num_fields++; 08005 } 08006 } 08007 08008 /* save the timezone, if it is specified */ 08009 if (num_fields == 5) { 08010 i->timezone = ast_strdup(info + last_sep + 1); 08011 } else { 08012 i->timezone = NULL; 08013 } 08014 08015 /* Assume everything except time */ 08016 i->monthmask = 0xfff; /* 12 bits */ 08017 i->daymask = 0x7fffffffU; /* 31 bits */ 08018 i->dowmask = 0x7f; /* 7 bits */ 08019 /* on each call, use strsep() to move info to the next argument */ 08020 get_timerange(i, strsep(&info, "|,")); 08021 if (info) 08022 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 08023 if (info) 08024 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 08025 if (info) 08026 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 08027 return 1; 08028 }
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 5115 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(), leave_voicemail(), loopback_canmatch(), mgcp_ss(), pbx_builtin_background(), phone_check_exception(), skinny_ss(), and valid_exit().
05116 { 05117 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 05118 }
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 8030 of file pbx.c.
References ast_check_timing2(), and ast_tvnow().
Referenced by iftime(), include_valid(), and pbx_builtin_execiftime().
08031 { 08032 return ast_check_timing2(i, ast_tvnow()); 08033 }
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 8035 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().
08036 { 08037 struct ast_tm tm; 08038 08039 ast_localtime(&tv, &tm, i->timezone); 08040 08041 /* If it's not the right month, return */ 08042 if (!(i->monthmask & (1 << tm.tm_mon))) 08043 return 0; 08044 08045 /* If it's not that time of the month.... */ 08046 /* Warning, tm_mday has range 1..31! */ 08047 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 08048 return 0; 08049 08050 /* If it's not the right day of the week */ 08051 if (!(i->dowmask & (1 << tm.tm_wday))) 08052 return 0; 08053 08054 /* Sanity check the hour just to be safe */ 08055 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 08056 ast_log(LOG_WARNING, "Insane time...\n"); 08057 return 0; 08058 } 08059 08060 /* Now the tough part, we calculate if it fits 08061 in the right time based on min/hour */ 08062 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)))) 08063 return 0; 08064 08065 /* If we got this far, then we're good */ 08066 return 1; 08067 }
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 10916 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, and ast_app::name.
Referenced by handle_orig(), and handle_show_application().
10917 { 10918 struct ast_app *app = NULL; 10919 int which = 0; 10920 char *ret = NULL; 10921 size_t wordlen = strlen(word); 10922 10923 AST_RWLIST_RDLOCK(&apps); 10924 AST_RWLIST_TRAVERSE(&apps, app, list) { 10925 if (!strncasecmp(word, app->name, wordlen) && ++which > state) { 10926 ret = ast_strdup(app->name); 10927 break; 10928 } 10929 } 10930 AST_RWLIST_UNLOCK(&apps); 10931 10932 return ret; 10933 }
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 |
Adds an ignore pattern to a particular context.
0 | on success | |
-1 | on failure |
Definition at line 8271 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
08272 { 08273 int ret = -1; 08274 struct ast_context *c; 08275 08276 c = find_context_locked(context); 08277 if (c) { 08278 ret = ast_context_add_ignorepat2(c, value, registrar); 08279 ast_unlock_contexts(); 08280 } 08281 return ret; 08282 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8284 of file pbx.c.
References ast_calloc, 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_compile_ael2(), ast_context_add_ignorepat(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
08285 { 08286 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 08287 int length; 08288 char *pattern; 08289 length = sizeof(struct ast_ignorepat); 08290 length += strlen(value) + 1; 08291 if (!(ignorepat = ast_calloc(1, length))) 08292 return -1; 08293 /* The cast to char * is because we need to write the initial value. 08294 * The field is not supposed to be modified otherwise. Also, gcc 4.2 08295 * sees the cast as dereferencing a type-punned pointer and warns about 08296 * it. This is the workaround (we're telling gcc, yes, that's really 08297 * what we wanted to do). 08298 */ 08299 pattern = (char *) ignorepat->pattern; 08300 strcpy(pattern, value); 08301 ignorepat->next = NULL; 08302 ignorepat->registrar = registrar; 08303 ast_wrlock_context(con); 08304 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 08305 ignorepatl = ignorepatc; 08306 if (!strcasecmp(ignorepatc->pattern, value)) { 08307 /* Already there */ 08308 ast_unlock_context(con); 08309 ast_free(ignorepat); 08310 errno = EEXIST; 08311 return -1; 08312 } 08313 } 08314 if (ignorepatl) 08315 ignorepatl->next = ignorepat; 08316 else 08317 con->ignorepats = ignorepat; 08318 ast_unlock_context(con); 08319 return 0; 08320 08321 }
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 |
Adds an include taking a char * string as the context parameter
0 | on success | |
-1 | on error |
Definition at line 7815 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
07816 { 07817 int ret = -1; 07818 struct ast_context *c; 07819 07820 c = find_context_locked(context); 07821 if (c) { 07822 ret = ast_context_add_include2(c, include, registrar); 07823 ast_unlock_contexts(); 07824 } 07825 return ret; 07826 }
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 |
Adds an include taking a struct ast_context as the first parameter
0 | on success | |
-1 | on failure |
Definition at line 8084 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_compile_ael2(), ast_context_add_include(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
08086 { 08087 struct ast_include *new_include; 08088 char *c; 08089 struct ast_include *i, *il = NULL; /* include, include_last */ 08090 int length; 08091 char *p; 08092 08093 length = sizeof(struct ast_include); 08094 length += 2 * (strlen(value) + 1); 08095 08096 /* allocate new include structure ... */ 08097 if (!(new_include = ast_calloc(1, length))) 08098 return -1; 08099 /* Fill in this structure. Use 'p' for assignments, as the fields 08100 * in the structure are 'const char *' 08101 */ 08102 p = new_include->stuff; 08103 new_include->name = p; 08104 strcpy(p, value); 08105 p += strlen(value) + 1; 08106 new_include->rname = p; 08107 strcpy(p, value); 08108 /* Strip off timing info, and process if it is there */ 08109 if ( (c = strchr(p, ',')) ) { 08110 *c++ = '\0'; 08111 new_include->hastime = ast_build_timing(&(new_include->timing), c); 08112 } 08113 new_include->next = NULL; 08114 new_include->registrar = registrar; 08115 08116 ast_wrlock_context(con); 08117 08118 /* ... go to last include and check if context is already included too... */ 08119 for (i = con->includes; i; i = i->next) { 08120 if (!strcasecmp(i->name, new_include->name)) { 08121 ast_destroy_timing(&(new_include->timing)); 08122 ast_free(new_include); 08123 ast_unlock_context(con); 08124 errno = EEXIST; 08125 return -1; 08126 } 08127 il = i; 08128 } 08129 08130 /* ... include new context into context list, unlock, return */ 08131 if (il) 08132 il->next = new_include; 08133 else 08134 con->includes = new_include; 08135 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 08136 08137 ast_unlock_context(con); 08138 08139 return 0; 08140 }
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 |
This function registers a switch with the asterisk switch architecture
0 | on success | |
-1 | on failure |
Definition at line 8147 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
08148 { 08149 int ret = -1; 08150 struct ast_context *c; 08151 08152 c = find_context_locked(context); 08153 if (c) { /* found, add switch to this context */ 08154 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 08155 ast_unlock_contexts(); 08156 } 08157 return ret; 08158 }
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 8167 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, ast_sw::name, ast_sw::registrar, and ast_sw::stuff.
Referenced by ast_compile_ael2(), ast_context_add_switch(), context_merge_incls_swits_igps_other_registrars(), lua_register_switches(), and pbx_load_config().
08169 { 08170 struct ast_sw *new_sw; 08171 struct ast_sw *i; 08172 int length; 08173 char *p; 08174 08175 length = sizeof(struct ast_sw); 08176 length += strlen(value) + 1; 08177 if (data) 08178 length += strlen(data); 08179 length++; 08180 08181 /* allocate new sw structure ... */ 08182 if (!(new_sw = ast_calloc(1, length))) 08183 return -1; 08184 /* ... fill in this structure ... */ 08185 p = new_sw->stuff; 08186 new_sw->name = p; 08187 strcpy(new_sw->name, value); 08188 p += strlen(value) + 1; 08189 new_sw->data = p; 08190 if (data) { 08191 strcpy(new_sw->data, data); 08192 p += strlen(data) + 1; 08193 } else { 08194 strcpy(new_sw->data, ""); 08195 p++; 08196 } 08197 new_sw->eval = eval; 08198 new_sw->registrar = registrar; 08199 08200 /* ... try to lock this context ... */ 08201 ast_wrlock_context(con); 08202 08203 /* ... go to last sw and check if context is already swd too... */ 08204 AST_LIST_TRAVERSE(&con->alts, i, list) { 08205 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 08206 ast_free(new_sw); 08207 ast_unlock_context(con); 08208 errno = EEXIST; 08209 return -1; 08210 } 08211 } 08212 08213 /* ... sw new context into context list, unlock, return */ 08214 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 08215 08216 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 08217 08218 ast_unlock_context(con); 08219 08220 return 0; 08221 }
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 |
You can optionally leave out either parameter. It will find it based on either the ast_context or the registrar name.
Definition at line 9548 of file pbx.c.
References __ast_context_destroy(), ast_unlock_contexts(), ast_wrlock_contexts(), contexts, and contexts_table.
Referenced by __unload_module(), ast_features_reload(), cleanup_stale_contexts(), remove_dead_dialplan_useage(), sla_destroy(), and unload_module().
09549 { 09550 ast_wrlock_contexts(); 09551 __ast_context_destroy(contexts, contexts_table, con,registrar); 09552 ast_unlock_contexts(); 09553 }
struct ast_context* ast_context_find | ( | const char * | name | ) | [read] |
Find a context.
name | name of the context to find |
Will search for the context with the given name.
Definition at line 2896 of file pbx.c.
References ast_copy_string(), ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::name, and fake_context::name.
Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_features_reload(), ast_ignore_pattern(), cleanup_stale_contexts(), isexten_function_read(), manage_parkinglot(), parked_call_exec(), register_exten(), register_peer_exten(), remove_dead_dialplan_useage(), unload_module(), and unregister_exten().
02897 { 02898 struct ast_context *tmp; 02899 struct fake_context item; 02900 02901 if (!name) { 02902 return NULL; 02903 } 02904 ast_rdlock_contexts(); 02905 if (contexts_table) { 02906 ast_copy_string(item.name, name, sizeof(item.name)); 02907 tmp = ast_hashtab_lookup(contexts_table, &item); 02908 } else { 02909 tmp = NULL; 02910 while ((tmp = ast_walk_contexts(tmp))) { 02911 if (!strcasecmp(name, tmp->name)) { 02912 break; 02913 } 02914 } 02915 } 02916 ast_unlock_contexts(); 02917 return tmp; 02918 }
struct ast_context* ast_context_find_or_create | ( | struct ast_context ** | extcontexts, | |
struct ast_hashtab * | exttable, | |||
const char * | name, | |||
const char * | registrar | |||
) | [read] |
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 function allows you to play in two environments: the global contexts (active dialplan) or an external context set of your choosing. To act on the external set, make sure extcontexts and exttable are set; for the globals, make sure both extcontexts and exttable are NULL.
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 7414 of file pbx.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_insert_immediate(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_mutex_init, ast_rdlock_contexts(), ast_rwlock_init, ast_strdup, ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), contexts, contexts_table, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, ast_context::macrolock, ast_context::name, fake_context::name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by ast_compile_ael2(), config_parse_variables(), context_merge(), load_module(), lua_register_switches(), manage_parked_call(), parkinglot_activate(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().
07415 { 07416 struct ast_context *tmp, **local_contexts; 07417 struct fake_context search; 07418 int length = sizeof(struct ast_context) + strlen(name) + 1; 07419 07420 if (!contexts_table) { 07421 /* Protect creation of contexts_table from reentrancy. */ 07422 ast_wrlock_contexts(); 07423 if (!contexts_table) { 07424 contexts_table = ast_hashtab_create(17, 07425 ast_hashtab_compare_contexts, 07426 ast_hashtab_resize_java, 07427 ast_hashtab_newsize_java, 07428 ast_hashtab_hash_contexts, 07429 0); 07430 } 07431 ast_unlock_contexts(); 07432 } 07433 07434 ast_copy_string(search.name, name, sizeof(search.name)); 07435 if (!extcontexts) { 07436 ast_rdlock_contexts(); 07437 local_contexts = &contexts; 07438 tmp = ast_hashtab_lookup(contexts_table, &search); 07439 ast_unlock_contexts(); 07440 if (tmp) { 07441 tmp->refcount++; 07442 return tmp; 07443 } 07444 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 07445 local_contexts = extcontexts; 07446 tmp = ast_hashtab_lookup(exttable, &search); 07447 if (tmp) { 07448 tmp->refcount++; 07449 return tmp; 07450 } 07451 } 07452 07453 if ((tmp = ast_calloc(1, length))) { 07454 ast_rwlock_init(&tmp->lock); 07455 ast_mutex_init(&tmp->macrolock); 07456 strcpy(tmp->name, name); 07457 tmp->root = NULL; 07458 tmp->root_table = NULL; 07459 tmp->registrar = ast_strdup(registrar); 07460 tmp->includes = NULL; 07461 tmp->ignorepats = NULL; 07462 tmp->refcount = 1; 07463 } else { 07464 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 07465 return NULL; 07466 } 07467 07468 if (!extcontexts) { 07469 ast_wrlock_contexts(); 07470 tmp->next = *local_contexts; 07471 *local_contexts = tmp; 07472 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 07473 ast_unlock_contexts(); 07474 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 07475 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07476 } else { 07477 tmp->next = *local_contexts; 07478 if (exttable) 07479 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 07480 07481 *local_contexts = tmp; 07482 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 07483 ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar); 07484 } 07485 return tmp; 07486 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
macrocontext | name of the macro-context to lock |
Locks the given macro-context to ensure only one thread (call) can execute it at a time
0 | on success | |
-1 | on failure |
Definition at line 6009 of file pbx.c.
References ast_mutex_lock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06010 { 06011 struct ast_context *c; 06012 int ret = -1; 06013 06014 c = find_context_locked(context); 06015 if (c) { 06016 ast_unlock_contexts(); 06017 06018 /* if we found context, lock macrolock */ 06019 ret = ast_mutex_lock(&c->macrolock); 06020 } 06021 06022 return ret; 06023 }
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 |
This function removes an extension from a given context.
0 | on success | |
-1 | on failure |
Definition at line 5814 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), remove_exten_if_exist(), unregister_exten(), and UnregisterExtension().
05815 { 05816 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 05817 }
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 5844 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by manage_parkinglot(), parked_call_exec(), and unload_module().
05845 { 05846 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 05847 }
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 5819 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().
05820 { 05821 int ret = -1; /* default error return */ 05822 struct ast_context *c; 05823 05824 c = find_context_locked(context); 05825 if (c) { /* ... remove extension ... */ 05826 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, 05827 matchcallerid, registrar, 0); 05828 ast_unlock_contexts(); 05829 } 05830 05831 return ret; 05832 }
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 5849 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, match_char::deleted, destroy_exten(), match_char::exten, ast_exten::exten, exten, ast_exten::label, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_context::pattern_tree, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, ast_context::root, ast_context::root_table, and match_char::x.
Referenced by __ast_context_destroy(), ast_context_remove_extension2(), and ast_context_remove_extension_callerid().
05850 { 05851 struct ast_exten *exten, *prev_exten = NULL; 05852 struct ast_exten *peer; 05853 struct ast_exten ex, *exten2, *exten3; 05854 char dummy_name[1024]; 05855 struct ast_exten *previous_peer = NULL; 05856 struct ast_exten *next_peer = NULL; 05857 int found = 0; 05858 05859 if (!already_locked) 05860 ast_wrlock_context(con); 05861 05862 /* Handle this is in the new world */ 05863 05864 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 05865 * peers, not just those matching the callerid. */ 05866 #ifdef NEED_DEBUG 05867 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar); 05868 #endif 05869 #ifdef CONTEXT_DEBUG 05870 check_contexts(__FILE__, __LINE__); 05871 #endif 05872 /* find this particular extension */ 05873 ex.exten = dummy_name; 05874 ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 05875 ex.cidmatch = callerid; 05876 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 05877 exten = ast_hashtab_lookup(con->root_table, &ex); 05878 if (exten) { 05879 if (priority == 0) { 05880 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05881 if (!exten2) 05882 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); 05883 if (con->pattern_tree) { 05884 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05885 05886 if (x->exten) { /* this test for safety purposes */ 05887 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05888 x->exten = 0; /* get rid of what will become a bad pointer */ 05889 } else { 05890 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 05891 } 05892 } 05893 } else { 05894 ex.priority = priority; 05895 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 05896 if (exten2) { 05897 05898 if (exten2->label) { /* if this exten has a label, remove that, too */ 05899 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 05900 if (!exten3) 05901 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); 05902 } 05903 05904 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 05905 if (!exten3) 05906 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); 05907 if (exten2 == exten && exten2->peer) { 05908 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 05909 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 05910 } 05911 if (ast_hashtab_size(exten->peer_table) == 0) { 05912 /* well, if the last priority of an exten is to be removed, 05913 then, the extension is removed, too! */ 05914 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 05915 if (!exten3) 05916 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 05917 if (con->pattern_tree) { 05918 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 05919 if (x->exten) { /* this test for safety purposes */ 05920 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 05921 x->exten = 0; /* get rid of what will become a bad pointer */ 05922 } 05923 } 05924 } 05925 } else { 05926 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 05927 priority, exten->exten, con->name); 05928 } 05929 } 05930 } else { 05931 /* hmmm? this exten is not in this pattern tree? */ 05932 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 05933 extension, con->name); 05934 } 05935 #ifdef NEED_DEBUG 05936 if (con->pattern_tree) { 05937 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 05938 log_match_char_tree(con->pattern_tree, " "); 05939 } 05940 #endif 05941 05942 /* scan the extension list to find first matching extension-registrar */ 05943 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 05944 if (!strcmp(exten->exten, extension) && 05945 (!registrar || !strcmp(exten->registrar, registrar)) && 05946 (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 05947 break; 05948 } 05949 if (!exten) { 05950 /* we can't find right extension */ 05951 if (!already_locked) 05952 ast_unlock_context(con); 05953 return -1; 05954 } 05955 05956 /* scan the priority list to remove extension with exten->priority == priority */ 05957 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 05958 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))); 05959 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 05960 if ((priority == 0 || peer->priority == priority) && 05961 (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) && 05962 (!registrar || !strcmp(peer->registrar, registrar) )) { 05963 found = 1; 05964 05965 /* we are first priority extension? */ 05966 if (!previous_peer) { 05967 /* 05968 * We are first in the priority chain, so must update the extension chain. 05969 * The next node is either the next priority or the next extension 05970 */ 05971 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 05972 if (peer->peer) { 05973 /* move the peer_table and peer_label_table down to the next peer, if 05974 it is there */ 05975 peer->peer->peer_table = peer->peer_table; 05976 peer->peer->peer_label_table = peer->peer_label_table; 05977 peer->peer_table = NULL; 05978 peer->peer_label_table = NULL; 05979 } 05980 if (!prev_exten) { /* change the root... */ 05981 con->root = next_node; 05982 } else { 05983 prev_exten->next = next_node; /* unlink */ 05984 } 05985 if (peer->peer) { /* update the new head of the pri list */ 05986 peer->peer->next = peer->next; 05987 } 05988 } else { /* easy, we are not first priority in extension */ 05989 previous_peer->peer = peer->peer; 05990 } 05991 05992 /* now, free whole priority extension */ 05993 destroy_exten(peer); 05994 } else { 05995 previous_peer = peer; 05996 } 05997 } 05998 if (!already_locked) 05999 ast_unlock_context(con); 06000 return found ? 0 : -1; 06001 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8227 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
08228 { 08229 int ret = -1; 08230 struct ast_context *c; 08231 08232 c = find_context_locked(context); 08233 if (c) { 08234 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 08235 ast_unlock_contexts(); 08236 } 08237 return ret; 08238 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 8240 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().
08241 { 08242 struct ast_ignorepat *ip, *ipl = NULL; 08243 08244 ast_wrlock_context(con); 08245 08246 for (ip = con->ignorepats; ip; ip = ip->next) { 08247 if (!strcmp(ip->pattern, ignorepat) && 08248 (!registrar || (registrar == ip->registrar))) { 08249 if (ipl) { 08250 ipl->next = ip->next; 08251 ast_free(ip); 08252 } else { 08253 con->ignorepats = ip->next; 08254 ast_free(ip); 08255 } 08256 ast_unlock_context(con); 08257 return 0; 08258 } 08259 ipl = ip; 08260 } 08261 08262 ast_unlock_context(con); 08263 errno = EINVAL; 08264 return -1; 08265 }
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 5707 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
05708 { 05709 int ret = -1; 05710 struct ast_context *c; 05711 05712 c = find_context_locked(context); 05713 if (c) { 05714 /* found, remove include from this context ... */ 05715 ret = ast_context_remove_include2(c, include, registrar); 05716 ast_unlock_contexts(); 05717 } 05718 return ret; 05719 }
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 success |
Removes an include by an ast_context structure.
0 | on success. | |
-1 | on failure. |
Definition at line 5730 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().
05731 { 05732 struct ast_include *i, *pi = NULL; 05733 int ret = -1; 05734 05735 ast_wrlock_context(con); 05736 05737 /* find our include */ 05738 for (i = con->includes; i; pi = i, i = i->next) { 05739 if (!strcmp(i->name, include) && 05740 (!registrar || !strcmp(i->registrar, registrar))) { 05741 /* remove from list */ 05742 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 05743 if (pi) 05744 pi->next = i->next; 05745 else 05746 con->includes = i->next; 05747 /* free include and return */ 05748 ast_destroy_timing(&(i->timing)); 05749 ast_free(i); 05750 ret = 0; 05751 break; 05752 } 05753 } 05754 05755 ast_unlock_context(con); 05756 05757 return ret; 05758 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Removes a switch with the given parameters
0 | on success | |
-1 | on failure |
Definition at line 5765 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
05766 { 05767 int ret = -1; /* default error return */ 05768 struct ast_context *c; 05769 05770 c = find_context_locked(context); 05771 if (c) { 05772 /* remove switch from this context ... */ 05773 ret = ast_context_remove_switch2(c, sw, data, registrar); 05774 ast_unlock_contexts(); 05775 } 05776 return ret; 05777 }
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 5787 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::name, and ast_sw::registrar.
Referenced by ast_context_remove_switch().
05788 { 05789 struct ast_sw *i; 05790 int ret = -1; 05791 05792 ast_wrlock_context(con); 05793 05794 /* walk switches */ 05795 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 05796 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 05797 (!registrar || !strcmp(i->registrar, registrar))) { 05798 /* found, remove from list */ 05799 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 05800 AST_LIST_REMOVE_CURRENT(list); 05801 ast_free(i); /* free switch and return */ 05802 ret = 0; 05803 break; 05804 } 05805 } 05806 AST_LIST_TRAVERSE_SAFE_END; 05807 05808 ast_unlock_context(con); 05809 05810 return ret; 05811 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
macrocontext | name of the macro-context to unlock |
Unlocks the given macro-context so that another thread (call) can execute it
0 | on success | |
-1 | on failure |
Definition at line 6030 of file pbx.c.
References ast_mutex_unlock, ast_unlock_contexts(), find_context_locked(), and ast_context::macrolock.
Referenced by _macro_exec().
06031 { 06032 struct ast_context *c; 06033 int ret = -1; 06034 06035 c = find_context_locked(context); 06036 if (c) { 06037 ast_unlock_contexts(); 06038 06039 /* if we found context, unlock macrolock */ 06040 ret = ast_mutex_unlock(&c->macrolock); 06041 } 06042 06043 return ret; 06044 }
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 10801 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().
10802 { 10803 struct ast_include *inc = NULL; 10804 int res = 0; 10805 10806 while ( (inc = ast_walk_context_includes(con, inc)) ) { 10807 if (ast_context_find(inc->rname)) 10808 continue; 10809 10810 res = -1; 10811 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 10812 ast_get_context_name(con), inc->rname); 10813 break; 10814 } 10815 10816 return res; 10817 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 3725 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_compile_ael2(), 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().
03726 { 03727 struct ast_custom_function *acf = NULL; 03728 03729 AST_RWLIST_RDLOCK(&acf_root); 03730 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 03731 if (!strcmp(name, acf->name)) 03732 break; 03733 } 03734 AST_RWLIST_UNLOCK(&acf_root); 03735 03736 return acf; 03737 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 3739 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(), unload_module(), and unload_pbx().
03740 { 03741 struct ast_custom_function *cur; 03742 03743 if (!acf) { 03744 return -1; 03745 } 03746 03747 AST_RWLIST_WRLOCK(&acf_root); 03748 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) { 03749 #ifdef AST_XML_DOCS 03750 if (cur->docsrc == AST_XML_DOC) { 03751 ast_string_field_free_memory(acf); 03752 } 03753 #endif 03754 ast_verb(2, "Unregistered custom function %s\n", cur->name); 03755 } 03756 AST_RWLIST_UNLOCK(&acf_root); 03757 03758 return cur ? 0 : -1; 03759 }
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 8069 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().
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 4548 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_state3().
04549 { 04550 switch (devstate) { 04551 case AST_DEVICE_ONHOLD: 04552 return AST_EXTENSION_ONHOLD; 04553 case AST_DEVICE_BUSY: 04554 return AST_EXTENSION_BUSY; 04555 case AST_DEVICE_UNKNOWN: 04556 return AST_EXTENSION_NOT_INUSE; 04557 case AST_DEVICE_UNAVAILABLE: 04558 case AST_DEVICE_INVALID: 04559 return AST_EXTENSION_UNAVAILABLE; 04560 case AST_DEVICE_RINGINUSE: 04561 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 04562 case AST_DEVICE_RINGING: 04563 return AST_EXTENSION_RINGING; 04564 case AST_DEVICE_INUSE: 04565 return AST_EXTENSION_INUSE; 04566 case AST_DEVICE_NOT_INUSE: 04567 return AST_EXTENSION_NOT_INUSE; 04568 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */ 04569 break; 04570 } 04571 04572 return AST_EXTENSION_NOT_INUSE; 04573 }
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 5100 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_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmf(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), findmeexec(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_call(), local_devicestate(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), my_handle_dtmf(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), privacy_exec(), process_ast_dsp(), process_sdp(), readexten_exec(), register_peer_exten(), show_debug_helper(), sip_new(), sip_read(), skinny_ss(), socket_process(), try_calling(), vm_authenticate(), and waitstream_core().
05101 { 05102 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 05103 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8381 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(), disa_exec(), do_bridge_masquerade(), handle_setpriority(), pbx_parseable_goto(), and return_exec().
08382 { 08383 if (!chan) 08384 return -1; 08385 08386 ast_channel_lock(chan); 08387 08388 if (!ast_strlen_zero(context)) 08389 ast_copy_string(chan->context, context, sizeof(chan->context)); 08390 if (!ast_strlen_zero(exten)) 08391 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08392 if (priority > -1) { 08393 chan->priority = priority; 08394 /* see flag description in channel.h for explanation */ 08395 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 08396 chan->priority--; 08397 } 08398 08399 ast_channel_unlock(chan); 08400 08401 return 0; 08402 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 2873 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().
02874 { 02875 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 02876 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 02877 return extension_match_core(pattern, data, needmore); 02878 }
int ast_extension_cmp | ( | const char * | a, | |
const char * | b | |||
) |
Determine if one extension should match before another.
Checks whether or extension a should match before extension b
0 | if the two extensions have equal matching priority | |
1 | on a > b | |
-1 | on a < b |
Definition at line 2638 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
02639 { 02640 int cmp; 02641 02642 cmp = ext_cmp(a, b); 02643 if (cmp < 0) { 02644 return -1; 02645 } 02646 if (cmp > 0) { 02647 return 1; 02648 } 02649 return 0; 02650 }
int ast_extension_match | ( | const char * | pattern, | |
const char * | extension | |||
) |
Determine if a given extension matches a given pattern (in NXX format).
Checks whether or not the given extension matches the given pattern.
1 | on match | |
0 | on failure |
Definition at line 2868 of file pbx.c.
References E_MATCH, and extension_match_core().
Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), load_module(), loopback_canmatch(), loopback_exists(), loopback_matchmore(), lua_find_extension(), manager_show_dialplan_helper(), matchcid(), misdn_cfg_is_msn_valid(), realtime_switch_common(), reload(), and show_dialplan_helper().
02869 { 02870 return extension_match_core(pattern, data, E_MATCH); 02871 }
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 4618 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().
04619 { 04620 struct ast_exten *e; 04621 04622 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */ 04623 return -1; /* No hint, return -1 */ 04624 } 04625 04626 if (e->exten[0] == '_') { 04627 /* Create this hint on-the-fly */ 04628 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04629 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04630 e->registrar); 04631 if (!(e = ast_hint_extension(c, context, exten))) { 04632 /* Improbable, but not impossible */ 04633 return -1; 04634 } 04635 } 04636 04637 return ast_extension_state2(e); /* Check all devices in the hint */ 04638 }
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 4606 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().
04607 { 04608 int i; 04609 04610 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 04611 if (extension_states[i].extension_state == extension_state) 04612 return extension_states[i].text; 04613 } 04614 return "Unknown"; 04615 }
int ast_extension_state_add | ( | const char * | context, | |
const char * | exten, | |||
ast_state_cb_type | change_cb, | |||
void * | data | |||
) |
Registers a state change callback.
context | which context to look in | |
exten | which extension to get state | |
change_cb | callback to call if state changed | |
data | to pass to callback |
-1 | on failure | |
ID | on success |
Definition at line 4839 of file pbx.c.
References ast_extension_state_add_destroy().
Referenced by __init_manager(), load_module(), and skinny_register().
04841 { 04842 return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data); 04843 }
int ast_extension_state_add_destroy | ( | const char * | context, | |
const char * | exten, | |||
ast_state_cb_type | change_cb, | |||
ast_state_cb_destroy_type | destroy_cb, | |||
void * | data | |||
) |
Registers a state change callback with destructor.
context | which context to look in | |
exten | which extension to get state | |
change_cb | callback to call if state changed | |
destroy_cb | callback to call when registration destroyed. | |
data | to pass to callback |
-1 | on failure | |
ID | on success |
Definition at line 4752 of file pbx.c.
References ao2_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension(), ast_free_ptr(), ast_hint_extension(), ast_strdup, ast_hint::callbacks, ast_state_cb::change_cb, ast_exten::cidmatch, ast_exten::data, ast_state_cb::data, ast_state_cb::destroy_cb, destroy_state_cb(), ast_exten::exten, hints, ast_state_cb::id, ast_exten::label, ast_exten::matchcid, ast_context::name, OBJ_NODATA, OBJ_UNLINK, ast_exten::parent, ast_exten::priority, ast_exten::registrar, statecbs, and stateid.
Referenced by ast_extension_state_add(), and handle_request_subscribe().
04754 { 04755 struct ast_hint *hint; 04756 struct ast_state_cb *state_cb; 04757 struct ast_exten *e; 04758 int id; 04759 04760 /* If there's no context and extension: add callback to statecbs list */ 04761 if (!context && !exten) { 04762 /* Prevent multiple adds from adding the same change_cb at the same time. */ 04763 ao2_lock(statecbs); 04764 04765 /* Remove any existing change_cb. */ 04766 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA); 04767 04768 /* Now insert the change_cb */ 04769 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 04770 ao2_unlock(statecbs); 04771 return -1; 04772 } 04773 state_cb->id = 0; 04774 state_cb->change_cb = change_cb; 04775 state_cb->destroy_cb = destroy_cb; 04776 state_cb->data = data; 04777 ao2_link(statecbs, state_cb); 04778 04779 ao2_ref(state_cb, -1); 04780 ao2_unlock(statecbs); 04781 return 0; 04782 } 04783 04784 if (!context || !exten) 04785 return -1; 04786 04787 /* This callback type is for only one hint, so get the hint */ 04788 e = ast_hint_extension(NULL, context, exten); 04789 if (!e) { 04790 return -1; 04791 } 04792 04793 /* If this is a pattern, dynamically create a new extension for this 04794 * particular match. Note that this will only happen once for each 04795 * individual extension, because the pattern will no longer match first. 04796 */ 04797 if (e->exten[0] == '_') { 04798 ast_add_extension(e->parent->name, 0, exten, e->priority, e->label, 04799 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr, 04800 e->registrar); 04801 e = ast_hint_extension(NULL, context, exten); 04802 if (!e || e->exten[0] == '_') { 04803 return -1; 04804 } 04805 } 04806 04807 /* Find the hint in the hints container */ 04808 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 04809 hint = ao2_find(hints, e, 0); 04810 if (!hint) { 04811 ao2_unlock(hints); 04812 return -1; 04813 } 04814 04815 /* Now insert the callback in the callback list */ 04816 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) { 04817 ao2_ref(hint, -1); 04818 ao2_unlock(hints); 04819 return -1; 04820 } 04821 do { 04822 id = stateid++; /* Unique ID for this callback */ 04823 /* Do not allow id to ever be -1 or 0. */ 04824 } while (id == -1 || id == 0); 04825 state_cb->id = id; 04826 state_cb->change_cb = change_cb; /* Pointer to callback routine */ 04827 state_cb->destroy_cb = destroy_cb; 04828 state_cb->data = data; /* Data for the callback */ 04829 ao2_link(hint->callbacks, state_cb); 04830 04831 ao2_ref(state_cb, -1); 04832 ao2_ref(hint, -1); 04833 ao2_unlock(hints); 04834 04835 return id; 04836 }
int ast_extension_state_del | ( | int | id, | |
ast_state_cb_type | change_cb | |||
) |
Deletes a registered state change callback by ID.
id | of the registered state callback to delete | |
change_cb | callback to call if state changed (Used if id == 0 (global)) |
0 | success | |
-1 | failure |
Definition at line 4861 of file pbx.c.
References ao2_callback, ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_hint::callbacks, find_hint_by_cb_id(), hints, OBJ_UNLINK, and statecbs.
Referenced by dialog_unlink_all(), handle_request_subscribe(), skinny_unregister(), and unload_module().
04862 { 04863 struct ast_state_cb *p_cur; 04864 int ret = -1; 04865 04866 if (!id) { /* id == 0 is a callback without extension */ 04867 if (!change_cb) { 04868 return ret; 04869 } 04870 p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK); 04871 if (p_cur) { 04872 ret = 0; 04873 ao2_ref(p_cur, -1); 04874 } 04875 } else { /* callback with extension, find the callback based on ID */ 04876 struct ast_hint *hint; 04877 04878 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */ 04879 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id); 04880 if (hint) { 04881 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK); 04882 if (p_cur) { 04883 ret = 0; 04884 ao2_ref(p_cur, -1); 04885 } 04886 ao2_ref(hint, -1); 04887 } 04888 ao2_unlock(hints); 04889 } 04890 04891 return ret; 04892 }
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 5105 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().
05106 { 05107 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05108 }
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.
Definition at line 5110 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
05111 { 05112 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 05113 }
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 |
This application executes a function in read mode on a given channel.
0 | success | |
non-zero | failure |
Definition at line 3883 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, 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().
03884 { 03885 char *copy = ast_strdupa(function); 03886 char *args = func_args(copy); 03887 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03888 int res; 03889 struct ast_module_user *u = NULL; 03890 03891 if (acfptr == NULL) { 03892 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03893 } else if (!acfptr->read && !acfptr->read2) { 03894 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03895 } else if (acfptr->read) { 03896 if (acfptr->mod) { 03897 u = __ast_module_user_add(acfptr->mod, chan); 03898 } 03899 res = acfptr->read(chan, copy, args, workspace, len); 03900 if (acfptr->mod && u) { 03901 __ast_module_user_remove(acfptr->mod, u); 03902 } 03903 return res; 03904 } else { 03905 struct ast_str *str = ast_str_create(16); 03906 if (acfptr->mod) { 03907 u = __ast_module_user_add(acfptr->mod, chan); 03908 } 03909 res = acfptr->read2(chan, copy, args, &str, 0); 03910 if (acfptr->mod && u) { 03911 __ast_module_user_remove(acfptr->mod, u); 03912 } 03913 ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len); 03914 ast_free(str); 03915 return res; 03916 } 03917 return -1; 03918 }
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 |
This application executes a function in read mode on a given channel.
0 | success | |
non-zero | failure |
Definition at line 3920 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, copy(), func_args(), LOG_ERROR, maxsize, ast_custom_function::mod, ast_custom_function::read, ast_custom_function::read2, ast_custom_function::read_max, and VAR_BUF_SIZE.
Referenced by append_channel_vars(), and ast_str_substitute_variables_full().
03921 { 03922 char *copy = ast_strdupa(function); 03923 char *args = func_args(copy); 03924 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03925 int res; 03926 struct ast_module_user *u = NULL; 03927 03928 if (acfptr == NULL) { 03929 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03930 } else if (!acfptr->read && !acfptr->read2) { 03931 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 03932 } else { 03933 if (acfptr->mod) { 03934 u = __ast_module_user_add(acfptr->mod, chan); 03935 } 03936 ast_str_reset(*str); 03937 if (acfptr->read2) { 03938 /* ast_str enabled */ 03939 res = acfptr->read2(chan, copy, args, str, maxlen); 03940 } else { 03941 /* Legacy function pointer, allocate buffer for result */ 03942 int maxsize = ast_str_size(*str); 03943 if (maxlen > -1) { 03944 if (maxlen == 0) { 03945 if (acfptr->read_max) { 03946 maxsize = acfptr->read_max; 03947 } else { 03948 maxsize = VAR_BUF_SIZE; 03949 } 03950 } else { 03951 maxsize = maxlen; 03952 } 03953 ast_str_make_space(str, maxsize); 03954 } 03955 res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize); 03956 } 03957 if (acfptr->mod && u) { 03958 __ast_module_user_remove(acfptr->mod, u); 03959 } 03960 return res; 03961 } 03962 return -1; 03963 }
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 |
This application executes a function in write mode on a given channel.
0 | success | |
non-zero | failure |
Definition at line 3965 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), args, ast_custom_function_find(), ast_log(), ast_strdupa, 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().
03966 { 03967 char *copy = ast_strdupa(function); 03968 char *args = func_args(copy); 03969 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 03970 03971 if (acfptr == NULL) 03972 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 03973 else if (!acfptr->write) 03974 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 03975 else { 03976 int res; 03977 struct ast_module_user *u = NULL; 03978 if (acfptr->mod) 03979 u = __ast_module_user_add(acfptr->mod, chan); 03980 res = acfptr->write(chan, copy, args, value); 03981 if (acfptr->mod && u) 03982 __ast_module_user_remove(acfptr->mod, u); 03983 return res; 03984 } 03985 03986 return -1; 03987 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 10653 of file pbx.c.
References ast_context::name.
Referenced by _macro_exec(), ast_compile_ael2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_include2(), ast_context_remove_switch2(), ast_context_verify_includes(), ast_remove_hint(), 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(), destroy_hint(), dundi_precache_full(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().
10654 { 10655 return con ? con->name : NULL; 10656 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 10691 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().
10692 { 10693 return c ? c->registrar : NULL; 10694 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 10721 of file pbx.c.
References ast_exten::app.
Referenced by _macro_exec(), ast_add_hint(), ast_extension_state2(), ast_get_hint(), ast_str_get_hint(), find_matching_endwhile(), get_parking_exten(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), manager_show_dialplan_helper(), and print_ext().
10722 { 10723 return e ? e->app : NULL; 10724 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 10726 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), ast_masq_park_call_exten(), ast_park_call_exten(), ast_str_get_hint(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), print_ext(), and xfer_park_call_helper().
10727 { 10728 return e ? e->data : NULL; 10729 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 10716 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10717 { 10718 return e ? e->cidmatch : NULL; 10719 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 10658 of file pbx.c.
References ast_exten::parent.
Referenced by ast_remove_hint(), destroy_hint(), handle_show_hint(), handle_show_hints(), handle_statechange(), and hints_data_provider_get().
10659 { 10660 return exten ? exten->parent : NULL; 10661 }
const char* ast_get_extension_label | ( | struct ast_exten * | e | ) |
Definition at line 10668 of file pbx.c.
References ast_exten::label.
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 10711 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
10712 { 10713 return e ? e->matchcid : 0; 10714 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 10663 of file pbx.c.
References ast_exten::exten.
Referenced by ast_add_hint(), ast_remove_hint(), complete_core_show_hint(), complete_dialplan_remove_extension(), destroy_hint(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), hint_hash(), hints_data_provider_get(), manager_show_dialplan_helper(), and show_dialplan_helper().
10664 { 10665 return exten ? exten->exten : NULL; 10666 }
int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 10683 of file pbx.c.
References ast_exten::priority.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().
10684 { 10685 return exten ? exten->priority : -1; 10686 }
const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 10696 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10697 { 10698 return e ? e->registrar : NULL; 10699 }
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 5062 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().
05063 { 05064 struct ast_exten *e = ast_hint_extension(c, context, exten); 05065 05066 if (e) { 05067 if (hint) 05068 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 05069 if (name) { 05070 const char *tmp = ast_get_extension_app_data(e); 05071 if (tmp) 05072 ast_copy_string(name, tmp, namesize); 05073 } 05074 return -1; 05075 } 05076 return 0; 05077 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10678 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().
10679 { 10680 return ip ? ip->pattern : NULL; 10681 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 10706 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().
10707 { 10708 return ip ? ip->registrar : NULL; 10709 }
const char* ast_get_include_name | ( | struct ast_include * | include | ) |
Definition at line 10673 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 10701 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().
10702 { 10703 return i ? i->registrar : NULL; 10704 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 10736 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().
10737 { 10738 return sw ? sw->data : NULL; 10739 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 10741 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
10742 { 10743 return sw->eval; 10744 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 10731 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().
10732 { 10733 return sw ? sw->name : NULL; 10734 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 10746 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().
10747 { 10748 return sw ? sw->registrar : NULL; 10749 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 10841 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(), select_entry(), valid_exit(), vm_execmain(), and vmauthenticate().
10842 { 10843 return __ast_goto_if_exists(chan, context, exten, priority, 0); 10844 }
int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
const void * | ah_b | |||
) |
hashtable functions for contexts
Definition at line 1081 of file pbx.c.
References ast_context::name.
Referenced by ast_context_find_or_create(), lua_register_switches(), and pbx_load_module().
01082 { 01083 const struct ast_context *ac = ah_a; 01084 const struct ast_context *bc = ah_b; 01085 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */ 01086 return 1; 01087 /* assume context names are registered in a string table! */ 01088 return strcmp(ac->name, bc->name); 01089 }
unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
Definition at line 1124 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().
01125 { 01126 const struct ast_context *ac = obj; 01127 return ast_hashtab_hash_string(ac->name); 01128 }
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 |
Check if a number should be ignored with respect to dialtone cancellation.
0 | if the pattern should not be ignored | |
non-zero | if the pattern should be ignored |
Definition at line 8323 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(), and skinny_ss().
08324 { 08325 struct ast_context *con = ast_context_find(context); 08326 08327 if (con) { 08328 struct ast_ignorepat *pat; 08329 08330 for (pat = con->ignorepats; pat; pat = pat->next) { 08331 if (ast_extension_match(pat->pattern, pattern)) 08332 return 1; 08333 } 08334 } 08335 08336 return 0; 08337 }
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 5120 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by __analog_ss_thread(), __ast_pbx_run(), analog_ss_thread(), ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), readexten_exec(), and skinny_ss().
05121 { 05122 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 05123 }
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 7620 of file pbx.c.
References __ast_internal_context_destroy(), ao2_callback, ao2_container_count(), ao2_find, ao2_iterator_destroy(), AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension_nolock(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_free_ptr(), ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), store_hint::callbacks, ast_hint::callbacks, ast_state_cb::change_cb, store_hint::context, context_merge(), context_merge_lock, contexts, contexts_table, ast_state_cb::data, ast_exten::data, store_hint::data, E_MATCH, store_hint::exten, ast_exten::exten, ast_hint::exten, hints, ast_hint::laststate, store_hint::laststate, ast_context::name, ast_context::next, ast_sw::next, OBJ_UNLINK, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_exten::registrar, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
07621 { 07622 double ft; 07623 struct ast_context *tmp; 07624 struct ast_context *oldcontextslist; 07625 struct ast_hashtab *oldtable; 07626 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07627 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 07628 struct store_hint *saved_hint; 07629 struct ast_hint *hint; 07630 struct ast_exten *exten; 07631 int length; 07632 struct ast_state_cb *thiscb; 07633 struct ast_hashtab_iter *iter; 07634 struct ao2_iterator i; 07635 struct timeval begintime; 07636 struct timeval writelocktime; 07637 struct timeval endlocktime; 07638 struct timeval enddeltime; 07639 07640 /* 07641 * It is very important that this function hold the hints 07642 * container lock _and_ the conlock during its operation; not 07643 * only do we need to ensure that the list of contexts and 07644 * extensions does not change, but also that no hint callbacks 07645 * (watchers) are added or removed during the merge/delete 07646 * process 07647 * 07648 * In addition, the locks _must_ be taken in this order, because 07649 * there are already other code paths that use this order 07650 */ 07651 07652 begintime = ast_tvnow(); 07653 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */ 07654 ast_wrlock_contexts(); 07655 iter = ast_hashtab_start_traversal(contexts_table); 07656 while ((tmp = ast_hashtab_next(iter))) { 07657 context_merge(extcontexts, exttable, tmp, registrar); 07658 } 07659 ast_hashtab_end_traversal(iter); 07660 07661 ao2_lock(hints); 07662 writelocktime = ast_tvnow(); 07663 07664 /* preserve all watchers for hints */ 07665 i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK); 07666 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) { 07667 if (ao2_container_count(hint->callbacks)) { 07668 ao2_lock(hint); 07669 if (!hint->exten) { 07670 /* The extension has already been destroyed. (Should never happen here) */ 07671 ao2_unlock(hint); 07672 continue; 07673 } 07674 07675 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 07676 + sizeof(*saved_hint); 07677 if (!(saved_hint = ast_calloc(1, length))) { 07678 ao2_unlock(hint); 07679 continue; 07680 } 07681 07682 /* This removes all the callbacks from the hint into saved_hint. */ 07683 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) { 07684 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry); 07685 /* 07686 * We intentionally do not unref thiscb to account for the 07687 * non-ao2 reference in saved_hint->callbacks 07688 */ 07689 } 07690 07691 saved_hint->laststate = hint->laststate; 07692 saved_hint->context = saved_hint->data; 07693 strcpy(saved_hint->data, hint->exten->parent->name); 07694 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1; 07695 strcpy(saved_hint->exten, hint->exten->exten); 07696 ao2_unlock(hint); 07697 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); 07698 } 07699 } 07700 ao2_iterator_destroy(&i); 07701 07702 /* save the old table and list */ 07703 oldtable = contexts_table; 07704 oldcontextslist = contexts; 07705 07706 /* move in the new table and list */ 07707 contexts_table = exttable; 07708 contexts = *extcontexts; 07709 07710 /* 07711 * Restore the watchers for hints that can be found; notify 07712 * those that cannot be restored. 07713 */ 07714 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) { 07715 struct pbx_find_info q = { .stacklen = 0 }; 07716 07717 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten, 07718 PRIORITY_HINT, NULL, "", E_MATCH); 07719 /* 07720 * If this is a pattern, dynamically create a new extension for this 07721 * particular match. Note that this will only happen once for each 07722 * individual extension, because the pattern will no longer match first. 07723 */ 07724 if (exten && exten->exten[0] == '_') { 07725 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten, 07726 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr, 07727 exten->registrar); 07728 /* rwlocks are not recursive locks */ 07729 exten = ast_hint_extension_nolock(NULL, saved_hint->context, 07730 saved_hint->exten); 07731 } 07732 07733 /* Find the hint in the hints container */ 07734 hint = exten ? ao2_find(hints, exten, 0) : NULL; 07735 if (!hint) { 07736 /* 07737 * Notify watchers of this removed hint later when we aren't 07738 * encumberd by so many locks. 07739 */ 07740 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list); 07741 } else { 07742 ao2_lock(hint); 07743 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07744 ao2_link(hint->callbacks, thiscb); 07745 /* Ref that we added when putting into saved_hint->callbacks */ 07746 ao2_ref(thiscb, -1); 07747 } 07748 hint->laststate = saved_hint->laststate; 07749 ao2_unlock(hint); 07750 ao2_ref(hint, -1); 07751 ast_free(saved_hint); 07752 } 07753 } 07754 07755 ao2_unlock(hints); 07756 ast_unlock_contexts(); 07757 07758 /* 07759 * Notify watchers of all removed hints with the same lock 07760 * environment as handle_statechange(). 07761 */ 07762 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) { 07763 /* this hint has been removed, notify the watchers */ 07764 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) { 07765 thiscb->change_cb(saved_hint->context, saved_hint->exten, 07766 AST_EXTENSION_REMOVED, thiscb->data); 07767 /* Ref that we added when putting into saved_hint->callbacks */ 07768 ao2_ref(thiscb, -1); 07769 } 07770 ast_free(saved_hint); 07771 } 07772 07773 ast_mutex_unlock(&context_merge_lock); 07774 endlocktime = ast_tvnow(); 07775 07776 /* 07777 * The old list and hashtab no longer are relevant, delete them 07778 * while the rest of asterisk is now freely using the new stuff 07779 * instead. 07780 */ 07781 07782 ast_hashtab_destroy(oldtable, NULL); 07783 07784 for (tmp = oldcontextslist; tmp; ) { 07785 struct ast_context *next; /* next starting point */ 07786 07787 next = tmp->next; 07788 __ast_internal_context_destroy(tmp); 07789 tmp = next; 07790 } 07791 enddeltime = ast_tvnow(); 07792 07793 ft = ast_tvdiff_us(writelocktime, begintime); 07794 ft /= 1000000.0; 07795 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 07796 07797 ft = ast_tvdiff_us(endlocktime, writelocktime); 07798 ft /= 1000000.0; 07799 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 07800 07801 ft = ast_tvdiff_us(enddeltime, endlocktime); 07802 ft /= 1000000.0; 07803 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 07804 07805 ft = ast_tvdiff_us(enddeltime, begintime); 07806 ft /= 1000000.0; 07807 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 07808 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 10906 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().
10907 { 10908 return pbx_parseable_goto(chan, goto_string, 0); 10909 }
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 9217 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, async_stat::appdata, 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_string_field_free_memory, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, errno, ast_channel::hangupcause, LOG_WARNING, async_stat::p, app_tmp::t, async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_app(), and originate_exec().
09218 { 09219 struct ast_channel *chan; 09220 struct app_tmp *tmp; 09221 int res = -1, cdr_res = -1; 09222 struct outgoing_helper oh; 09223 09224 memset(&oh, 0, sizeof(oh)); 09225 oh.vars = vars; 09226 oh.account = account; 09227 09228 if (locked_channel) 09229 *locked_channel = NULL; 09230 if (ast_strlen_zero(app)) { 09231 res = -1; 09232 goto outgoing_app_cleanup; 09233 } 09234 if (synchronous) { 09235 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09236 if (chan) { 09237 ast_set_variables(chan, vars); 09238 if (account) 09239 ast_cdr_setaccount(chan, account); 09240 if (chan->_state == AST_STATE_UP) { 09241 res = 0; 09242 ast_verb(4, "Channel %s was answered.\n", chan->name); 09243 tmp = ast_calloc(1, sizeof(*tmp)); 09244 if (!tmp || ast_string_field_init(tmp, 252)) { 09245 if (tmp) { 09246 ast_free(tmp); 09247 } 09248 res = -1; 09249 } else { 09250 ast_string_field_set(tmp, app, app); 09251 ast_string_field_set(tmp, data, appdata); 09252 tmp->chan = chan; 09253 if (synchronous > 1) { 09254 if (locked_channel) 09255 ast_channel_unlock(chan); 09256 ast_pbx_run_app(tmp); 09257 } else { 09258 if (locked_channel) 09259 ast_channel_lock(chan); 09260 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 09261 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 09262 ast_string_field_free_memory(tmp); 09263 ast_free(tmp); 09264 if (locked_channel) 09265 ast_channel_unlock(chan); 09266 ast_hangup(chan); 09267 res = -1; 09268 } else { 09269 if (locked_channel) 09270 *locked_channel = chan; 09271 } 09272 } 09273 } 09274 } else { 09275 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09276 if (chan->cdr) { /* update the cdr */ 09277 /* here we update the status of the call, which sould be busy. 09278 * if that fails then we set the status to failed */ 09279 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09280 ast_cdr_failed(chan->cdr); 09281 } 09282 ast_hangup(chan); 09283 } 09284 } 09285 09286 if (res < 0) { /* the call failed for some reason */ 09287 if (*reason == 0) { /* if the call failed (not busy or no answer) 09288 * update the cdr with the failed message */ 09289 cdr_res = ast_pbx_outgoing_cdr_failed(); 09290 if (cdr_res != 0) { 09291 res = cdr_res; 09292 goto outgoing_app_cleanup; 09293 } 09294 } 09295 } 09296 09297 } else { 09298 struct async_stat *as; 09299 if (!(as = ast_calloc(1, sizeof(*as)))) { 09300 res = -1; 09301 goto outgoing_app_cleanup; 09302 } 09303 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09304 if (!chan) { 09305 ast_free(as); 09306 res = -1; 09307 goto outgoing_app_cleanup; 09308 } 09309 as->chan = chan; 09310 ast_copy_string(as->app, app, sizeof(as->app)); 09311 if (appdata) 09312 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 09313 as->timeout = timeout; 09314 ast_set_variables(chan, vars); 09315 if (account) 09316 ast_cdr_setaccount(chan, account); 09317 /* Start a new thread, and get something handling this channel. */ 09318 if (locked_channel) 09319 ast_channel_lock(chan); 09320 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09321 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09322 ast_free(as); 09323 if (locked_channel) 09324 ast_channel_unlock(chan); 09325 ast_hangup(chan); 09326 res = -1; 09327 goto outgoing_app_cleanup; 09328 } else { 09329 if (locked_channel) 09330 *locked_channel = chan; 09331 } 09332 res = 0; 09333 } 09334 outgoing_app_cleanup: 09335 ast_variables_destroy(vars); 09336 return res; 09337 }
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 9048 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, async_stat::chan, outgoing_helper::cid_name, outgoing_helper::cid_num, async_stat::context, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, async_stat::p, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), async_stat::timeout, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), orig_exten(), and originate_exec().
09049 { 09050 struct ast_channel *chan; 09051 struct async_stat *as; 09052 int res = -1, cdr_res = -1; 09053 struct outgoing_helper oh; 09054 09055 if (synchronous) { 09056 oh.context = context; 09057 oh.exten = exten; 09058 oh.priority = priority; 09059 oh.cid_num = cid_num; 09060 oh.cid_name = cid_name; 09061 oh.account = account; 09062 oh.vars = vars; 09063 oh.parent_channel = NULL; 09064 09065 chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh); 09066 if (channel) { 09067 *channel = chan; 09068 if (chan) 09069 ast_channel_lock(chan); 09070 } 09071 if (chan) { 09072 if (chan->_state == AST_STATE_UP) { 09073 res = 0; 09074 ast_verb(4, "Channel %s was answered.\n", chan->name); 09075 09076 if (synchronous > 1) { 09077 if (channel) 09078 ast_channel_unlock(chan); 09079 if (ast_pbx_run(chan)) { 09080 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09081 if (channel) 09082 *channel = NULL; 09083 ast_hangup(chan); 09084 chan = NULL; 09085 res = -1; 09086 } 09087 } else { 09088 if (ast_pbx_start(chan)) { 09089 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 09090 if (channel) { 09091 *channel = NULL; 09092 ast_channel_unlock(chan); 09093 } 09094 ast_hangup(chan); 09095 res = -1; 09096 } 09097 chan = NULL; 09098 } 09099 } else { 09100 ast_verb(4, "Channel %s was never answered.\n", chan->name); 09101 09102 if (chan->cdr) { /* update the cdr */ 09103 /* here we update the status of the call, which sould be busy. 09104 * if that fails then we set the status to failed */ 09105 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 09106 ast_cdr_failed(chan->cdr); 09107 } 09108 09109 if (channel) { 09110 *channel = NULL; 09111 ast_channel_unlock(chan); 09112 } 09113 ast_hangup(chan); 09114 chan = NULL; 09115 } 09116 } 09117 09118 if (res < 0) { /* the call failed for some reason */ 09119 if (*reason == 0) { /* if the call failed (not busy or no answer) 09120 * update the cdr with the failed message */ 09121 cdr_res = ast_pbx_outgoing_cdr_failed(); 09122 if (cdr_res != 0) { 09123 res = cdr_res; 09124 goto outgoing_exten_cleanup; 09125 } 09126 } 09127 09128 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 09129 /* check if "failed" exists */ 09130 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 09131 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed"); 09132 if (chan) { 09133 char failed_reason[4] = ""; 09134 if (!ast_strlen_zero(context)) 09135 ast_copy_string(chan->context, context, sizeof(chan->context)); 09136 set_ext_pri(chan, "failed", 1); 09137 ast_set_variables(chan, vars); 09138 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 09139 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 09140 if (account) 09141 ast_cdr_setaccount(chan, account); 09142 if (ast_pbx_run(chan)) { 09143 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 09144 ast_hangup(chan); 09145 } 09146 chan = NULL; 09147 } 09148 } 09149 } 09150 } else { 09151 if (!(as = ast_calloc(1, sizeof(*as)))) { 09152 res = -1; 09153 goto outgoing_exten_cleanup; 09154 } 09155 chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name); 09156 if (channel) { 09157 *channel = chan; 09158 if (chan) 09159 ast_channel_lock(chan); 09160 } 09161 if (!chan) { 09162 ast_free(as); 09163 res = -1; 09164 goto outgoing_exten_cleanup; 09165 } 09166 as->chan = chan; 09167 ast_copy_string(as->context, context, sizeof(as->context)); 09168 set_ext_pri(as->chan, exten, priority); 09169 as->timeout = timeout; 09170 ast_set_variables(chan, vars); 09171 if (account) 09172 ast_cdr_setaccount(chan, account); 09173 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 09174 ast_log(LOG_WARNING, "Failed to start async wait\n"); 09175 ast_free(as); 09176 if (channel) { 09177 *channel = NULL; 09178 ast_channel_unlock(chan); 09179 } 09180 ast_hangup(chan); 09181 res = -1; 09182 goto outgoing_exten_cleanup; 09183 } 09184 res = 0; 09185 } 09186 outgoing_exten_cleanup: 09187 ast_variables_destroy(vars); 09188 return res; 09189 }
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 |
This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality. See ast_pbx_start for an asynchronous function to run the PBX in a new thread as opposed to the current one.
Zero | on success | |
non-zero | on failure |
Definition at line 5626 of file pbx.c.
References ast_pbx_run_args().
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_pbx_outgoing_exten(), async_wait(), do_notify(), mgcp_ss(), skinny_newcall(), and unistim_ss().
05627 { 05628 return ast_pbx_run_args(c, NULL); 05629 }
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 |
This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality. See ast_pbx_start for an asynchronous function to run the PBX in a new thread as opposed to the current one.
Zero | on success | |
non-zero | on failure |
Definition at line 5606 of file pbx.c.
References __ast_pbx_run(), ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_test_flag, decrease_call_count(), increase_call_count(), and LOG_WARNING.
Referenced by ast_pbx_run(), dial_exec_full(), handle_gosub(), and try_calling().
05607 { 05608 enum ast_pbx_result res = AST_PBX_SUCCESS; 05609 05610 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05611 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05612 return AST_PBX_FAILED; 05613 } 05614 05615 if (increase_call_count(c)) { 05616 return AST_PBX_CALL_LIMIT; 05617 } 05618 05619 res = __ast_pbx_run(c, args); 05620 05621 decrease_call_count(); 05622 05623 return res; 05624 }
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 5579 of file pbx.c.
References ast_log(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, ast_test_flag, 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_parked_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), skinny_new(), and unistim_new().
05580 { 05581 pthread_t t; 05582 05583 if (!c) { 05584 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 05585 return AST_PBX_FAILED; 05586 } 05587 05588 if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 05589 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n"); 05590 return AST_PBX_FAILED; 05591 } 05592 05593 if (increase_call_count(c)) 05594 return AST_PBX_CALL_LIMIT; 05595 05596 /* Start a new thread, and get something handling this channel. */ 05597 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 05598 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 05599 decrease_call_count(); 05600 return AST_PBX_FAILED; 05601 } 05602 05603 return AST_PBX_SUCCESS; 05604 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 5636 of file pbx.c.
References totalcalls.
Referenced by ast_var_Config(), handle_chanlist(), and handle_showcalls().
05637 { 05638 return totalcalls; 05639 }
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 10640 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().
10641 { 10642 return ast_rwlock_rdlock(&con->lock); 10643 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10622 of file pbx.c.
References ast_mutex_lock, and conlock.
Referenced by _macro_exec(), ast_context_find(), ast_context_find_or_create(), ast_hint_extension(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
10623 { 10624 return ast_mutex_lock(&conlock); 10625 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
This function registers a populated ast_switch structure with the asterisk switching architecture.
0 | success | |
non-zero | failure |
Definition at line 6142 of file pbx.c.
References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, LOG_WARNING, and ast_switch::name.
Referenced by load_module().
06143 { 06144 struct ast_switch *tmp; 06145 06146 AST_RWLIST_WRLOCK(&switches); 06147 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 06148 if (!strcasecmp(tmp->name, sw->name)) { 06149 AST_RWLIST_UNLOCK(&switches); 06150 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 06151 return -1; 06152 } 06153 } 06154 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 06155 AST_RWLIST_UNLOCK(&switches); 06156 06157 return 0; 06158 }
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 5125 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().
05126 { 05127 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 05128 }
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 5080 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), and ast_str_set().
Referenced by ast_str_retrieve_variable().
05081 { 05082 struct ast_exten *e = ast_hint_extension(c, context, exten); 05083 05084 if (!e) { 05085 return 0; 05086 } 05087 05088 if (hint) { 05089 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e)); 05090 } 05091 if (name) { 05092 const char *tmp = ast_get_extension_app_data(e); 05093 if (tmp) { 05094 ast_str_set(name, namesize, "%s", tmp); 05095 } 05096 } 05097 return -1; 05098 }
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 3370 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_party_id::number, parse_variable_name(), ast_party_number::plan, ast_channel::priority, ast_party_dialed::transit_network_select, and ast_channel::varshead.
Referenced by ast_str_substitute_variables_full(), and pbx_retrieve_variable().
03371 { 03372 const char not_found = '\0'; 03373 char *tmpvar; 03374 const char *ret; 03375 const char *s; /* the result */ 03376 int offset, length; 03377 int i, need_substring; 03378 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 03379 char workspace[20]; 03380 03381 if (c) { 03382 ast_channel_lock(c); 03383 places[0] = &c->varshead; 03384 } 03385 /* 03386 * Make a copy of var because parse_variable_name() modifies the string. 03387 * Then if called directly, we might need to run substring() on the result; 03388 * remember this for later in 'need_substring', 'offset' and 'length' 03389 */ 03390 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 03391 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 03392 03393 /* 03394 * Look first into predefined variables, then into variable lists. 03395 * Variable 's' points to the result, according to the following rules: 03396 * s == ¬_found (set at the beginning) means that we did not find a 03397 * matching variable and need to look into more places. 03398 * If s != ¬_found, s is a valid result string as follows: 03399 * s = NULL if the variable does not have a value; 03400 * you typically do this when looking for an unset predefined variable. 03401 * s = workspace if the result has been assembled there; 03402 * typically done when the result is built e.g. with an snprintf(), 03403 * so we don't need to do an additional copy. 03404 * s != workspace in case we have a string, that needs to be copied 03405 * (the ast_copy_string is done once for all at the end). 03406 * Typically done when the result is already available in some string. 03407 */ 03408 s = ¬_found; /* default value */ 03409 if (c) { /* This group requires a valid channel */ 03410 /* Names with common parts are looked up a piece at a time using strncmp. */ 03411 if (!strncmp(var, "CALL", 4)) { 03412 if (!strncmp(var + 4, "ING", 3)) { 03413 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 03414 ast_str_set(str, maxlen, "%d", 03415 ast_party_id_presentation(&c->caller.id)); 03416 s = ast_str_buffer(*str); 03417 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 03418 ast_str_set(str, maxlen, "%d", c->caller.ani2); 03419 s = ast_str_buffer(*str); 03420 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 03421 ast_str_set(str, maxlen, "%d", c->caller.id.number.plan); 03422 s = ast_str_buffer(*str); 03423 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 03424 ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select); 03425 s = ast_str_buffer(*str); 03426 } 03427 } 03428 } else if (!strcmp(var, "HINT")) { 03429 s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03430 } else if (!strcmp(var, "HINTNAME")) { 03431 s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL; 03432 } else if (!strcmp(var, "EXTEN")) { 03433 s = c->exten; 03434 } else if (!strcmp(var, "CONTEXT")) { 03435 s = c->context; 03436 } else if (!strcmp(var, "PRIORITY")) { 03437 ast_str_set(str, maxlen, "%d", c->priority); 03438 s = ast_str_buffer(*str); 03439 } else if (!strcmp(var, "CHANNEL")) { 03440 s = c->name; 03441 } else if (!strcmp(var, "UNIQUEID")) { 03442 s = c->uniqueid; 03443 } else if (!strcmp(var, "HANGUPCAUSE")) { 03444 ast_str_set(str, maxlen, "%d", c->hangupcause); 03445 s = ast_str_buffer(*str); 03446 } 03447 } 03448 if (s == ¬_found) { /* look for more */ 03449 if (!strcmp(var, "EPOCH")) { 03450 ast_str_set(str, maxlen, "%u", (int) time(NULL)); 03451 s = ast_str_buffer(*str); 03452 } else if (!strcmp(var, "SYSTEMNAME")) { 03453 s = ast_config_AST_SYSTEM_NAME; 03454 } else if (!strcmp(var, "ENTITYID")) { 03455 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default); 03456 s = workspace; 03457 } 03458 } 03459 /* if not found, look into chanvars or global vars */ 03460 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 03461 struct ast_var_t *variables; 03462 if (!places[i]) 03463 continue; 03464 if (places[i] == &globals) 03465 ast_rwlock_rdlock(&globalslock); 03466 AST_LIST_TRAVERSE(places[i], variables, entries) { 03467 if (!strcasecmp(ast_var_name(variables), var)) { 03468 s = ast_var_value(variables); 03469 break; 03470 } 03471 } 03472 if (places[i] == &globals) 03473 ast_rwlock_unlock(&globalslock); 03474 } 03475 if (s == ¬_found || s == NULL) { 03476 ast_debug(5, "Result of '%s' is NULL\n", var); 03477 ret = NULL; 03478 } else { 03479 ast_debug(5, "Result of '%s' is '%s'\n", var, s); 03480 if (s != ast_str_buffer(*str)) { 03481 ast_str_set(str, maxlen, "%s", s); 03482 } 03483 ret = ast_str_buffer(*str); 03484 if (need_substring) { 03485 ret = ast_str_substring(*str, offset, length); 03486 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret); 03487 } 03488 } 03489 03490 if (c) { 03491 ast_channel_unlock(c); 03492 } 03493 return ret; 03494 }
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 4168 of file pbx.c.
References ast_str_substitute_variables_full().
Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_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().
04169 { 04170 size_t used; 04171 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used); 04172 }
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 3989 of file pbx.c.
References ast_channel_unref, 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().
03990 { 03991 /* Substitutes variables into buf, based on string templ */ 03992 char *cp4 = NULL; 03993 const char *tmp, *whereweare; 03994 int orig_size = 0; 03995 int offset, offset2, isfunction; 03996 const char *nextvar, *nextexp, *nextthing; 03997 const char *vars, *vare; 03998 char *finalvars; 03999 int pos, brackets, needsub, len; 04000 struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16); 04001 04002 ast_str_reset(*buf); 04003 whereweare = tmp = templ; 04004 while (!ast_strlen_zero(whereweare)) { 04005 /* reset our buffer */ 04006 ast_str_reset(substr3); 04007 04008 /* Assume we're copying the whole remaining string */ 04009 pos = strlen(whereweare); 04010 nextvar = NULL; 04011 nextexp = NULL; 04012 nextthing = strchr(whereweare, '$'); 04013 if (nextthing) { 04014 switch (nextthing[1]) { 04015 case '{': 04016 nextvar = nextthing; 04017 pos = nextvar - whereweare; 04018 break; 04019 case '[': 04020 nextexp = nextthing; 04021 pos = nextexp - whereweare; 04022 break; 04023 default: 04024 pos = 1; 04025 } 04026 } 04027 04028 if (pos) { 04029 /* Copy that many bytes */ 04030 ast_str_append_substr(buf, maxlen, whereweare, pos); 04031 04032 templ += pos; 04033 whereweare += pos; 04034 } 04035 04036 if (nextvar) { 04037 /* We have a variable. Find the start and end, and determine 04038 if we are going to have to recursively call ourselves on the 04039 contents */ 04040 vars = vare = nextvar + 2; 04041 brackets = 1; 04042 needsub = 0; 04043 04044 /* Find the end of it */ 04045 while (brackets && *vare) { 04046 if ((vare[0] == '$') && (vare[1] == '{')) { 04047 needsub++; 04048 } else if (vare[0] == '{') { 04049 brackets++; 04050 } else if (vare[0] == '}') { 04051 brackets--; 04052 } else if ((vare[0] == '$') && (vare[1] == '[')) 04053 needsub++; 04054 vare++; 04055 } 04056 if (brackets) 04057 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04058 len = vare - vars - 1; 04059 04060 /* Skip totally over variable string */ 04061 whereweare += (len + 3); 04062 04063 /* Store variable name (and truncate) */ 04064 ast_str_set_substr(&substr1, 0, vars, len); 04065 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len); 04066 04067 /* Substitute if necessary */ 04068 if (needsub) { 04069 size_t used; 04070 if (!substr2) { 04071 substr2 = ast_str_create(16); 04072 } 04073 04074 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04075 finalvars = ast_str_buffer(substr2); 04076 } else { 04077 finalvars = ast_str_buffer(substr1); 04078 } 04079 04080 parse_variable_name(finalvars, &offset, &offset2, &isfunction); 04081 if (isfunction) { 04082 /* Evaluate function */ 04083 if (c || !headp) { 04084 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04085 } else { 04086 struct varshead old; 04087 struct ast_channel *bogus = ast_dummy_channel_alloc(); 04088 if (bogus) { 04089 memcpy(&old, &bogus->varshead, sizeof(old)); 04090 memcpy(&bogus->varshead, headp, sizeof(bogus->varshead)); 04091 cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3); 04092 /* Don't deallocate the varshead that was passed in */ 04093 memcpy(&bogus->varshead, &old, sizeof(bogus->varshead)); 04094 ast_channel_unref(bogus); 04095 } else { 04096 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04097 } 04098 } 04099 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 04100 } else { 04101 /* Retrieve variable value */ 04102 ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars); 04103 cp4 = ast_str_buffer(substr3); 04104 } 04105 if (cp4) { 04106 ast_str_substring(substr3, offset, offset2); 04107 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04108 } 04109 } else if (nextexp) { 04110 /* We have an expression. Find the start and end, and determine 04111 if we are going to have to recursively call ourselves on the 04112 contents */ 04113 vars = vare = nextexp + 2; 04114 brackets = 1; 04115 needsub = 0; 04116 04117 /* Find the end of it */ 04118 while (brackets && *vare) { 04119 if ((vare[0] == '$') && (vare[1] == '[')) { 04120 needsub++; 04121 brackets++; 04122 vare++; 04123 } else if (vare[0] == '[') { 04124 brackets++; 04125 } else if (vare[0] == ']') { 04126 brackets--; 04127 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04128 needsub++; 04129 vare++; 04130 } 04131 vare++; 04132 } 04133 if (brackets) 04134 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04135 len = vare - vars - 1; 04136 04137 /* Skip totally over expression */ 04138 whereweare += (len + 3); 04139 04140 /* Store variable name (and truncate) */ 04141 ast_str_set_substr(&substr1, 0, vars, len); 04142 04143 /* Substitute if necessary */ 04144 if (needsub) { 04145 size_t used; 04146 if (!substr2) { 04147 substr2 = ast_str_create(16); 04148 } 04149 04150 ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used); 04151 finalvars = ast_str_buffer(substr2); 04152 } else { 04153 finalvars = ast_str_buffer(substr1); 04154 } 04155 04156 if (ast_str_expr(&substr3, 0, c, finalvars)) { 04157 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3)); 04158 } 04159 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3)); 04160 } 04161 } 04162 *used = ast_str_strlen(*buf) - orig_size; 04163 ast_free(substr1); 04164 ast_free(substr2); 04165 ast_free(substr3); 04166 }
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 4174 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().
04175 { 04176 size_t used; 04177 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used); 04178 }
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 10645 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().
10646 { 10647 return ast_rwlock_unlock(&con->lock); 10648 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 10627 of file pbx.c.
References ast_mutex_unlock, and conlock.
Referenced by _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_extension_helper(), show_debug_helper(), show_dialplan_helper(), and unreference_cached_app().
10628 { 10629 return ast_mutex_unlock(&conlock); 10630 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Unregisters a switch from asterisk.
Definition at line 6160 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
Referenced by __unload_module(), and unload_module().
06161 { 06162 AST_RWLIST_WRLOCK(&switches); 06163 AST_RWLIST_REMOVE(&switches, sw, list); 06164 AST_RWLIST_UNLOCK(&switches); 06165 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | priority | |||
) | [read] |
Definition at line 10759 of file pbx.c.
References ast_exten::next, and ast_context::root.
Referenced by complete_dialplan_remove_extension(), context_used(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) | [read] |
Definition at line 10792 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(), context_used(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
10794 { 10795 if (!ip) 10796 return con ? con->ignorepats : NULL; 10797 else 10798 return ip->next; 10799 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) | [read] |
Definition at line 10783 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(), context_used(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) | [read] |
Definition at line 10768 of file pbx.c.
References ast_context::alts, AST_LIST_FIRST, and AST_LIST_NEXT.
Referenced by context_merge_incls_swits_igps_other_registrars(), context_used(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
10770 { 10771 if (!sw) 10772 return con ? AST_LIST_FIRST(&con->alts) : NULL; 10773 else 10774 return AST_LIST_NEXT(sw, list); 10775 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
Definition at line 10754 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 | |||
) | [read] |
Definition at line 10777 of file pbx.c.
References ast_exten::peer.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), show_dialplan_helper(), and unreference_cached_app().
10779 { 10780 return priority ? priority->peer : exten; 10781 }
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 10635 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().
10636 { 10637 return ast_rwlock_wrlock(&con->lock); 10638 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 10617 of file pbx.c.
References ast_mutex_lock, and conlock.
Referenced by ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and complete_dialplan_remove_include().
10618 { 10619 return ast_mutex_lock(&conlock); 10620 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 10384 of file pbx.c.
References AST_LIST_REMOVE_HEAD, ast_rwlock_unlock, ast_rwlock_wrlock, ast_var_delete(), globals, and globalslock.
Referenced by handle_cli_dialplan_reload(), and reload().
10385 { 10386 struct ast_var_t *vardata; 10387 10388 ast_rwlock_wrlock(&globalslock); 10389 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 10390 ast_var_delete(vardata); 10391 ast_rwlock_unlock(&globalslock); 10392 }
const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
const char * | name | |||
) |
Return a pointer to the value of the corresponding channel variable.
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 10148 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, globalslock, and ast_channel::varshead.
Referenced by __ast_pbx_run(), _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(), create_dynamic_parkinglot(), crement_function_read(), dahdi_hangup(), dial_exec_full(), do_forward(), dundi_exec(), dundi_helper(), feature_check(), feature_interpret(), find_by_mark(), find_conf_realtime(), 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(), meetme_menu_admin_extended(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_exec(), 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(), sip_addheader(), sla_trunk_exec(), speech_background(), try_calling(), try_suggested_sip_codec(), update_bridge_vars(), and wait_for_answer().
10149 { 10150 struct ast_var_t *variables; 10151 const char *ret = NULL; 10152 int i; 10153 struct varshead *places[2] = { NULL, &globals }; 10154 10155 if (!name) 10156 return NULL; 10157 10158 if (chan) { 10159 ast_channel_lock(chan); 10160 places[0] = &chan->varshead; 10161 } 10162 10163 for (i = 0; i < 2; i++) { 10164 if (!places[i]) 10165 continue; 10166 if (places[i] == &globals) 10167 ast_rwlock_rdlock(&globalslock); 10168 AST_LIST_TRAVERSE(places[i], variables, entries) { 10169 if (!strcmp(name, ast_var_name(variables))) { 10170 ret = ast_var_value(variables); 10171 break; 10172 } 10173 } 10174 if (places[i] == &globals) 10175 ast_rwlock_unlock(&globalslock); 10176 if (ret) 10177 break; 10178 } 10179 10180 if (chan) 10181 ast_channel_unlock(chan); 10182 10183 return ret; 10184 }
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 10186 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, LOG_WARNING, and ast_channel::varshead.
Referenced by acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), and frame_set_var().
10187 { 10188 struct ast_var_t *newvariable; 10189 struct varshead *headp; 10190 10191 if (name[strlen(name)-1] == ')') { 10192 char *function = ast_strdupa(name); 10193 10194 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 10195 ast_func_write(chan, function, value); 10196 return; 10197 } 10198 10199 if (chan) { 10200 ast_channel_lock(chan); 10201 headp = &chan->varshead; 10202 } else { 10203 ast_rwlock_wrlock(&globalslock); 10204 headp = &globals; 10205 } 10206 10207 if (value) { 10208 if (headp == &globals) 10209 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10210 newvariable = ast_var_assign(name, value); 10211 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10212 } 10213 10214 if (chan) 10215 ast_channel_unlock(chan); 10216 else 10217 ast_rwlock_unlock(&globalslock); 10218 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
const char * | data | |||
) |
Definition at line 3545 of file pbx.c.
References raise_exception().
03546 { 03547 /* Priority will become 1, next time through the AUTOLOOP */ 03548 return raise_exception(chan, reason, 0); 03549 }
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 10117 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(), LOG_ERROR, total, var, and ast_channel::varshead.
Referenced by ast_var_channels_table(), dumpchan_exec(), handle_show_chanvar(), handle_showchan(), and vars2manager().
10118 { 10119 struct ast_var_t *variables; 10120 const char *var, *val; 10121 int total = 0; 10122 10123 if (!chan) 10124 return 0; 10125 10126 ast_str_reset(*buf); 10127 10128 ast_channel_lock(chan); 10129 10130 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 10131 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 10132 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 10133 ) { 10134 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 10135 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 10136 break; 10137 } else 10138 total++; 10139 } else 10140 break; 10141 } 10142 10143 ast_channel_unlock(chan); 10144 10145 return total; 10146 }
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 10278 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(), and value.
Referenced by ast_compile_ael2().
10279 { 10280 char *name, *value, *mydata; 10281 10282 if (ast_compat_app_set) { 10283 return pbx_builtin_setvar_multiple(chan, data); 10284 } 10285 10286 if (ast_strlen_zero(data)) { 10287 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n"); 10288 return 0; 10289 } 10290 10291 mydata = ast_strdupa(data); 10292 name = strsep(&mydata, "="); 10293 value = mydata; 10294 if (!value) { 10295 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n"); 10296 return 0; 10297 } 10298 10299 if (strchr(name, ' ')) { 10300 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata); 10301 } 10302 10303 pbx_builtin_setvar_helper(chan, name, value); 10304 10305 return 0; 10306 }
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 10220 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, and ast_channel::varshead.
Referenced by __analog_ss_thread(), __ast_pbx_run(), __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_eivr_setvariable(), ast_iax2_new(), ast_monitor_start(), ast_monitor_stop(), ast_pbx_outgoing_exten(), ast_pickup_call(), 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(), cccancel_exec(), 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(), disa_exec(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), feature_exec_app(), feature_request_and_dial(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_incoming(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_queue(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), manage_parked_call(), 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(), parked_call_exec(), 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(), privacy_exec(), process_ast_dsp(), process_sdp(), read_exec(), readexten_exec(), readfile_exec(), realtimefield_read(), receivefax_exec(), record_exec(), reload_module(), return_exec(), rollback_exec(), rotate_file(), rqm_exec(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_channel_variables(), set_queue_result(), shift_pop(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), start_monitor_exec(), system_exec_helper(), testtime_write(), transfer_exec(), transmit(), tryexec_exec(), unshift_push(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().
10221 { 10222 struct ast_var_t *newvariable; 10223 struct varshead *headp; 10224 const char *nametail = name; 10225 10226 if (name[strlen(name) - 1] == ')') { 10227 char *function = ast_strdupa(name); 10228 10229 return ast_func_write(chan, function, value); 10230 } 10231 10232 if (chan) { 10233 ast_channel_lock(chan); 10234 headp = &chan->varshead; 10235 } else { 10236 ast_rwlock_wrlock(&globalslock); 10237 headp = &globals; 10238 } 10239 10240 /* For comparison purposes, we have to strip leading underscores */ 10241 if (*nametail == '_') { 10242 nametail++; 10243 if (*nametail == '_') 10244 nametail++; 10245 } 10246 10247 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 10248 if (strcmp(ast_var_name(newvariable), nametail) == 0) { 10249 /* there is already such a variable, delete it */ 10250 AST_LIST_REMOVE_CURRENT(entries); 10251 ast_var_delete(newvariable); 10252 break; 10253 } 10254 } 10255 AST_LIST_TRAVERSE_SAFE_END; 10256 10257 if (value) { 10258 if (headp == &globals) 10259 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 10260 newvariable = ast_var_assign(name, value); 10261 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 10262 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 10263 "Channel: %s\r\n" 10264 "Variable: %s\r\n" 10265 "Value: %s\r\n" 10266 "Uniqueid: %s\r\n", 10267 chan ? chan->name : "none", name, value, 10268 chan ? chan->uniqueid : "none"); 10269 } 10270 10271 if (chan) 10272 ast_channel_unlock(chan); 10273 else 10274 ast_rwlock_unlock(&globalslock); 10275 return 0; 10276 }
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 10308 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, pbx_builtin_setvar_helper(), ast_channel::priority, and value.
Referenced by pbx_builtin_setvar(), queue_function_var(), set_queue_variables(), and try_calling().
10309 { 10310 char *data; 10311 int x; 10312 AST_DECLARE_APP_ARGS(args, 10313 AST_APP_ARG(pair)[24]; 10314 ); 10315 AST_DECLARE_APP_ARGS(pair, 10316 AST_APP_ARG(name); 10317 AST_APP_ARG(value); 10318 ); 10319 10320 if (ast_strlen_zero(vdata)) { 10321 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n"); 10322 return 0; 10323 } 10324 10325 data = ast_strdupa(vdata); 10326 AST_STANDARD_APP_ARGS(args, data); 10327 10328 for (x = 0; x < args.argc; x++) { 10329 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '='); 10330 if (pair.argc == 2) { 10331 pbx_builtin_setvar_helper(chan, pair.name, pair.value); 10332 if (strchr(pair.name, ' ')) 10333 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); 10334 } else if (!chan) { 10335 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name); 10336 } else { 10337 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority); 10338 } 10339 } 10340 10341 return 0; 10342 }
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 10394 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().
10395 { 10396 int res; 10397 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */ 10398 return 0; 10399 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */ 10400 return res; 10401 } else { /* Strings are true */ 10402 return 1; 10403 } 10404 }
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 |
This application executes an application on a given channel. It saves the stack and executes the given application passing in the given data.
0 | success | |
-1 | failure |
c | Channel | |
app | Application | |
data | Data for execution |
Definition at line 1418 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), 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, ast_app::execute, LOG_WARNING, ast_app::module, ast_app::name, and S_OR.
Referenced by aelsub_exec(), 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(), realtime_exec(), try_calling(), and tryexec_exec().
01421 { 01422 int res; 01423 struct ast_module_user *u = NULL; 01424 const char *saved_c_appl; 01425 const char *saved_c_data; 01426 01427 if (c->cdr && !ast_check_hangup(c)) 01428 ast_cdr_setapp(c->cdr, app->name, data); 01429 01430 /* save channel values */ 01431 saved_c_appl= c->appl; 01432 saved_c_data= c->data; 01433 01434 c->appl = app->name; 01435 c->data = data; 01436 ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL); 01437 01438 if (app->module) 01439 u = __ast_module_user_add(app->module, c); 01440 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 01441 strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) { 01442 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 01443 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 01444 app->name, (char *) data); 01445 } 01446 res = app->execute(c, S_OR(data, "")); 01447 if (app->module && u) 01448 __ast_module_user_remove(app->module, u); 01449 ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL); 01450 /* restore channel values */ 01451 c->appl = saved_c_appl; 01452 c->data = saved_c_data; 01453 return res; 01454 }
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 | |||
) | [read] |
Definition at line 2938 of file pbx.c.
References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_buffer(), ast_str_size(), ast_str_thread_get(), ast_strdupa, ast_strlen_zero(), ast_walk_context_extensions(), ast_switch::canmatch, scoreboard::canmatch_exten, create_match_char_tree(), ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, scoreboard::exten, extenpatternmatchnew, extension_match_core(), find_context(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_context::name, ast_sw::name, 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, 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(), check_goto(), check_pval_item(), get_parking_exten(), pbx_extension_helper(), pbx_find_extension(), register_peer_exten(), and remove_exten_if_exist().
02942 { 02943 int x, res; 02944 struct ast_context *tmp = NULL; 02945 struct ast_exten *e = NULL, *eroot = NULL; 02946 struct ast_include *i = NULL; 02947 struct ast_sw *sw = NULL; 02948 struct ast_exten pattern = {NULL, }; 02949 struct scoreboard score = {0, }; 02950 struct ast_str *tmpdata = NULL; 02951 02952 pattern.label = label; 02953 pattern.priority = priority; 02954 #ifdef NEED_DEBUG_HERE 02955 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action); 02956 #endif 02957 02958 /* Initialize status if appropriate */ 02959 if (q->stacklen == 0) { 02960 q->status = STATUS_NO_CONTEXT; 02961 q->swo = NULL; 02962 q->data = NULL; 02963 q->foundcontext = NULL; 02964 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02965 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02966 return NULL; 02967 } 02968 02969 /* Check first to see if we've already been checked */ 02970 for (x = 0; x < q->stacklen; x++) { 02971 if (!strcasecmp(q->incstack[x], context)) 02972 return NULL; 02973 } 02974 02975 if (bypass) { /* bypass means we only look there */ 02976 tmp = bypass; 02977 } else { /* look in contexts */ 02978 tmp = find_context(context); 02979 if (!tmp) { 02980 return NULL; 02981 } 02982 } 02983 02984 if (q->status < STATUS_NO_EXTENSION) 02985 q->status = STATUS_NO_EXTENSION; 02986 02987 /* Do a search for matching extension */ 02988 02989 eroot = NULL; 02990 score.total_specificity = 0; 02991 score.exten = 0; 02992 score.total_length = 0; 02993 if (!tmp->pattern_tree && tmp->root_table) { 02994 create_match_char_tree(tmp); 02995 #ifdef NEED_DEBUG 02996 ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context); 02997 log_match_char_tree(tmp->pattern_tree," "); 02998 #endif 02999 } 03000 #ifdef NEED_DEBUG 03001 ast_log(LOG_NOTICE, "The Trie we are searching in:\n"); 03002 log_match_char_tree(tmp->pattern_tree, ":: "); 03003 #endif 03004 03005 do { 03006 if (!ast_strlen_zero(overrideswitch)) { 03007 char *osw = ast_strdupa(overrideswitch), *name; 03008 struct ast_switch *asw; 03009 ast_switch_f *aswf = NULL; 03010 char *datap; 03011 int eval = 0; 03012 03013 name = strsep(&osw, "/"); 03014 asw = pbx_findswitch(name); 03015 03016 if (!asw) { 03017 ast_log(LOG_WARNING, "No such switch '%s'\n", name); 03018 break; 03019 } 03020 03021 if (osw && strchr(osw, '$')) { 03022 eval = 1; 03023 } 03024 03025 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03026 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n"); 03027 break; 03028 } else if (eval) { 03029 /* Substitute variables now */ 03030 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03031 datap = ast_str_buffer(tmpdata); 03032 } else { 03033 datap = osw; 03034 } 03035 03036 /* equivalent of extension_match_core() at the switch level */ 03037 if (action == E_CANMATCH) 03038 aswf = asw->canmatch; 03039 else if (action == E_MATCHMORE) 03040 aswf = asw->matchmore; 03041 else /* action == E_MATCH */ 03042 aswf = asw->exists; 03043 if (!aswf) { 03044 res = 0; 03045 } else { 03046 if (chan) { 03047 ast_autoservice_start(chan); 03048 } 03049 res = aswf(chan, context, exten, priority, callerid, datap); 03050 if (chan) { 03051 ast_autoservice_stop(chan); 03052 } 03053 } 03054 if (res) { /* Got a match */ 03055 q->swo = asw; 03056 q->data = datap; 03057 q->foundcontext = context; 03058 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03059 return NULL; 03060 } 03061 } 03062 } while (0); 03063 03064 if (extenpatternmatchnew) { 03065 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 03066 eroot = score.exten; 03067 03068 if (score.last_char == '!' && action == E_MATCHMORE) { 03069 /* We match an extension ending in '!'. 03070 * The decision in this case is final and is NULL (no match). 03071 */ 03072 #ifdef NEED_DEBUG_HERE 03073 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 03074 #endif 03075 return NULL; 03076 } 03077 03078 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 03079 q->status = STATUS_SUCCESS; 03080 #ifdef NEED_DEBUG_HERE 03081 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 03082 #endif 03083 return score.canmatch_exten; 03084 } 03085 03086 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 03087 if (score.node) { 03088 struct ast_exten *z = trie_find_next_match(score.node); 03089 if (z) { 03090 #ifdef NEED_DEBUG_HERE 03091 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 03092 #endif 03093 } else { 03094 if (score.canmatch_exten) { 03095 #ifdef NEED_DEBUG_HERE 03096 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 03097 #endif 03098 return score.canmatch_exten; 03099 } else { 03100 #ifdef NEED_DEBUG_HERE 03101 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 03102 #endif 03103 } 03104 } 03105 return z; 03106 } 03107 #ifdef NEED_DEBUG_HERE 03108 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 03109 #endif 03110 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 03111 } 03112 03113 if (eroot) { 03114 /* found entry, now look for the right priority */ 03115 if (q->status < STATUS_NO_PRIORITY) 03116 q->status = STATUS_NO_PRIORITY; 03117 e = NULL; 03118 if (action == E_FINDLABEL && label ) { 03119 if (q->status < STATUS_NO_LABEL) 03120 q->status = STATUS_NO_LABEL; 03121 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03122 } else { 03123 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03124 } 03125 if (e) { /* found a valid match */ 03126 q->status = STATUS_SUCCESS; 03127 q->foundcontext = context; 03128 #ifdef NEED_DEBUG_HERE 03129 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 03130 #endif 03131 return e; 03132 } 03133 } 03134 } else { /* the old/current default exten pattern match algorithm */ 03135 03136 /* scan the list trying to match extension and CID */ 03137 eroot = NULL; 03138 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 03139 int match = extension_match_core(eroot->exten, exten, action); 03140 /* 0 on fail, 1 on match, 2 on earlymatch */ 03141 03142 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 03143 continue; /* keep trying */ 03144 if (match == 2 && action == E_MATCHMORE) { 03145 /* We match an extension ending in '!'. 03146 * The decision in this case is final and is NULL (no match). 03147 */ 03148 return NULL; 03149 } 03150 /* found entry, now look for the right priority */ 03151 if (q->status < STATUS_NO_PRIORITY) 03152 q->status = STATUS_NO_PRIORITY; 03153 e = NULL; 03154 if (action == E_FINDLABEL && label ) { 03155 if (q->status < STATUS_NO_LABEL) 03156 q->status = STATUS_NO_LABEL; 03157 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 03158 } else { 03159 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 03160 } 03161 if (e) { /* found a valid match */ 03162 q->status = STATUS_SUCCESS; 03163 q->foundcontext = context; 03164 return e; 03165 } 03166 } 03167 } 03168 03169 /* Check alternative switches */ 03170 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 03171 struct ast_switch *asw = pbx_findswitch(sw->name); 03172 ast_switch_f *aswf = NULL; 03173 char *datap; 03174 03175 if (!asw) { 03176 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 03177 continue; 03178 } 03179 03180 /* Substitute variables now */ 03181 if (sw->eval) { 03182 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 03183 ast_log(LOG_WARNING, "Can't evaluate switch?!\n"); 03184 continue; 03185 } 03186 pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); 03187 } 03188 03189 /* equivalent of extension_match_core() at the switch level */ 03190 if (action == E_CANMATCH) 03191 aswf = asw->canmatch; 03192 else if (action == E_MATCHMORE) 03193 aswf = asw->matchmore; 03194 else /* action == E_MATCH */ 03195 aswf = asw->exists; 03196 datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; 03197 if (!aswf) 03198 res = 0; 03199 else { 03200 if (chan) 03201 ast_autoservice_start(chan); 03202 res = aswf(chan, context, exten, priority, callerid, datap); 03203 if (chan) 03204 ast_autoservice_stop(chan); 03205 } 03206 if (res) { /* Got a match */ 03207 q->swo = asw; 03208 q->data = datap; 03209 q->foundcontext = context; 03210 /* XXX keep status = STATUS_NO_CONTEXT ? */ 03211 return NULL; 03212 } 03213 } 03214 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 03215 /* Now try any includes we have in this context */ 03216 for (i = tmp->includes; i; i = i->next) { 03217 if (include_valid(i)) { 03218 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 03219 #ifdef NEED_DEBUG_HERE 03220 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 03221 #endif 03222 return e; 03223 } 03224 if (q->swo) 03225 return NULL; 03226 } 03227 } 03228 return NULL; 03229 }
struct ast_app* pbx_findapp | ( | const char * | app | ) | [read] |
Look up an application.
app | name of the app |
This function searches for the ast_app structure within the apps that are registered for the one with the name you passed in.
Definition at line 1462 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_app::name.
Referenced by aelsub_exec(), 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(), realtime_exec(), try_calling(), and tryexec_exec().
01463 { 01464 struct ast_app *tmp; 01465 01466 AST_RWLIST_RDLOCK(&apps); 01467 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 01468 if (!strcasecmp(tmp->name, app)) 01469 break; 01470 } 01471 AST_RWLIST_UNLOCK(&apps); 01472 01473 return tmp; 01474 }
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.
Retrieve the value of a builtin variable or variable from the channel variable stack.
Definition at line 3359 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().
03360 { 03361 struct ast_str *str = ast_str_create(16); 03362 const char *cret; 03363 03364 cret = ast_str_retrieve_variable(&str, 0, c, headp, var); 03365 ast_copy_string(workspace, ast_str_buffer(str), workspacelen); 03366 *ret = cret ? workspace : NULL; 03367 ast_free(str); 03368 }
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 5641 of file pbx.c.
References autofallthrough.
Referenced by pbx_load_module().
05642 { 05643 int oldval = autofallthrough; 05644 autofallthrough = newval; 05645 return oldval; 05646 }
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 5648 of file pbx.c.
References extenpatternmatchnew.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
05649 { 05650 int oldval = extenpatternmatchnew; 05651 extenpatternmatchnew = newval; 05652 return oldval; 05653 }
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 5655 of file pbx.c.
References ast_free, ast_strdup, ast_strlen_zero(), and overrideswitch.
Referenced by pbx_load_module().
05656 { 05657 if (overrideswitch) { 05658 ast_free(overrideswitch); 05659 } 05660 if (!ast_strlen_zero(newval)) { 05661 overrideswitch = ast_strdup(newval); 05662 } else { 05663 overrideswitch = NULL; 05664 } 05665 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4376 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(), realtime_exec(), rotate_file(), substituted(), try_calling(), and write_cdr().
04377 { 04378 size_t used; 04379 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); 04380 }
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 4180 of file pbx.c.
References ast_alloca, ast_channel_unref, 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().
04181 { 04182 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ 04183 char *cp4 = NULL; 04184 const char *tmp, *whereweare, *orig_cp2 = cp2; 04185 int length, offset, offset2, isfunction; 04186 char *workspace = NULL; 04187 char *ltmp = NULL, *var = NULL; 04188 char *nextvar, *nextexp, *nextthing; 04189 char *vars, *vare; 04190 int pos, brackets, needsub, len; 04191 04192 *cp2 = 0; /* just in case nothing ends up there */ 04193 whereweare=tmp=cp1; 04194 while (!ast_strlen_zero(whereweare) && count) { 04195 /* Assume we're copying the whole remaining string */ 04196 pos = strlen(whereweare); 04197 nextvar = NULL; 04198 nextexp = NULL; 04199 nextthing = strchr(whereweare, '$'); 04200 if (nextthing) { 04201 switch (nextthing[1]) { 04202 case '{': 04203 nextvar = nextthing; 04204 pos = nextvar - whereweare; 04205 break; 04206 case '[': 04207 nextexp = nextthing; 04208 pos = nextexp - whereweare; 04209 break; 04210 default: 04211 pos = 1; 04212 } 04213 } 04214 04215 if (pos) { 04216 /* Can't copy more than 'count' bytes */ 04217 if (pos > count) 04218 pos = count; 04219 04220 /* Copy that many bytes */ 04221 memcpy(cp2, whereweare, pos); 04222 04223 count -= pos; 04224 cp2 += pos; 04225 whereweare += pos; 04226 *cp2 = 0; 04227 } 04228 04229 if (nextvar) { 04230 /* We have a variable. Find the start and end, and determine 04231 if we are going to have to recursively call ourselves on the 04232 contents */ 04233 vars = vare = nextvar + 2; 04234 brackets = 1; 04235 needsub = 0; 04236 04237 /* Find the end of it */ 04238 while (brackets && *vare) { 04239 if ((vare[0] == '$') && (vare[1] == '{')) { 04240 needsub++; 04241 } else if (vare[0] == '{') { 04242 brackets++; 04243 } else if (vare[0] == '}') { 04244 brackets--; 04245 } else if ((vare[0] == '$') && (vare[1] == '[')) 04246 needsub++; 04247 vare++; 04248 } 04249 if (brackets) 04250 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n"); 04251 len = vare - vars - 1; 04252 04253 /* Skip totally over variable string */ 04254 whereweare += (len + 3); 04255 04256 if (!var) 04257 var = ast_alloca(VAR_BUF_SIZE); 04258 04259 /* Store variable name (and truncate) */ 04260 ast_copy_string(var, vars, len + 1); 04261 04262 /* Substitute if necessary */ 04263 if (needsub) { 04264 size_t used; 04265 if (!ltmp) 04266 ltmp = ast_alloca(VAR_BUF_SIZE); 04267 04268 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04269 vars = ltmp; 04270 } else { 04271 vars = var; 04272 } 04273 04274 if (!workspace) 04275 workspace = ast_alloca(VAR_BUF_SIZE); 04276 04277 workspace[0] = '\0'; 04278 04279 parse_variable_name(vars, &offset, &offset2, &isfunction); 04280 if (isfunction) { 04281 /* Evaluate function */ 04282 if (c || !headp) 04283 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04284 else { 04285 struct varshead old; 04286 struct ast_channel *c = ast_dummy_channel_alloc(); 04287 if (c) { 04288 memcpy(&old, &c->varshead, sizeof(old)); 04289 memcpy(&c->varshead, headp, sizeof(c->varshead)); 04290 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace; 04291 /* Don't deallocate the varshead that was passed in */ 04292 memcpy(&c->varshead, &old, sizeof(c->varshead)); 04293 c = ast_channel_unref(c); 04294 } else { 04295 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 04296 } 04297 } 04298 ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); 04299 } else { 04300 /* Retrieve variable value */ 04301 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); 04302 } 04303 if (cp4) { 04304 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE); 04305 04306 length = strlen(cp4); 04307 if (length > count) 04308 length = count; 04309 memcpy(cp2, cp4, length); 04310 count -= length; 04311 cp2 += length; 04312 *cp2 = 0; 04313 } 04314 } else if (nextexp) { 04315 /* We have an expression. Find the start and end, and determine 04316 if we are going to have to recursively call ourselves on the 04317 contents */ 04318 vars = vare = nextexp + 2; 04319 brackets = 1; 04320 needsub = 0; 04321 04322 /* Find the end of it */ 04323 while (brackets && *vare) { 04324 if ((vare[0] == '$') && (vare[1] == '[')) { 04325 needsub++; 04326 brackets++; 04327 vare++; 04328 } else if (vare[0] == '[') { 04329 brackets++; 04330 } else if (vare[0] == ']') { 04331 brackets--; 04332 } else if ((vare[0] == '$') && (vare[1] == '{')) { 04333 needsub++; 04334 vare++; 04335 } 04336 vare++; 04337 } 04338 if (brackets) 04339 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n"); 04340 len = vare - vars - 1; 04341 04342 /* Skip totally over expression */ 04343 whereweare += (len + 3); 04344 04345 if (!var) 04346 var = ast_alloca(VAR_BUF_SIZE); 04347 04348 /* Store variable name (and truncate) */ 04349 ast_copy_string(var, vars, len + 1); 04350 04351 /* Substitute if necessary */ 04352 if (needsub) { 04353 size_t used; 04354 if (!ltmp) 04355 ltmp = ast_alloca(VAR_BUF_SIZE); 04356 04357 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); 04358 vars = ltmp; 04359 } else { 04360 vars = var; 04361 } 04362 04363 length = ast_expr(vars, cp2, count, c); 04364 04365 if (length) { 04366 ast_debug(1, "Expression result is '%s'\n", cp2); 04367 count -= length; 04368 cp2 += length; 04369 *cp2 = 0; 04370 } 04371 } 04372 } 04373 *used = cp2 - orig_cp2; 04374 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 4382 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by do_say(), dundi_lookup_local(), and loopback_subst().
04383 { 04384 size_t used; 04385 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); 04386 }