#include "asterisk/sched.h"
#include "asterisk/chanvars.h"
#include "asterisk/hashtab.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 |
Functions for returning values from structures | |
const char * | ast_get_context_name (struct ast_context *con) |
ast_context * | ast_get_extension_context (struct ast_exten *exten) |
const char * | ast_get_extension_name (struct ast_exten *exten) |
const char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
const char * | ast_get_include_name (struct ast_include *include) |
const char * | ast_get_switch_data (struct ast_sw *sw) |
int | ast_get_switch_eval (struct ast_sw *sw) |
const char * | ast_get_switch_name (struct ast_sw *sw) |
Registrar info functions ... | |
const char * | ast_get_context_registrar (struct ast_context *c) |
const char * | ast_get_extension_registrar (struct ast_exten *e) |
const char * | ast_get_ignorepat_registrar (struct ast_ignorepat *ip) |
const char * | ast_get_include_registrar (struct ast_include *i) |
const char * | ast_get_switch_registrar (struct ast_sw *sw) |
Other Extension stuff | |
const char * | ast_get_extension_app (struct ast_exten *e) |
void * | ast_get_extension_app_data (struct ast_exten *e) |
const char * | ast_get_extension_cidmatch (struct ast_exten *e) |
const char * | ast_get_extension_label (struct ast_exten *e) |
int | ast_get_extension_matchcid (struct ast_exten *e) |
int | ast_get_extension_priority (struct ast_exten *exten) |
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_ERROR 1 |
#define | AST_PBX_HANGUP -1 |
Special return values from applications to the PBX {. | |
#define | AST_PBX_KEEP 0 |
#define | AST_PBX_MAX_STACK 128 |
#define | AST_PBX_OK 0 |
#define | AST_PBX_REPLACE 1 |
#define | PRIORITY_HINT -1 |
#define | STATUS_NO_CONTEXT 1 |
#define | STATUS_NO_EXTENSION 2 |
#define | STATUS_NO_LABEL 4 |
#define | STATUS_NO_PRIORITY 3 |
#define | STATUS_SUCCESS 5 |
Typedefs | |
typedef int(*) | ast_state_cb_type (char *context, char *id, enum ast_extension_states state, void *data) |
Typedef for devicestate and hint callbacks. | |
typedef int( | ast_switch_f )(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
All switch functions have the same interface, so define a type for them. | |
Enumerations | |
enum | ast_extension_states { AST_EXTENSION_REMOVED = -2, AST_EXTENSION_DEACTIVATED = -1, AST_EXTENSION_NOT_INUSE = 0, AST_EXTENSION_INUSE = 1 << 0, AST_EXTENSION_BUSY = 1 << 1, AST_EXTENSION_UNAVAILABLE = 1 << 2, AST_EXTENSION_RINGING = 1 << 3, AST_EXTENSION_ONHOLD = 1 << 4 } |
Extension states. More... | |
enum | ast_pbx_result { AST_PBX_SUCCESS = 0, AST_PBX_FAILED = -1, AST_PBX_CALL_LIMIT = -2 } |
The result codes when starting the PBX on a channelwith. More... | |
enum | ext_match_t { E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22 } |
Functions | |
int | __ast_custom_function_register (struct ast_custom_function *acf, struct ast_module *mod) |
Register a custom function. | |
int | ast_active_calls (void) |
Retrieve the number of active calls. | |
int | ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
Add and extension to an extension context. | |
int | ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
Add an extension to an extension context, this time with an ast_context *. | |
int | ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_async_goto_by_name (const char *chan, const char *context, const char *exten, int priority) |
int | ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string) |
int | ast_build_timing (struct ast_timing *i, const char *info) |
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) |
int | ast_context_add_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
Add an ignorepat. | |
int | ast_context_add_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
int | ast_context_add_include (const char *context, const char *include, const char *registrar) |
Add a context include. | |
int | ast_context_add_include2 (struct ast_context *con, const char *include, const char *registrar) |
Add a context include. | |
int | ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar) |
Add a switch. | |
int | ast_context_add_switch2 (struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar) |
Adds a switch (first param is a ast_context). | |
void | ast_context_destroy (struct ast_context *con, const char *registrar) |
Destroy a context (matches the specified context (or ANY context if NULL). | |
ast_context * | ast_context_find (const char *name) |
Find a context. | |
ast_context * | ast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar) |
Register a new context or find an existing one. | |
int | ast_context_lockmacro (const char *macrocontext) |
locks the macrolock in the given given context | |
int | ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar) |
Simply remove extension from context. | |
int | ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked) |
This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return. | |
int | ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar) |
int | ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar, int already_locked) |
int | ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
int | ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
int | ast_context_remove_include (const char *context, const char *include, const char *registrar) |
Remove a context include. | |
int | ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar) |
Removes an include by an ast_context structure. | |
int | ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar) |
Remove a switch. | |
int | ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar) |
This function locks given context, removes switch, unlock context and return. | |
int | ast_context_unlockmacro (const char *macrocontext) |
Unlocks the macrolock in the given context. | |
int | ast_context_verify_includes (struct ast_context *con) |
Verifies includes in an ast_contect structure. | |
ast_custom_function * | ast_custom_function_find (const char *name) |
int | ast_custom_function_unregister (struct ast_custom_function *acf) |
Unregister a custom function. | |
int | ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Determine whether an extension exists. | |
int | ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
int | ast_extension_close (const char *pattern, const char *data, int needmore) |
int | ast_extension_cmp (const char *a, const char *b) |
Determine if one extension should match before another. | |
int | ast_extension_match (const char *pattern, const char *extension) |
Determine if a given extension matches a given pattern (in NXX format). | |
int | ast_extension_patmatch (const char *pattern, const char *data) |
int | ast_extension_state (struct ast_channel *c, const char *context, const char *exten) |
Uses hint and devicestate callback to get the state of an extension. | |
const char * | ast_extension_state2str (int extension_state) |
Return string representation of the state of an extension. | |
int | ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data) |
Registers a state change callback. | |
int | ast_extension_state_del (int id, ast_state_cb_type callback) |
Deletes a registered state change callback by ID. | |
int | ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid) |
Find the priority of an extension that has the specified label. | |
int | ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid) |
Find the priority of an extension that has the specified label. | |
int | ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len) |
executes a read operation on a function | |
int | ast_func_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 maxlen, char *name, int maxnamelen, 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_hashtab_compare_contexts (const void *ah_a, const void *ah_b) |
unsigned int | ast_hashtab_hash_contexts (const void *obj) |
int | ast_ignore_pattern (const char *context, const char *pattern) |
Checks to see if a number should be ignored. | |
int | ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
Looks to see if adding anything to this extension might match something. (exists ^ canmatch). | |
void | ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar) |
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added. | |
int | ast_parseable_goto (struct ast_channel *chan, const char *goto_string) |
int | ast_pbx_outgoing_app (const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) |
int | ast_pbx_outgoing_exten (const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) |
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_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. | |
ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority) |
ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
ast_context * | ast_walk_contexts (struct ast_context *con) |
ast_exten * | ast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority) |
int | ast_wrlock_context (struct ast_context *con) |
Write locks a given context. | |
int | ast_wrlock_contexts (void) |
Write locks the context list. | |
int | ast_wrlock_contexts_version (void) |
void | pbx_builtin_clear_globals (void) |
const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
void | pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value) |
int | pbx_builtin_raise_exception (struct ast_channel *chan, void *data) |
int | pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf) |
int | pbx_builtin_setvar (struct ast_channel *chan, void *data) |
void | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
int | pbx_builtin_setvar_multiple (struct ast_channel *chan, void *data) |
int | pbx_checkcondition (const char *condition) |
Evaluate a condition. | |
int | pbx_exec (struct ast_channel *c, struct ast_app *app, void *data) |
Execute an application. | |
ast_exten * | pbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action) |
ast_app * | pbx_findapp (const char *app) |
Look up an application. | |
void | pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp) |
Support for Asterisk built-in variables in the dialplan. | |
int | pbx_set_autofallthrough (int newval) |
int | pbx_set_extenpatternmatchnew (int newval) |
void | pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count) |
void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
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 960 of file pbx.h.
Referenced by load_module(), and reload().
#define AST_MAX_APP 32 |
Max length of an application
Definition at line 34 of file pbx.h.
Referenced by destroy_station(), handle_show_application(), and handle_show_function().
#define AST_PBX_HANGUP -1 |
#define PRIORITY_HINT -1 |
} Special Priority for a hint
Definition at line 45 of file pbx.h.
Referenced by ast_add_extension2_lockopt(), ast_hint_extension(), ast_merge_contexts_and_delete(), destroy_exten(), destroy_station(), handle_cli_dialplan_add_extension(), handle_cli_dialplan_remove_extension(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), park_add_hints(), pbx_load_config(), and print_ext().
typedef int(*) ast_state_cb_type(char *context, char *id, enum ast_extension_states state, void *data) |
typedef int( ast_switch_f)(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
enum ast_extension_states |
Extension states.
Definition at line 51 of file pbx.h.
00051 { 00052 AST_EXTENSION_REMOVED = -2, /*!< Extension removed */ 00053 AST_EXTENSION_DEACTIVATED = -1, /*!< Extension hint removed */ 00054 AST_EXTENSION_NOT_INUSE = 0, /*!< No device INUSE or BUSY */ 00055 AST_EXTENSION_INUSE = 1 << 0, /*!< One or more devices INUSE */ 00056 AST_EXTENSION_BUSY = 1 << 1, /*!< All devices BUSY */ 00057 AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */ 00058 AST_EXTENSION_RINGING = 1 << 3, /*!< All devices RINGING */ 00059 AST_EXTENSION_ONHOLD = 1 << 4, /*!< All devices ONHOLD */ 00060 };
enum ast_pbx_result |
The result codes when starting the PBX on a channelwith.
Definition at line 227 of file pbx.h.
00227 { 00228 AST_PBX_SUCCESS = 0, 00229 AST_PBX_FAILED = -1, 00230 AST_PBX_CALL_LIMIT = -2, 00231 };
enum ext_match_t |
When looking up extensions, we can have different requests identified by the 'action' argument, as follows. Note that the coding is such that the low 4 bits are the third argument to extension_match_core.
Definition at line 1011 of file pbx.h.
01011 { 01012 E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */ 01013 E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */ 01014 E_MATCH = 0x02, /* extension is an exact match */ 01015 E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */ 01016 E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */ 01017 E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */ 01018 };
int __ast_custom_function_register | ( | struct ast_custom_function * | acf, | |
struct ast_module * | mod | |||
) |
Register a custom function.
Definition at line 2714 of file pbx.c.
References ast_custom_function::acflist, ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, COLOR_BRCYAN, LOG_ERROR, ast_custom_function::mod, ast_custom_function::name, and term_color().
Referenced by load_pbx().
02715 { 02716 struct ast_custom_function *cur; 02717 char tmps[80]; 02718 02719 if (!acf) 02720 return -1; 02721 02722 acf->mod = mod; 02723 02724 AST_RWLIST_WRLOCK(&acf_root); 02725 02726 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 02727 if (!strcmp(acf->name, cur->name)) { 02728 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 02729 AST_RWLIST_UNLOCK(&acf_root); 02730 return -1; 02731 } 02732 } 02733 02734 /* Store in alphabetical order */ 02735 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 02736 if (strcasecmp(acf->name, cur->name) < 0) { 02737 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist); 02738 break; 02739 } 02740 } 02741 AST_RWLIST_TRAVERSE_SAFE_END; 02742 if (!cur) 02743 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 02744 02745 AST_RWLIST_UNLOCK(&acf_root); 02746 02747 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps))); 02748 02749 return 0; 02750 }
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 4026 of file pbx.c.
Referenced by handle_chanlist(), handle_showcalls(), and sysinfo_helper().
04027 { 04028 return countcalls; 04029 }
int ast_add_extension | ( | const char * | context, | |
int | replace, | |||
const char * | extension, | |||
int | priority, | |||
const char * | label, | |||
const char * | callerid, | |||
const char * | application, | |||
void * | data, | |||
void(*)(void *) | datad, | |||
const char * | registrar | |||
) |
Add and extension to an extension context.
context | context to add the extension to | |
replace | ||
extension | extension to add | |
priority | priority level of extension addition | |
label | extension label | |
callerid | pattern to match CallerID, or NULL to match any CallerID | |
application | application to run on the extension with that priority level | |
data | data to pass to the application | |
datad | ||
registrar | who registered the extension |
0 | success | |
-1 | failure |
Definition at line 6431 of file pbx.c.
References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_extension(), park_add_hints(), register_exten(), register_peer_exten(), and RegisterExtension().
06434 { 06435 int ret = -1; 06436 struct ast_context *c = find_context_locked(context); 06437 06438 if (c) { 06439 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 06440 application, data, datad, registrar); 06441 ast_unlock_contexts(); 06442 } 06443 06444 return ret; 06445 }
int ast_add_extension2 | ( | struct ast_context * | con, | |
int | replace, | |||
const char * | extension, | |||
int | priority, | |||
const char * | label, | |||
const char * | callerid, | |||
const char * | application, | |||
void * | data, | |||
void(*)(void *) | datad, | |||
const char * | registrar | |||
) |
Add an extension to an extension context, this time with an ast_context *.
We sort extensions in order of matching preference, so that we can stop the search as soon as we find a suitable match. This ordering also takes care of wildcards such as '.' (meaning "one or more of any character") and '!' (which is 'earlymatch', meaning "zero or more of any character" but also impacts the return value from CANMATCH and EARLYMATCH.
The extension match rules defined in the devmeeting 2006.05.05 are quite simple: WE SELECT THE LONGEST MATCH. In detail, "longest" means the number of matched characters in the extension. In case of ties (e.g. _XXX and 333) in the length of a pattern, we give priority to entries with the smallest cardinality (e.g, [5-9] comes before [2-8] before the former has only 5 elements, while the latter has 7, etc. In case of same cardinality, the first element in the range counts. If we still have a tie, any final '!' will make this as a possibly less specific pattern.
EBUSY - can't lock EEXIST - extension with the same priority exist and no replace is set
Definition at line 6749 of file pbx.c.
References ast_add_extension2_lockopt().
Referenced by ast_add_extension(), context_merge(), do_parking_thread(), load_module(), park_call_full(), pbx_load_config(), and pbx_load_users().
06753 { 06754 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid, application, data, datad, registrar, 1, 1); 06755 }
int ast_async_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6470 of file pbx.c.
References ast_channel::_state, ast_channel::accountcode, ast_channel::amaflags, ast_cdr_discard(), ast_cdr_dup(), ast_channel_alloc, ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_channel::cdr, chan, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::name, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.
Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), dahdi_handle_dtmfup(), handle_request_bye(), handle_request_refer(), pbx_parseable_goto(), process_ast_dsp(), and socket_process().
06471 { 06472 int res = 0; 06473 06474 ast_channel_lock(chan); 06475 06476 if (chan->pbx) { /* This channel is currently in the PBX */ 06477 ast_explicit_goto(chan, context, exten, priority + 1); 06478 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 06479 } else { 06480 /* In order to do it when the channel doesn't really exist within 06481 the PBX, we have to make a new channel, masquerade, and start the PBX 06482 at the new location */ 06483 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name); 06484 if (!tmpchan) { 06485 res = -1; 06486 } else { 06487 if (chan->cdr) { 06488 ast_cdr_discard(tmpchan->cdr); 06489 tmpchan->cdr = ast_cdr_dup(chan->cdr); /* share the love */ 06490 } 06491 /* Make formats okay */ 06492 tmpchan->readformat = chan->readformat; 06493 tmpchan->writeformat = chan->writeformat; 06494 /* Setup proper location */ 06495 ast_explicit_goto(tmpchan, 06496 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 06497 06498 /* Masquerade into temp channel */ 06499 if (ast_channel_masquerade(tmpchan, chan)) { 06500 /* Failed to set up the masquerade. It's probably chan_local 06501 * in the middle of optimizing itself out. Sad. :( */ 06502 ast_hangup(tmpchan); 06503 tmpchan = NULL; 06504 res = -1; 06505 } else { 06506 /* Grab the locks and get going */ 06507 ast_channel_lock(tmpchan); 06508 ast_do_masquerade(tmpchan); 06509 ast_channel_unlock(tmpchan); 06510 /* Start the PBX going on our stolen channel */ 06511 if (ast_pbx_start(tmpchan)) { 06512 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 06513 ast_hangup(tmpchan); 06514 res = -1; 06515 } 06516 } 06517 } 06518 } 06519 ast_channel_unlock(chan); 06520 return res; 06521 }
int ast_async_goto_by_name | ( | const char * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6523 of file pbx.c.
References ast_async_goto(), ast_channel_unlock, ast_get_channel_by_name_locked(), and chan.
06524 { 06525 struct ast_channel *chan; 06526 int res = -1; 06527 06528 chan = ast_get_channel_by_name_locked(channame); 06529 if (chan) { 06530 res = ast_async_goto(chan, context, exten, priority); 06531 ast_channel_unlock(chan); 06532 } 06533 return res; 06534 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8630 of file pbx.c.
References __ast_goto_if_exists(), and chan.
08631 { 08632 return __ast_goto_if_exists(chan, context, exten, priority, 1); 08633 }
int ast_async_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 8693 of file pbx.c.
References chan, and pbx_parseable_goto().
Referenced by asyncgoto_exec().
08694 { 08695 return pbx_parseable_goto(chan, goto_string, 1); 08696 }
int ast_build_timing | ( | struct ast_timing * | i, | |
const char * | info | |||
) |
Definition at line 6110 of file pbx.c.
References ast_copy_string(), ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, and strsep().
Referenced by ast_context_add_include2(), iftime(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
06111 { 06112 char info_save[256]; 06113 char *info; 06114 06115 /* Check for empty just in case */ 06116 if (ast_strlen_zero(info_in)) 06117 return 0; 06118 /* make a copy just in case we were passed a static string */ 06119 ast_copy_string(info_save, info_in, sizeof(info_save)); 06120 info = info_save; 06121 /* Assume everything except time */ 06122 i->monthmask = 0xfff; /* 12 bits */ 06123 i->daymask = 0x7fffffffU; /* 31 bits */ 06124 i->dowmask = 0x7f; /* 7 bits */ 06125 /* on each call, use strsep() to move info to the next argument */ 06126 get_timerange(i, strsep(&info, "|,")); 06127 if (info) 06128 i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week"); 06129 if (info) 06130 i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day"); 06131 if (info) 06132 i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month"); 06133 return 1; 06134 }
int ast_canmatch_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | callerid | |||
) |
Looks for a valid matching extension.
c | not really important | |
context | context to serach within | |
exten | extension to check | |
priority | priority of extension path | |
callerid | callerid of extension being searched for |
Definition at line 3604 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
Referenced by background_detect_exec(), cb_events(), do_immediate_setup(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), handle_link_data(), handle_link_phone_dtmf(), leave_voicemail(), local_dtmf_helper(), loopback_canmatch(), mgcp_ss(), phone_check_exception(), skinny_ss(), ss_thread(), and valid_exit().
03605 { 03606 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0); 03607 }
int ast_check_timing | ( | const struct ast_timing * | i | ) |
Definition at line 6136 of file pbx.c.
References ast_localtime(), ast_log(), ast_tvnow(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, ast_timing::monthmask, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and ast_tm::tm_wday.
Referenced by iftime(), include_valid(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime().
06137 { 06138 struct ast_tm tm; 06139 struct timeval tv = ast_tvnow(); 06140 06141 ast_localtime(&tv, &tm, NULL); 06142 06143 /* If it's not the right month, return */ 06144 if (!(i->monthmask & (1 << tm.tm_mon))) 06145 return 0; 06146 06147 /* If it's not that time of the month.... */ 06148 /* Warning, tm_mday has range 1..31! */ 06149 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 06150 return 0; 06151 06152 /* If it's not the right day of the week */ 06153 if (!(i->dowmask & (1 << tm.tm_wday))) 06154 return 0; 06155 06156 /* Sanity check the hour just to be safe */ 06157 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 06158 ast_log(LOG_WARNING, "Insane time...\n"); 06159 return 0; 06160 } 06161 06162 /* Now the tough part, we calculate if it fits 06163 in the right time based on min/hour */ 06164 if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2)))) 06165 return 0; 06166 06167 /* If we got this far, then we're good */ 06168 return 1; 06169 }
int ast_context_add_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Add an ignorepat.
context | which context to add the ignorpattern to | |
ignorepat | ignorepattern to set up for the extension | |
registrar | registrar of the ignore pattern |
0 | on success | |
-1 | on failure |
Definition at line 6362 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_ignorepat().
06363 { 06364 int ret = -1; 06365 struct ast_context *c = find_context_locked(context); 06366 06367 if (c) { 06368 ret = ast_context_add_ignorepat2(c, value, registrar); 06369 ast_unlock_contexts(); 06370 } 06371 return ret; 06372 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 6374 of file pbx.c.
References ast_calloc, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_add_ignorepat(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
06375 { 06376 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 06377 int length; 06378 char *pattern; 06379 length = sizeof(struct ast_ignorepat); 06380 length += strlen(value) + 1; 06381 if (!(ignorepat = ast_calloc(1, length))) 06382 return -1; 06383 /* The cast to char * is because we need to write the initial value. 06384 * The field is not supposed to be modified otherwise. Also, gcc 4.2 06385 * sees the cast as dereferencing a type-punned pointer and warns about 06386 * it. This is the workaround (we're telling gcc, yes, that's really 06387 * what we wanted to do). 06388 */ 06389 pattern = (char *) ignorepat->pattern; 06390 strcpy(pattern, value); 06391 ignorepat->next = NULL; 06392 ignorepat->registrar = registrar; 06393 ast_wrlock_context(con); 06394 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 06395 ignorepatl = ignorepatc; 06396 if (!strcasecmp(ignorepatc->pattern, value)) { 06397 /* Already there */ 06398 ast_unlock_context(con); 06399 errno = EEXIST; 06400 return -1; 06401 } 06402 } 06403 if (ignorepatl) 06404 ignorepatl->next = ignorepat; 06405 else 06406 con->ignorepats = ignorepat; 06407 ast_unlock_context(con); 06408 return 0; 06409 06410 }
int ast_context_add_include | ( | const char * | context, | |
const char * | include, | |||
const char * | registrar | |||
) |
Add a context include.
context | context to add include to | |
include | new include to add | |
registrar | who's registering it |
0 | on success | |
-1 | on error |
Definition at line 5916 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_add_include().
05917 { 05918 int ret = -1; 05919 struct ast_context *c = find_context_locked(context); 05920 05921 if (c) { 05922 ret = ast_context_add_include2(c, include, registrar); 05923 ast_unlock_contexts(); 05924 } 05925 return ret; 05926 }
int ast_context_add_include2 | ( | struct ast_context * | con, | |
const char * | include, | |||
const char * | registrar | |||
) |
Add a context include.
con | context to add the include to | |
include | include to add | |
registrar | who registered the context |
0 | on success | |
-1 | on failure |
Definition at line 6178 of file pbx.c.
References ast_build_timing(), ast_calloc, ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), errno, ast_include::hastime, ast_context::includes, ast_include::name, ast_include::next, ast_include::registrar, ast_include::rname, ast_include::stuff, and ast_include::timing.
Referenced by ast_context_add_include(), context_merge_incls_swits_igps_other_registrars(), and pbx_load_config().
06180 { 06181 struct ast_include *new_include; 06182 char *c; 06183 struct ast_include *i, *il = NULL; /* include, include_last */ 06184 int length; 06185 char *p; 06186 06187 length = sizeof(struct ast_include); 06188 length += 2 * (strlen(value) + 1); 06189 06190 /* allocate new include structure ... */ 06191 if (!(new_include = ast_calloc(1, length))) 06192 return -1; 06193 /* Fill in this structure. Use 'p' for assignments, as the fields 06194 * in the structure are 'const char *' 06195 */ 06196 p = new_include->stuff; 06197 new_include->name = p; 06198 strcpy(p, value); 06199 p += strlen(value) + 1; 06200 new_include->rname = p; 06201 strcpy(p, value); 06202 /* Strip off timing info, and process if it is there */ 06203 if ( (c = strchr(p, ',')) ) { 06204 *c++ = '\0'; 06205 new_include->hastime = ast_build_timing(&(new_include->timing), c); 06206 } 06207 new_include->next = NULL; 06208 new_include->registrar = registrar; 06209 06210 ast_wrlock_context(con); 06211 06212 /* ... go to last include and check if context is already included too... */ 06213 for (i = con->includes; i; i = i->next) { 06214 if (!strcasecmp(i->name, new_include->name)) { 06215 ast_free(new_include); 06216 ast_unlock_context(con); 06217 errno = EEXIST; 06218 return -1; 06219 } 06220 il = i; 06221 } 06222 06223 /* ... include new context into context list, unlock, return */ 06224 if (il) 06225 il->next = new_include; 06226 else 06227 con->includes = new_include; 06228 ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 06229 06230 ast_unlock_context(con); 06231 06232 return 0; 06233 }
int ast_context_add_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
int | eval, | |||
const char * | registrar | |||
) |
Add a switch.
context | context to which to add the switch | |
sw | switch to add | |
data | data to pass to switch | |
eval | whether to evaluate variables when running switch | |
registrar | whoever registered the switch |
0 | on success | |
-1 | on failure |
Definition at line 6240 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
06241 { 06242 int ret = -1; 06243 struct ast_context *c = find_context_locked(context); 06244 06245 if (c) { /* found, add switch to this context */ 06246 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 06247 ast_unlock_contexts(); 06248 } 06249 return ret; 06250 }
int ast_context_add_switch2 | ( | struct ast_context * | con, | |
const char * | sw, | |||
const char * | data, | |||
int | eval, | |||
const char * | registrar | |||
) |
Adds a switch (first param is a ast_context).
Definition at line 6259 of file pbx.c.
References ast_context::alts, ast_calloc, ast_free, ast_get_context_name(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, errno, ast_sw::eval, store_hint::list, ast_sw::name, ast_sw::registrar, and ast_sw::stuff.
Referenced by ast_context_add_switch(), context_merge_incls_swits_igps_other_registrars(), lua_register_switches(), and pbx_load_config().
06261 { 06262 struct ast_sw *new_sw; 06263 struct ast_sw *i; 06264 int length; 06265 char *p; 06266 06267 length = sizeof(struct ast_sw); 06268 length += strlen(value) + 1; 06269 if (data) 06270 length += strlen(data); 06271 length++; 06272 06273 /* allocate new sw structure ... */ 06274 if (!(new_sw = ast_calloc(1, length))) 06275 return -1; 06276 /* ... fill in this structure ... */ 06277 p = new_sw->stuff; 06278 new_sw->name = p; 06279 strcpy(new_sw->name, value); 06280 p += strlen(value) + 1; 06281 new_sw->data = p; 06282 if (data) { 06283 strcpy(new_sw->data, data); 06284 p += strlen(data) + 1; 06285 } else { 06286 strcpy(new_sw->data, ""); 06287 p++; 06288 } 06289 new_sw->eval = eval; 06290 new_sw->registrar = registrar; 06291 06292 /* ... try to lock this context ... */ 06293 ast_wrlock_context(con); 06294 06295 /* ... go to last sw and check if context is already swd too... */ 06296 AST_LIST_TRAVERSE(&con->alts, i, list) { 06297 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 06298 ast_free(new_sw); 06299 ast_unlock_context(con); 06300 errno = EEXIST; 06301 return -1; 06302 } 06303 } 06304 06305 /* ... sw new context into context list, unlock, return */ 06306 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 06307 06308 ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 06309 06310 ast_unlock_context(con); 06311 06312 return 0; 06313 }
void ast_context_destroy | ( | struct ast_context * | con, | |
const char * | registrar | |||
) |
Destroy a context (matches the specified context (or ANY context if NULL).
con | context to destroy | |
registrar | who registered it |
Definition at line 7537 of file pbx.c.
References __ast_context_destroy(), ast_unlock_contexts(), ast_wrlock_contexts(), contexts, and contexts_table.
Referenced by __unload_module(), cleanup_stale_contexts(), sla_destroy(), and unload_module().
07538 { 07539 ast_wrlock_contexts(); 07540 __ast_context_destroy(contexts, contexts_table, con,registrar); 07541 ast_unlock_contexts(); 07542 }
struct ast_context* ast_context_find | ( | const char * | name | ) |
Find a context.
name | name of the context to find |
Definition at line 2001 of file pbx.c.
References ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::name, and fake_context::name.
Referenced by __unload_module(), _macro_exec(), ast_context_verify_includes(), ast_ignore_pattern(), cleanup_stale_contexts(), do_parking_thread(), isexten_function_read(), park_exec(), register_exten(), register_peer_exten(), unload_module(), and unregister_exten().
02002 { 02003 struct ast_context *tmp = NULL; 02004 struct fake_context item; 02005 strncpy(item.name,name,256); 02006 ast_rdlock_contexts(); 02007 if( contexts_table ) { 02008 tmp = ast_hashtab_lookup(contexts_table,&item); 02009 } else { 02010 while ( (tmp = ast_walk_contexts(tmp)) ) { 02011 if (!name || !strcasecmp(name, tmp->name)) 02012 break; 02013 } 02014 } 02015 ast_unlock_contexts(); 02016 return tmp; 02017 }
struct ast_context* ast_context_find_or_create | ( | struct ast_context ** | extcontexts, | |
struct ast_hashtab * | exttable, | |||
const char * | name, | |||
const char * | registrar | |||
) |
Register a new context or find an existing one.
extcontexts | pointer to the ast_context structure pointer | |
exttable | pointer to the hashtable that contains all the elements in extcontexts | |
name | name of the new context | |
registrar | registrar of the context |
This will first search for a context with your name. If it exists already, it will not create a new one. If it does not exist, it will create a new one with the given name and registrar.
Definition at line 5575 of file pbx.c.
References ast_calloc, ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_insert_immediate(), ast_hashtab_insert_safe(), ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log(), ast_mutex_init(), ast_rdlock_contexts(), ast_rwlock_init(), ast_strdup, ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), contexts, contexts_table, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, ast_context::macrolock, ast_context::name, fake_context::name, name, ast_context::next, ast_context::refcount, ast_context::registrar, ast_context::root, and ast_context::root_table.
Referenced by context_merge(), do_parking_thread(), load_module(), lua_register_switches(), park_call_full(), pbx_load_config(), pbx_load_users(), reload_config(), and set_config().
05576 { 05577 struct ast_context *tmp, **local_contexts; 05578 struct fake_context search; 05579 int length = sizeof(struct ast_context) + strlen(name) + 1; 05580 05581 if (!contexts_table) { 05582 contexts_table = ast_hashtab_create(17, 05583 ast_hashtab_compare_contexts, 05584 ast_hashtab_resize_java, 05585 ast_hashtab_newsize_java, 05586 ast_hashtab_hash_contexts, 05587 0); 05588 } 05589 05590 strncpy(search.name,name,sizeof(search.name)); 05591 if (!extcontexts) { 05592 ast_rdlock_contexts(); 05593 local_contexts = &contexts; 05594 tmp = ast_hashtab_lookup(contexts_table, &search); 05595 ast_unlock_contexts(); 05596 if (tmp) { 05597 tmp->refcount++; 05598 return tmp; 05599 } 05600 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */ 05601 local_contexts = extcontexts; 05602 tmp = ast_hashtab_lookup(exttable, &search); 05603 if (tmp) { 05604 tmp->refcount++; 05605 return tmp; 05606 } 05607 } 05608 05609 if ((tmp = ast_calloc(1, length))) { 05610 ast_rwlock_init(&tmp->lock); 05611 ast_mutex_init(&tmp->macrolock); 05612 strcpy(tmp->name, name); 05613 tmp->root = NULL; 05614 tmp->root_table = NULL; 05615 tmp->registrar = ast_strdup(registrar); 05616 tmp->includes = NULL; 05617 tmp->ignorepats = NULL; 05618 tmp->refcount = 1; 05619 } else { 05620 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name); 05621 return NULL; 05622 } 05623 05624 if (!extcontexts) { 05625 ast_wrlock_contexts(); 05626 tmp->next = *local_contexts; 05627 *local_contexts = tmp; 05628 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */ 05629 ast_unlock_contexts(); 05630 ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 05631 ast_verb(3, "Registered extension context '%s' (%p) in table %p; registrar: %s\n", tmp->name, tmp, contexts_table, registrar); 05632 } else { 05633 tmp->next = *local_contexts; 05634 if (exttable) 05635 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */ 05636 05637 *local_contexts = tmp; 05638 ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 05639 ast_verb(3, "Registered extension context '%s' (%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar); 05640 } 05641 return tmp; 05642 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
Definition at line 4385 of file pbx.c.
References ast_get_context_name(), ast_hashtab_lookup(), ast_mutex_lock(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::macrolock, and fake_context::name.
Referenced by _macro_exec().
04386 { 04387 struct ast_context *c = NULL; 04388 int ret = -1; 04389 struct fake_context item; 04390 04391 ast_rdlock_contexts(); 04392 04393 strncpy(item.name,context,256); 04394 c = ast_hashtab_lookup(contexts_table,&item); 04395 if (c) 04396 ret = 0; 04397 04398 04399 #ifdef NOTNOW 04400 04401 while ((c = ast_walk_contexts(c))) { 04402 if (!strcmp(ast_get_context_name(c), context)) { 04403 ret = 0; 04404 break; 04405 } 04406 } 04407 04408 #endif 04409 ast_unlock_contexts(); 04410 04411 /* if we found context, lock macrolock */ 04412 if (ret == 0) 04413 ret = ast_mutex_lock(&c->macrolock); 04414 04415 return ret; 04416 }
int ast_context_remove_extension | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar | |||
) |
Simply remove extension from context.
context | context to remove extension from | |
extension | which extension to remove | |
priority | priority of extension to remove (0 to remove all) | |
callerid | NULL to remove all; non-NULL to match a single record per priority | |
matchcid | non-zero to match callerid element (if non-NULL); 0 to match default case | |
registrar | registrar of the extension |
0 | on success | |
-1 | on failure |
Definition at line 4192 of file pbx.c.
References ast_context_remove_extension_callerid().
Referenced by destroy_station(), destroy_trunk(), register_peer_exten(), unregister_exten(), and UnregisterExtension().
04193 { 04194 return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar); 04195 }
int ast_context_remove_extension2 | ( | struct ast_context * | con, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar, | |||
int | already_locked | |||
) |
This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
Definition at line 4219 of file pbx.c.
References ast_context_remove_extension_callerid2().
Referenced by do_parking_thread(), park_exec(), and unload_module().
04220 { 04221 return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked); 04222 }
int ast_context_remove_extension_callerid | ( | const char * | context, | |
const char * | extension, | |||
int | priority, | |||
const char * | callerid, | |||
int | matchcid, | |||
const char * | registrar | |||
) |
Definition at line 4197 of file pbx.c.
References ast_context_remove_extension_callerid2(), ast_unlock_contexts(), and find_context_locked().
Referenced by ast_context_remove_extension(), and handle_cli_dialplan_remove_extension().
04198 { 04199 int ret = -1; /* default error return */ 04200 struct ast_context *c = find_context_locked(context); 04201 04202 if (c) { /* ... remove extension ... */ 04203 ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcid, registrar, 1); 04204 ast_unlock_contexts(); 04205 } 04206 return ret; 04207 }
int ast_context_remove_extension_callerid2 | ( | struct ast_context * | con, | |
const char * | extension, | |||
int | priority, | |||
const char * | callerid, | |||
int | matchcid, | |||
const char * | registrar, | |||
int | already_locked | |||
) |
Definition at line 4224 of file pbx.c.
References add_exten_to_pattern_tree(), ast_copy_string(), ast_hashtab_insert_immediate(), ast_hashtab_lookup(), ast_hashtab_remove_this_object(), ast_hashtab_size(), ast_log(), ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, destroy_exten(), ast_exten::exten, exten, ast_exten::label, LOG_ERROR, log_match_char_tree(), LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_exten::next, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, and match_char::x.
Referenced by __ast_context_destroy(), ast_context_remove_extension2(), and ast_context_remove_extension_callerid().
04225 { 04226 struct ast_exten *exten, *prev_exten = NULL; 04227 struct ast_exten *peer; 04228 struct ast_exten ex, *exten2, *exten3; 04229 char dummy_name[1024]; 04230 struct ast_exten *previous_peer = NULL; 04231 struct ast_exten *next_peer = NULL; 04232 int found = 0; 04233 04234 if (!already_locked) 04235 ast_wrlock_context(con); 04236 04237 /* Handle this is in the new world */ 04238 04239 /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL 04240 * peers, not just those matching the callerid. */ 04241 #ifdef NEED_DEBUG 04242 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcid ? "/" : "", matchcid ? callerid : "", registrar); 04243 #endif 04244 #ifdef CONTEXT_DEBUG 04245 check_contexts(__FILE__, __LINE__); 04246 #endif 04247 /* find this particular extension */ 04248 ex.exten = dummy_name; 04249 ex.matchcid = matchcid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */ 04250 ex.cidmatch = callerid; 04251 ast_copy_string(dummy_name, extension, sizeof(dummy_name)); 04252 exten = ast_hashtab_lookup(con->root_table, &ex); 04253 if (exten) { 04254 if (priority == 0) { 04255 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 04256 if (!exten2) 04257 ast_log(LOG_ERROR,"Trying to delete the exten %s from context %s, but could not remove from the root_table\n", extension, con->name); 04258 if (con->pattern_tree) { 04259 04260 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 04261 04262 if (x->exten) { /* this test for safety purposes */ 04263 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 04264 x->exten = 0; /* get rid of what will become a bad pointer */ 04265 } else { 04266 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n"); 04267 } 04268 } 04269 } else { 04270 ex.priority = priority; 04271 exten2 = ast_hashtab_lookup(exten->peer_table, &ex); 04272 if (exten2) { 04273 04274 if (exten2->label) { /* if this exten has a label, remove that, too */ 04275 exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2); 04276 if (!exten3) 04277 ast_log(LOG_ERROR,"Did not remove this priority label (%d/%s) from the peer_label_table of context %s, extension %s!\n", priority, exten2->label, con->name, exten2->exten); 04278 } 04279 04280 exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2); 04281 if (!exten3) 04282 ast_log(LOG_ERROR,"Did not remove this priority (%d) from the peer_table of context %s, extension %s!\n", priority, con->name, exten2->exten); 04283 if (exten2 == exten && exten2->peer) { 04284 exten2 = ast_hashtab_remove_this_object(con->root_table, exten); 04285 ast_hashtab_insert_immediate(con->root_table, exten2->peer); 04286 } 04287 if (ast_hashtab_size(exten->peer_table) == 0) { 04288 /* well, if the last priority of an exten is to be removed, 04289 then, the extension is removed, too! */ 04290 exten3 = ast_hashtab_remove_this_object(con->root_table, exten); 04291 if (!exten3) 04292 ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority); 04293 if (con->pattern_tree) { 04294 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1); 04295 if (x->exten) { /* this test for safety purposes */ 04296 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */ 04297 x->exten = 0; /* get rid of what will become a bad pointer */ 04298 } 04299 } 04300 } 04301 } else { 04302 ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n", 04303 priority, exten->exten, con->name); 04304 } 04305 } 04306 } else { 04307 /* hmmm? this exten is not in this pattern tree? */ 04308 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n", 04309 extension, con->name); 04310 } 04311 #ifdef NEED_DEBUG 04312 if (con->pattern_tree) { 04313 ast_log(LOG_NOTICE,"match char tree after exten removal:\n"); 04314 log_match_char_tree(con->pattern_tree, " "); 04315 } 04316 #endif 04317 04318 /* scan the extension list to find first matching extension-registrar */ 04319 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 04320 if (!strcmp(exten->exten, extension) && 04321 (!registrar || !strcmp(exten->registrar, registrar)) && 04322 (!matchcid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch)))) 04323 break; 04324 } 04325 if (!exten) { 04326 /* we can't find right extension */ 04327 if (!already_locked) 04328 ast_unlock_context(con); 04329 return -1; 04330 } 04331 04332 /* scan the priority list to remove extension with exten->priority == priority */ 04333 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next; 04334 peer && !strcmp(peer->exten, extension) && (!matchcid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(peer->cidmatch) && !strcmp(peer->cidmatch,callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(peer->cidmatch))); 04335 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) { 04336 if ((priority == 0 || peer->priority == priority) && 04337 (!callerid || !matchcid || (matchcid && !strcmp(peer->cidmatch, callerid))) && 04338 (!registrar || !strcmp(peer->registrar, registrar) )) { 04339 found = 1; 04340 04341 /* we are first priority extension? */ 04342 if (!previous_peer) { 04343 /* 04344 * We are first in the priority chain, so must update the extension chain. 04345 * The next node is either the next priority or the next extension 04346 */ 04347 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 04348 if (peer->peer) { 04349 /* move the peer_table and peer_label_table down to the next peer, if 04350 it is there */ 04351 peer->peer->peer_table = peer->peer_table; 04352 peer->peer->peer_label_table = peer->peer_label_table; 04353 peer->peer_table = NULL; 04354 peer->peer_label_table = NULL; 04355 } 04356 if (!prev_exten) { /* change the root... */ 04357 con->root = next_node; 04358 } else { 04359 prev_exten->next = next_node; /* unlink */ 04360 } 04361 if (peer->peer) { /* update the new head of the pri list */ 04362 peer->peer->next = peer->next; 04363 } 04364 } else { /* easy, we are not first priority in extension */ 04365 previous_peer->peer = peer->peer; 04366 } 04367 04368 /* now, free whole priority extension */ 04369 destroy_exten(peer); 04370 } else { 04371 previous_peer = peer; 04372 } 04373 } 04374 if (!already_locked) 04375 ast_unlock_context(con); 04376 return found ? 0 : -1; 04377 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 6319 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_ignorepat().
06320 { 06321 int ret = -1; 06322 struct ast_context *c = find_context_locked(context); 06323 06324 if (c) { 06325 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 06326 ast_unlock_contexts(); 06327 } 06328 return ret; 06329 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 6331 of file pbx.c.
References ast_free, ast_unlock_context(), ast_wrlock_context(), errno, ast_context::ignorepats, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
Referenced by ast_context_remove_ignorepat().
06332 { 06333 struct ast_ignorepat *ip, *ipl = NULL; 06334 06335 ast_wrlock_context(con); 06336 06337 for (ip = con->ignorepats; ip; ip = ip->next) { 06338 if (!strcmp(ip->pattern, ignorepat) && 06339 (!registrar || (registrar == ip->registrar))) { 06340 if (ipl) { 06341 ipl->next = ip->next; 06342 ast_free(ip); 06343 } else { 06344 con->ignorepats = ip->next; 06345 ast_free(ip); 06346 } 06347 ast_unlock_context(con); 06348 return 0; 06349 } 06350 ipl = ip; 06351 } 06352 06353 ast_unlock_context(con); 06354 errno = EINVAL; 06355 return -1; 06356 }
int ast_context_remove_include | ( | const char * | context, | |
const char * | include, | |||
const char * | registrar | |||
) |
Remove a context include.
0 | on success | |
-1 | on failure |
Definition at line 4084 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
Referenced by handle_cli_dialplan_remove_include().
04085 { 04086 int ret = -1; 04087 struct ast_context *c = find_context_locked(context); 04088 04089 if (c) { 04090 /* found, remove include from this context ... */ 04091 ret = ast_context_remove_include2(c, include, registrar); 04092 ast_unlock_contexts(); 04093 } 04094 return ret; 04095 }
int ast_context_remove_include2 | ( | struct ast_context * | con, | |
const char * | include, | |||
const char * | registrar | |||
) |
Removes an include by an ast_context structure.
0 | on success. | |
-1 | on failure. |
Definition at line 4106 of file pbx.c.
References ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_context::includes, ast_include::name, ast_include::next, and ast_include::registrar.
Referenced by ast_context_remove_include().
04107 { 04108 struct ast_include *i, *pi = NULL; 04109 int ret = -1; 04110 04111 ast_wrlock_context(con); 04112 04113 /* find our include */ 04114 for (i = con->includes; i; pi = i, i = i->next) { 04115 if (!strcmp(i->name, include) && 04116 (!registrar || !strcmp(i->registrar, registrar))) { 04117 /* remove from list */ 04118 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar); 04119 if (pi) 04120 pi->next = i->next; 04121 else 04122 con->includes = i->next; 04123 /* free include and return */ 04124 ast_free(i); 04125 ret = 0; 04126 break; 04127 } 04128 } 04129 04130 ast_unlock_context(con); 04131 04132 return ret; 04133 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Definition at line 4140 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
04141 { 04142 int ret = -1; /* default error return */ 04143 struct ast_context *c = find_context_locked(context); 04144 04145 if (c) { 04146 /* remove switch from this context ... */ 04147 ret = ast_context_remove_switch2(c, sw, data, registrar); 04148 ast_unlock_contexts(); 04149 } 04150 return ret; 04151 }
int ast_context_remove_switch2 | ( | struct ast_context * | con, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
This function locks given context, removes switch, unlock context and return.
Definition at line 4161 of file pbx.c.
References ast_context::alts, ast_free, ast_get_context_name(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_sw::data, ast_sw::list, ast_sw::name, and ast_sw::registrar.
Referenced by ast_context_remove_switch().
04162 { 04163 struct ast_sw *i; 04164 int ret = -1; 04165 04166 ast_wrlock_context(con); 04167 04168 /* walk switches */ 04169 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 04170 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 04171 (!registrar || !strcmp(i->registrar, registrar))) { 04172 /* found, remove from list */ 04173 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar); 04174 AST_LIST_REMOVE_CURRENT(list); 04175 ast_free(i); /* free switch and return */ 04176 ret = 0; 04177 break; 04178 } 04179 } 04180 AST_LIST_TRAVERSE_SAFE_END; 04181 04182 ast_unlock_context(con); 04183 04184 return ret; 04185 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
Definition at line 4423 of file pbx.c.
References ast_get_context_name(), ast_hashtab_lookup(), ast_mutex_unlock(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, ast_context::macrolock, and fake_context::name.
Referenced by _macro_exec().
04424 { 04425 struct ast_context *c = NULL; 04426 int ret = -1; 04427 struct fake_context item; 04428 04429 ast_rdlock_contexts(); 04430 04431 strncpy(item.name, context, 256); 04432 c = ast_hashtab_lookup(contexts_table,&item); 04433 if (c) 04434 ret = 0; 04435 #ifdef NOTNOW 04436 04437 while ((c = ast_walk_contexts(c))) { 04438 if (!strcmp(ast_get_context_name(c), context)) { 04439 ret = 0; 04440 break; 04441 } 04442 } 04443 04444 #endif 04445 ast_unlock_contexts(); 04446 04447 /* if we found context, unlock macrolock */ 04448 if (ret == 0) 04449 ret = ast_mutex_unlock(&c->macrolock); 04450 04451 return ret; 04452 }
int ast_context_verify_includes | ( | struct ast_context * | con | ) |
Verifies includes in an ast_contect structure.
con | context in which to verify the includes |
0 | if no problems found | |
-1 | if there were any missing context |
Definition at line 8587 of file pbx.c.
References ast_context_find(), ast_get_context_name(), ast_log(), ast_walk_context_includes(), LOG_WARNING, and ast_include::rname.
Referenced by pbx_load_module().
08588 { 08589 struct ast_include *inc = NULL; 08590 int res = 0; 08591 08592 while ( (inc = ast_walk_context_includes(con, inc)) ) { 08593 if (ast_context_find(inc->rname)) 08594 continue; 08595 08596 res = -1; 08597 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n", 08598 ast_get_context_name(con), inc->rname); 08599 break; 08600 } 08601 08602 return res; 08603 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) |
Definition at line 2685 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_function::name.
Referenced by ast_func_read(), ast_func_write(), config_curl(), destroy_curl(), handle_show_function(), op_func(), realtime_curl(), realtime_multi_curl(), store_curl(), and update_curl().
02686 { 02687 struct ast_custom_function *acf = NULL; 02688 02689 AST_RWLIST_RDLOCK(&acf_root); 02690 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 02691 if (!strcmp(name, acf->name)) 02692 break; 02693 } 02694 AST_RWLIST_UNLOCK(&acf_root); 02695 02696 return acf; 02697 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 2699 of file pbx.c.
References ast_custom_function::acflist, AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, and ast_custom_function::name.
Referenced by reload(), and unload_module().
02700 { 02701 struct ast_custom_function *cur; 02702 02703 if (!acf) 02704 return -1; 02705 02706 AST_RWLIST_WRLOCK(&acf_root); 02707 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) 02708 ast_verb(2, "Unregistered custom function %s\n", cur->name); 02709 AST_RWLIST_UNLOCK(&acf_root); 02710 02711 return cur ? 0 : -1; 02712 }
int ast_exists_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | callerid | |||
) |
Determine whether an extension exists.
c | this is not important | |
context | which context to look in | |
exten | which extension to search for | |
priority | priority of the action within the extension | |
callerid | callerid to search for |
Definition at line 3589 of file pbx.c.
References E_MATCH, and pbx_extension_helper().
Referenced by __ast_goto_if_exists(), __ast_pbx_run(), _macro_exec(), acf_isexten_exec(), answer_call(), ast_app_dtget(), ast_bridge_call(), ast_pbx_outgoing_exten(), builtin_atxfer(), builtin_blindtransfer(), cb_events(), cli_console_dial(), conf_run(), console_dial(), console_transfer(), dahdi_handle_dtmfup(), dial_exec_full(), disa_exec(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), gosub_exec(), handle_gosub(), handle_link_data(), handle_link_phone_dtmf(), handle_stimulus_message(), isexten_function_read(), leave_voicemail(), local_alloc(), local_devicestate(), local_dtmf_helper(), loopback_exists(), metermaidstate(), mgcp_ss(), minivm_greet_exec(), misdn_overlap_dial_task(), park_space_reserve(), parkandannounce_exec(), pbx_builtin_waitexten(), phone_check_exception(), pri_dchannel(), process_ast_dsp(), readexten_exec(), register_peer_exten(), skinny_ss(), socket_process(), ss_thread(), and waitstream_core().
03590 { 03591 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0); 03592 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6447 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_FLAG_IN_AUTOLOOP, ast_strlen_zero(), ast_test_flag, chan, ast_channel::context, ast_channel::exten, and ast_channel::priority.
Referenced by __ast_goto_if_exists(), ast_async_goto(), builtin_atxfer(), do_bridge_masquerade(), handle_setpriority(), pbx_parseable_goto(), and return_exec().
06448 { 06449 if (!chan) 06450 return -1; 06451 06452 ast_channel_lock(chan); 06453 06454 if (!ast_strlen_zero(context)) 06455 ast_copy_string(chan->context, context, sizeof(chan->context)); 06456 if (!ast_strlen_zero(exten)) 06457 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06458 if (priority > -1) { 06459 chan->priority = priority; 06460 /* see flag description in channel.h for explanation */ 06461 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 06462 chan->priority--; 06463 } 06464 06465 ast_channel_unlock(chan); 06466 06467 return 0; 06468 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 1978 of file pbx.c.
References ast_log(), E_CANMATCH, E_MATCHMORE, extension_match_core(), and LOG_WARNING.
Referenced by lua_find_extension(), and realtime_switch_common().
01979 { 01980 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 01981 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 01982 return extension_match_core(pattern, data, needmore); 01983 }
int ast_extension_cmp | ( | const char * | a, | |
const char * | b | |||
) |
Determine if one extension should match before another.
a | extension to compare with b | |
b | extension to compare with a |
0 | if the two extensions have equal matching priority | |
1 | on a > b | |
-1 | on a < b |
Definition at line 1780 of file pbx.c.
References ext_cmp().
Referenced by lua_extension_cmp().
01781 { 01782 return ext_cmp(a, b); 01783 }
int ast_extension_match | ( | const char * | pattern, | |
const char * | extension | |||
) |
Determine if a given extension matches a given pattern (in NXX format).
pattern | pattern to match | |
extension | extension to check against the pattern. |
1 | on match | |
0 | on failure |
Definition at line 1973 of file pbx.c.
References E_MATCH, and extension_match_core().
Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), load_module(), loopback_canmatch(), loopback_exists(), loopback_matchmore(), lua_find_extension(), manager_show_dialplan_helper(), matchcid(), misdn_cfg_is_msn_valid(), realtime_switch_common(), reload(), and show_dialplan_helper().
01974 { 01975 return extension_match_core(pattern, data, E_MATCH); 01976 }
int ast_extension_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 3266 of file pbx.c.
References ast_extension_state2(), and ast_hint_extension().
Referenced by action_extensionstate(), extstate_read(), and handle_request_subscribe().
03267 { 03268 struct ast_exten *e; 03269 03270 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */ 03271 if (!e) 03272 return -1; /* No hint, return -1 */ 03273 03274 return ast_extension_state2(e); /* Check all devices in the hint */ 03275 }
const char* ast_extension_state2str | ( | int | extension_state | ) |
Return string representation of the state of an extension.
extension_state | is the numerical state delivered by ast_extension_state |
Definition at line 3254 of file pbx.c.
References ARRAY_LEN, extension_states, and cfextension_states::text.
Referenced by cb_extensionstate(), handle_request_subscribe(), handle_show_hint(), handle_show_hints(), and show_channels_cb().
03255 { 03256 int i; 03257 03258 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) { 03259 if (extension_states[i].extension_state == extension_state) 03260 return extension_states[i].text; 03261 } 03262 return "Unknown"; 03263 }
int ast_extension_state_add | ( | const char * | context, | |
const char * | exten, | |||
ast_state_cb_type | callback, | |||
void * | data | |||
) |
Registers a state change callback.
context | which context to look in | |
exten | which extension to get state | |
callback | callback to call if state changed | |
data | to pass to callback |
-1 | on failure | |
ID | on success |
Definition at line 3364 of file pbx.c.
References ast_calloc, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_state_cb::callback, ast_state_cb::data, ast_state_cb::next, and statecbs.
Referenced by __init_manager(), and handle_request_subscribe().
03366 { 03367 struct ast_hint *hint; 03368 struct ast_state_cb *cblist; 03369 struct ast_exten *e; 03370 03371 /* If there's no context and extension: add callback to statecbs list */ 03372 if (!context && !exten) { 03373 AST_RWLIST_WRLOCK(&hints); 03374 03375 for (cblist = statecbs; cblist; cblist = cblist->next) { 03376 if (cblist->callback == callback) { 03377 cblist->data = data; 03378 AST_RWLIST_UNLOCK(&hints); 03379 return 0; 03380 } 03381 } 03382 03383 /* Now insert the callback */ 03384 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 03385 AST_RWLIST_UNLOCK(&hints); 03386 return -1; 03387 } 03388 cblist->id = 0; 03389 cblist->callback = callback; 03390 cblist->data = data; 03391 03392 cblist->next = statecbs; 03393 statecbs = cblist; 03394 03395 AST_RWLIST_UNLOCK(&hints); 03396 return 0; 03397 } 03398 03399 if (!context || !exten) 03400 return -1; 03401 03402 /* This callback type is for only one hint, so get the hint */ 03403 e = ast_hint_extension(NULL, context, exten); 03404 if (!e) { 03405 return -1; 03406 } 03407 03408 /* Find the hint in the list of hints */ 03409 AST_RWLIST_WRLOCK(&hints); 03410 03411 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03412 if (hint->exten == e) 03413 break; 03414 } 03415 03416 if (!hint) { 03417 /* We have no hint, sorry */ 03418 AST_RWLIST_UNLOCK(&hints); 03419 return -1; 03420 } 03421 03422 /* Now insert the callback in the callback list */ 03423 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 03424 AST_RWLIST_UNLOCK(&hints); 03425 return -1; 03426 } 03427 cblist->id = stateid++; /* Unique ID for this callback */ 03428 cblist->callback = callback; /* Pointer to callback routine */ 03429 cblist->data = data; /* Data for the callback */ 03430 03431 cblist->next = hint->callbacks; 03432 hint->callbacks = cblist; 03433 03434 AST_RWLIST_UNLOCK(&hints); 03435 return cblist->id; 03436 }
int ast_extension_state_del | ( | int | id, | |
ast_state_cb_type | callback | |||
) |
Deletes a registered state change callback by ID.
id | of the callback to delete | |
callback | callback |
0 | success | |
-1 | failure |
Definition at line 3439 of file pbx.c.
References ast_free, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_hint::callbacks, ast_hint::list, ast_state_cb::next, and statecbs.
Referenced by __sip_destroy(), handle_request_subscribe(), and skinny_unregister().
03440 { 03441 struct ast_state_cb **p_cur = NULL; /* address of pointer to us */ 03442 int ret = -1; 03443 03444 if (!id && !callback) 03445 return -1; 03446 03447 AST_RWLIST_WRLOCK(&hints); 03448 03449 if (!id) { /* id == 0 is a callback without extension */ 03450 for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) { 03451 if ((*p_cur)->callback == callback) 03452 break; 03453 } 03454 } else { /* callback with extension, find the callback based on ID */ 03455 struct ast_hint *hint; 03456 AST_RWLIST_TRAVERSE(&hints, hint, list) { 03457 for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) { 03458 if ((*p_cur)->id == id) 03459 break; 03460 } 03461 if (*p_cur) /* found in the inner loop */ 03462 break; 03463 } 03464 } 03465 if (p_cur && *p_cur) { 03466 struct ast_state_cb *cur = *p_cur; 03467 *p_cur = cur->next; 03468 ast_free(cur); 03469 ret = 0; 03470 } 03471 AST_RWLIST_UNLOCK(&hints); 03472 return ret; 03473 }
int ast_findlabel_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten, | |||
const char * | label, | |||
const char * | callerid | |||
) |
Find the priority of an extension that has the specified label.
c | this is not important | |
context | which context to look in | |
exten | which extension to search for | |
label | label of the action within the extension to match to priority | |
callerid | callerid to search for |
the | priority which matches the given label in the extension | |
-1 | if not found. |
Definition at line 3594 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by action_originate(), action_redirect(), handle_gosub(), handle_setpriority(), isexten_function_read(), and pbx_parseable_goto().
03595 { 03596 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 03597 }
int ast_findlabel_extension2 | ( | struct ast_channel * | c, | |
struct ast_context * | con, | |||
const char * | exten, | |||
const char * | label, | |||
const char * | callerid | |||
) |
Find the priority of an extension that has the specified label.
This function is the same as ast_findlabel_extension, except that it accepts a pointer to an ast_context structure to specify the context instead of the name of the context. Otherwise, the functions behave the same.
Definition at line 3599 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
Referenced by pbx_load_config().
03600 { 03601 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0); 03602 }
int ast_func_read | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | workspace, | |||
size_t | len | |||
) |
executes a read operation on a function
chan | Channel to execute on | |
function | Data containing the function call string (will be modified) | |
workspace | A pointer to safe memory to use for a return value | |
len | the number of bytes in workspace |
Definition at line 2772 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_custom_function_find(), ast_log(), ast_strdupa, chan, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::read.
Referenced by action_getvar(), handle_getvariable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
02773 { 02774 char *copy = ast_strdupa(function); 02775 char *args = func_args(copy); 02776 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 02777 02778 if (acfptr == NULL) 02779 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 02780 else if (!acfptr->read) 02781 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 02782 else { 02783 int res; 02784 struct ast_module_user *u = NULL; 02785 if (acfptr->mod) 02786 u = __ast_module_user_add(acfptr->mod, chan); 02787 res = acfptr->read(chan, copy, args, workspace, len); 02788 if (acfptr->mod && u) 02789 __ast_module_user_remove(acfptr->mod, u); 02790 return res; 02791 } 02792 return -1; 02793 }
int ast_func_write | ( | struct ast_channel * | chan, | |
const char * | function, | |||
const char * | value | |||
) |
executes a write operation on a function
chan | Channel to execute on | |
function | Data containing the function call string (will be modified) | |
value | A value parameter to pass for writing |
Definition at line 2795 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), ast_custom_function_find(), ast_log(), ast_strdupa, chan, copy(), func_args(), LOG_ERROR, ast_custom_function::mod, and ast_custom_function::write.
Referenced by pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().
02796 { 02797 char *copy = ast_strdupa(function); 02798 char *args = func_args(copy); 02799 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 02800 02801 if (acfptr == NULL) 02802 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 02803 else if (!acfptr->write) 02804 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 02805 else { 02806 int res; 02807 struct ast_module_user *u = NULL; 02808 if (acfptr->mod) 02809 u = __ast_module_user_add(acfptr->mod, chan); 02810 res = acfptr->write(chan, copy, args, value); 02811 if (acfptr->mod && u) 02812 __ast_module_user_remove(acfptr->mod, u); 02813 return res; 02814 } 02815 02816 return -1; 02817 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
Definition at line 8439 of file pbx.c.
References ast_context::name.
Referenced by _macro_exec(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_lockmacro(), ast_context_remove_include2(), ast_context_remove_switch2(), ast_context_unlockmacro(), ast_context_verify_includes(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), context_merge_incls_swits_igps_other_registrars(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), manager_show_dialplan_helper(), and show_dialplan_helper().
08440 { 08441 return con ? con->name : NULL; 08442 }
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 8477 of file pbx.c.
References ast_context::registrar.
Referenced by handle_cli_dialplan_save(), and show_dialplan_helper().
08478 { 08479 return c ? c->registrar : NULL; 08480 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 8507 of file pbx.c.
References ast_exten::app.
Referenced by _macro_exec(), ast_add_hint_nolock(), ast_extension_state2(), ast_get_hint(), find_matching_endwhile(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), handle_statechange(), manager_show_dialplan_helper(), and print_ext().
08508 { 08509 return e ? e->app : NULL; 08510 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 8512 of file pbx.c.
References ast_exten::data.
Referenced by _macro_exec(), ast_get_hint(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().
08513 { 08514 return e ? e->data : NULL; 08515 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 8502 of file pbx.c.
References ast_exten::cidmatch.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
08503 { 08504 return e ? e->cidmatch : NULL; 08505 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) |
Definition at line 8444 of file pbx.c.
References exten.
Referenced by handle_show_hint(), and handle_show_hints().
const char* ast_get_extension_label | ( | struct ast_exten * | e | ) |
Definition at line 8454 of file pbx.c.
References exten.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 8497 of file pbx.c.
References ast_exten::matchcid.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().
08498 { 08499 return e ? e->matchcid : 0; 08500 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 8449 of file pbx.c.
References exten.
Referenced by ast_add_hint_nolock(), complete_core_show_hint(), complete_dialplan_remove_extension(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), handle_show_hint(), handle_show_hints(), manager_show_dialplan_helper(), and show_dialplan_helper().
int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 8469 of file pbx.c.
References exten.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().
const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 8482 of file pbx.c.
References ast_exten::registrar.
Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
08483 { 08484 return e ? e->registrar : NULL; 08485 }
int ast_get_hint | ( | char * | hint, | |
int | maxlen, | |||
char * | name, | |||
int | maxnamelen, | |||
struct ast_channel * | c, | |||
const char * | context, | |||
const char * | exten | |||
) |
If an extension hint exists, return non-zero.
hint | buffer for hint | |
maxlen | size of hint buffer | |
name | buffer for name portion of hint | |
maxnamelen | size of name buffer | |
c | this is not important | |
context | which context to look in | |
exten | which extension to search for |
Definition at line 3572 of file pbx.c.
References ast_copy_string(), ast_get_extension_app(), ast_get_extension_app_data(), and ast_hint_extension().
Referenced by action_extensionstate(), get_cid_name(), get_destination(), hint_read(), manager_state_cb(), pbx_retrieve_variable(), skinny_extensionstate_cb(), and transmit_state_notify().
03573 { 03574 struct ast_exten *e = ast_hint_extension(c, context, exten); 03575 03576 if (e) { 03577 if (hint) 03578 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 03579 if (name) { 03580 const char *tmp = ast_get_extension_app_data(e); 03581 if (tmp) 03582 ast_copy_string(name, tmp, namesize); 03583 } 03584 return -1; 03585 } 03586 return 0; 03587 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 8464 of file pbx.c.
References ast_ignorepat::pattern.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
08465 { 08466 return ip ? ip->pattern : NULL; 08467 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 8492 of file pbx.c.
References ast_ignorepat::registrar.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
08493 { 08494 return ip ? ip->registrar : NULL; 08495 }
const char* ast_get_include_name | ( | struct ast_include * | include | ) |
Definition at line 8459 of file pbx.c.
References ast_include::name.
Referenced by complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 8487 of file pbx.c.
References ast_include::registrar.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
08488 { 08489 return i ? i->registrar : NULL; 08490 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 8522 of file pbx.c.
References ast_sw::data.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
08523 { 08524 return sw ? sw->data : NULL; 08525 }
int ast_get_switch_eval | ( | struct ast_sw * | sw | ) |
Definition at line 8527 of file pbx.c.
References ast_sw::eval.
Referenced by context_merge_incls_swits_igps_other_registrars().
08528 { 08529 return sw->eval; 08530 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 8517 of file pbx.c.
References ast_sw::name.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
08518 { 08519 return sw ? sw->name : NULL; 08520 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 8532 of file pbx.c.
References ast_sw::registrar.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
08533 { 08534 return sw ? sw->registrar : NULL; 08535 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 8625 of file pbx.c.
References __ast_goto_if_exists(), and chan.
Referenced by background_detect_exec(), channel_spy(), common_exec(), conf_run(), goto_exten(), onedigit_goto(), select_entry(), and valid_exit().
08626 { 08627 return __ast_goto_if_exists(chan, context, exten, priority, 0); 08628 }
int ast_hashtab_compare_contexts | ( | const void * | ah_a, | |
const void * | ah_b | |||
) |
unsigned int ast_hashtab_hash_contexts | ( | const void * | obj | ) |
int ast_ignore_pattern | ( | const char * | context, | |
const char * | pattern | |||
) |
Checks to see if a number should be ignored.
context | context to search within | |
pattern | to check whether it should be ignored or not |
0 | if the pattern should not be ignored | |
non-zero | if the pattern should be ignored |
Definition at line 6412 of file pbx.c.
References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.
Referenced by ast_app_dtget(), disa_exec(), dp_lookup(), dundi_lookup_local(), handle_enbloc_call_message(), handle_soft_key_event_message(), handle_stimulus_message(), mgcp_ss(), skinny_ss(), and ss_thread().
06413 { 06414 struct ast_context *con = ast_context_find(context); 06415 if (con) { 06416 struct ast_ignorepat *pat; 06417 for (pat = con->ignorepats; pat; pat = pat->next) { 06418 if (ast_extension_match(pat->pattern, pattern)) 06419 return 1; 06420 } 06421 } 06422 06423 return 0; 06424 }
int ast_matchmore_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | callerid | |||
) |
Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
c | not really important XXX | |
context | context to serach within | |
exten | extension to check | |
priority | priority of extension path | |
callerid | callerid of extension being searched for |
Definition at line 3609 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
Referenced by ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), loopback_matchmore(), mgcp_ss(), pbx_builtin_background(), readexten_exec(), skinny_ss(), and ss_thread().
03610 { 03611 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0); 03612 }
void ast_merge_contexts_and_delete | ( | struct ast_context ** | extcontexts, | |
struct ast_hashtab * | exttable, | |||
const char * | registrar | |||
) |
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
extcontexts | pointer to the ast_context structure | |
exttable | pointer to the ast_hashtab structure that contains all the elements in extcontexts | |
registrar | of the context; if it's set the routine will delete all contexts that belong to that registrar; if NULL only the contexts that are specified in extcontexts |
Definition at line 5774 of file pbx.c.
References __ast_internal_context_destroy(), ast_calloc, AST_EXTENSION_REMOVED, ast_free, ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_log(), ast_rdlock_contexts(), AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), ast_wrlock_contexts_version(), ast_state_cb::callback, store_hint::callbacks, ast_hint::callbacks, store_hint::context, context_merge(), contexts, contexts_table, ast_state_cb::data, E_MATCH, ast_exten::exten, ast_hint::exten, store_hint::exten, ast_hint::laststate, store_hint::laststate, store_hint::list, LOG_WARNING, ast_context::name, ast_context::next, store_hint::next, ast_state_cb::next, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_context::registrar, and pbx_find_info::stacklen.
Referenced by lua_reload_extensions(), and pbx_load_module().
05775 { 05776 double ft; 05777 struct ast_context *tmp, *oldcontextslist; 05778 struct ast_hashtab *oldtable; 05779 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 05780 struct store_hint *this; 05781 struct ast_hint *hint; 05782 struct ast_exten *exten; 05783 int length; 05784 struct ast_state_cb *thiscb, *prevcb; 05785 struct ast_hashtab_iter *iter; 05786 05787 /* it is very important that this function hold the hint list lock _and_ the conlock 05788 during its operation; not only do we need to ensure that the list of contexts 05789 and extensions does not change, but also that no hint callbacks (watchers) are 05790 added or removed during the merge/delete process 05791 05792 in addition, the locks _must_ be taken in this order, because there are already 05793 other code paths that use this order 05794 */ 05795 05796 struct timeval begintime, writelocktime, endlocktime, enddeltime; 05797 int wrlock_ver; 05798 05799 begintime = ast_tvnow(); 05800 ast_rdlock_contexts(); 05801 iter = ast_hashtab_start_traversal(contexts_table); 05802 while ((tmp=ast_hashtab_next(iter))) { 05803 context_merge(extcontexts, exttable, tmp, registrar); 05804 } 05805 ast_hashtab_end_traversal(iter); 05806 wrlock_ver = ast_wrlock_contexts_version(); 05807 05808 ast_unlock_contexts(); /* this feels real retarded, but you must do 05809 what you must do If this isn't done, the following 05810 wrlock is a guraranteed deadlock */ 05811 ast_wrlock_contexts(); 05812 if (ast_wrlock_contexts_version() > wrlock_ver+1) { 05813 ast_log(LOG_WARNING,"==================!!!!!!!!!!!!!!!Something changed the contexts in the middle of merging contexts!\n"); 05814 } 05815 05816 AST_RWLIST_WRLOCK(&hints); 05817 writelocktime = ast_tvnow(); 05818 05819 /* preserve all watchers for hints associated with this registrar */ 05820 AST_RWLIST_TRAVERSE(&hints, hint, list) { 05821 if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) { 05822 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 05823 if (!(this = ast_calloc(1, length))) 05824 continue; 05825 this->callbacks = hint->callbacks; 05826 hint->callbacks = NULL; 05827 this->laststate = hint->laststate; 05828 this->context = this->data; 05829 strcpy(this->data, hint->exten->parent->name); 05830 this->exten = this->data + strlen(this->context) + 1; 05831 strcpy(this->exten, hint->exten->exten); 05832 AST_LIST_INSERT_HEAD(&store, this, list); 05833 } 05834 } 05835 05836 /* save the old table and list */ 05837 oldtable = contexts_table; 05838 oldcontextslist = contexts; 05839 05840 /* move in the new table and list */ 05841 contexts_table = exttable; 05842 contexts = *extcontexts; 05843 05844 /* restore the watchers for hints that can be found; notify those that 05845 cannot be restored 05846 */ 05847 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 05848 struct pbx_find_info q = { .stacklen = 0 }; 05849 exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH); 05850 /* Find the hint in the list of hints */ 05851 AST_RWLIST_TRAVERSE(&hints, hint, list) { 05852 if (hint->exten == exten) 05853 break; 05854 } 05855 if (!exten || !hint) { 05856 /* this hint has been removed, notify the watchers */ 05857 prevcb = NULL; 05858 thiscb = this->callbacks; 05859 while (thiscb) { 05860 prevcb = thiscb; 05861 thiscb = thiscb->next; 05862 prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data); 05863 ast_free(prevcb); 05864 } 05865 } else { 05866 thiscb = this->callbacks; 05867 while (thiscb->next) 05868 thiscb = thiscb->next; 05869 thiscb->next = hint->callbacks; 05870 hint->callbacks = this->callbacks; 05871 hint->laststate = this->laststate; 05872 } 05873 ast_free(this); 05874 } 05875 05876 AST_RWLIST_UNLOCK(&hints); 05877 ast_unlock_contexts(); 05878 endlocktime = ast_tvnow(); 05879 05880 /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk 05881 is now freely using the new stuff instead */ 05882 05883 ast_hashtab_destroy(oldtable, NULL); 05884 05885 for (tmp = oldcontextslist; tmp; ) { 05886 struct ast_context *next; /* next starting point */ 05887 next = tmp->next; 05888 __ast_internal_context_destroy(tmp); 05889 tmp = next; 05890 } 05891 enddeltime = ast_tvnow(); 05892 05893 ft = ast_tvdiff_us(writelocktime, begintime); 05894 ft /= 1000000.0; 05895 ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft); 05896 05897 ft = ast_tvdiff_us(endlocktime, writelocktime); 05898 ft /= 1000000.0; 05899 ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft); 05900 05901 ft = ast_tvdiff_us(enddeltime, endlocktime); 05902 ft /= 1000000.0; 05903 ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft); 05904 05905 ft = ast_tvdiff_us(enddeltime, begintime); 05906 ft /= 1000000.0; 05907 ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft); 05908 return; 05909 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
This function will handle locking the channel as needed.
Definition at line 8688 of file pbx.c.
References chan, and pbx_parseable_goto().
Referenced by _while_exec(), check_goto_on_transfer(), dial_exec_full(), gosub_exec(), ivr_dispatch(), parkandannounce_exec(), pbx_builtin_goto(), and while_continue_exec().
08689 { 08690 return pbx_parseable_goto(chan, goto_string, 0); 08691 }
int ast_pbx_outgoing_app | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int | timeout, | |||
const char * | app, | |||
const char * | appdata, | |||
int * | reason, | |||
int | sync, | |||
const char * | cid_num, | |||
const char * | cid_name, | |||
struct ast_variable * | vars, | |||
const char * | account, | |||
struct ast_channel ** | locked_channel | |||
) |
Synchronously or asynchronously make an outbound call and send it to a particular application with given extension
Definition at line 7228 of file pbx.c.
References __ast_request_and_dial(), ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create_detached, ast_set_variables(), AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), chan, errno, LOG_WARNING, and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), and orig_app().
07229 { 07230 struct ast_channel *chan; 07231 struct app_tmp *tmp; 07232 int res = -1, cdr_res = -1; 07233 struct outgoing_helper oh; 07234 07235 memset(&oh, 0, sizeof(oh)); 07236 oh.vars = vars; 07237 oh.account = account; 07238 07239 if (locked_channel) 07240 *locked_channel = NULL; 07241 if (ast_strlen_zero(app)) { 07242 res = -1; 07243 goto outgoing_app_cleanup; 07244 } 07245 if (sync) { 07246 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07247 if (chan) { 07248 ast_set_variables(chan, vars); 07249 if (account) 07250 ast_cdr_setaccount(chan, account); 07251 if (chan->_state == AST_STATE_UP) { 07252 res = 0; 07253 ast_verb(4, "Channel %s was answered.\n", chan->name); 07254 tmp = ast_calloc(1, sizeof(*tmp)); 07255 if (!tmp) 07256 res = -1; 07257 else { 07258 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 07259 if (appdata) 07260 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 07261 tmp->chan = chan; 07262 if (sync > 1) { 07263 if (locked_channel) 07264 ast_channel_unlock(chan); 07265 ast_pbx_run_app(tmp); 07266 } else { 07267 if (locked_channel) 07268 ast_channel_lock(chan); 07269 if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 07270 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 07271 ast_free(tmp); 07272 if (locked_channel) 07273 ast_channel_unlock(chan); 07274 ast_hangup(chan); 07275 res = -1; 07276 } else { 07277 if (locked_channel) 07278 *locked_channel = chan; 07279 } 07280 } 07281 } 07282 } else { 07283 ast_verb(4, "Channel %s was never answered.\n", chan->name); 07284 if (chan->cdr) { /* update the cdr */ 07285 /* here we update the status of the call, which sould be busy. 07286 * if that fails then we set the status to failed */ 07287 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 07288 ast_cdr_failed(chan->cdr); 07289 } 07290 ast_hangup(chan); 07291 } 07292 } 07293 07294 if (res < 0) { /* the call failed for some reason */ 07295 if (*reason == 0) { /* if the call failed (not busy or no answer) 07296 * update the cdr with the failed message */ 07297 cdr_res = ast_pbx_outgoing_cdr_failed(); 07298 if (cdr_res != 0) { 07299 res = cdr_res; 07300 goto outgoing_app_cleanup; 07301 } 07302 } 07303 } 07304 07305 } else { 07306 struct async_stat *as; 07307 if (!(as = ast_calloc(1, sizeof(*as)))) { 07308 res = -1; 07309 goto outgoing_app_cleanup; 07310 } 07311 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07312 if (!chan) { 07313 ast_free(as); 07314 res = -1; 07315 goto outgoing_app_cleanup; 07316 } 07317 as->chan = chan; 07318 ast_copy_string(as->app, app, sizeof(as->app)); 07319 if (appdata) 07320 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 07321 as->timeout = timeout; 07322 ast_set_variables(chan, vars); 07323 if (account) 07324 ast_cdr_setaccount(chan, account); 07325 /* Start a new thread, and get something handling this channel. */ 07326 if (locked_channel) 07327 ast_channel_lock(chan); 07328 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 07329 ast_log(LOG_WARNING, "Failed to start async wait\n"); 07330 ast_free(as); 07331 if (locked_channel) 07332 ast_channel_unlock(chan); 07333 ast_hangup(chan); 07334 res = -1; 07335 goto outgoing_app_cleanup; 07336 } else { 07337 if (locked_channel) 07338 *locked_channel = chan; 07339 } 07340 res = 0; 07341 } 07342 outgoing_app_cleanup: 07343 ast_variables_destroy(vars); 07344 return res; 07345 }
int ast_pbx_outgoing_exten | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int | timeout, | |||
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
int * | reason, | |||
int | sync, | |||
const char * | cid_num, | |||
const char * | cid_name, | |||
struct ast_variable * | vars, | |||
const char * | account, | |||
struct ast_channel ** | locked_channel | |||
) |
Synchronously or asynchronously make an outbound call and send it to a particular extension
Definition at line 7062 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_exists_extension(), ast_free, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create_detached, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verb, async_wait(), ast_channel::cdr, chan, outgoing_helper::cid_name, outgoing_helper::cid_num, ast_channel::context, outgoing_helper::context, outgoing_helper::exten, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, ast_channel::name, outgoing_helper::parent_channel, pbx_builtin_setvar_helper(), outgoing_helper::priority, set_ext_pri(), and outgoing_helper::vars.
Referenced by action_originate(), attempt_thread(), fast_originate(), and orig_exten().
07063 { 07064 struct ast_channel *chan; 07065 struct async_stat *as; 07066 int res = -1, cdr_res = -1; 07067 struct outgoing_helper oh; 07068 07069 if (sync) { 07070 oh.context = context; 07071 oh.exten = exten; 07072 oh.priority = priority; 07073 oh.cid_num = cid_num; 07074 oh.cid_name = cid_name; 07075 oh.account = account; 07076 oh.vars = vars; 07077 oh.parent_channel = NULL; 07078 07079 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 07080 if (channel) { 07081 *channel = chan; 07082 if (chan) 07083 ast_channel_lock(chan); 07084 } 07085 if (chan) { 07086 if (chan->_state == AST_STATE_UP) { 07087 res = 0; 07088 ast_verb(4, "Channel %s was answered.\n", chan->name); 07089 07090 if (sync > 1) { 07091 if (channel) 07092 ast_channel_unlock(chan); 07093 if (ast_pbx_run(chan)) { 07094 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 07095 if (channel) 07096 *channel = NULL; 07097 ast_hangup(chan); 07098 chan = NULL; 07099 res = -1; 07100 } 07101 } else { 07102 if (ast_pbx_start(chan)) { 07103 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 07104 if (channel) { 07105 *channel = NULL; 07106 ast_channel_unlock(chan); 07107 } 07108 ast_hangup(chan); 07109 res = -1; 07110 } 07111 chan = NULL; 07112 } 07113 } else { 07114 ast_verb(4, "Channel %s was never answered.\n", chan->name); 07115 07116 if (chan->cdr) { /* update the cdr */ 07117 /* here we update the status of the call, which sould be busy. 07118 * if that fails then we set the status to failed */ 07119 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 07120 ast_cdr_failed(chan->cdr); 07121 } 07122 07123 if (channel) { 07124 *channel = NULL; 07125 ast_channel_unlock(chan); 07126 } 07127 ast_hangup(chan); 07128 chan = NULL; 07129 } 07130 } 07131 07132 if (res < 0) { /* the call failed for some reason */ 07133 if (*reason == 0) { /* if the call failed (not busy or no answer) 07134 * update the cdr with the failed message */ 07135 cdr_res = ast_pbx_outgoing_cdr_failed(); 07136 if (cdr_res != 0) { 07137 res = cdr_res; 07138 goto outgoing_exten_cleanup; 07139 } 07140 } 07141 07142 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 07143 /* check if "failed" exists */ 07144 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 07145 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed"); 07146 if (chan) { 07147 char failed_reason[4] = ""; 07148 if (!ast_strlen_zero(context)) 07149 ast_copy_string(chan->context, context, sizeof(chan->context)); 07150 set_ext_pri(chan, "failed", 1); 07151 ast_set_variables(chan, vars); 07152 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason); 07153 pbx_builtin_setvar_helper(chan, "REASON", failed_reason); 07154 if (account) 07155 ast_cdr_setaccount(chan, account); 07156 if (ast_pbx_run(chan)) { 07157 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 07158 ast_hangup(chan); 07159 } 07160 chan = NULL; 07161 } 07162 } 07163 } 07164 } else { 07165 if (!(as = ast_calloc(1, sizeof(*as)))) { 07166 res = -1; 07167 goto outgoing_exten_cleanup; 07168 } 07169 chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name); 07170 if (channel) { 07171 *channel = chan; 07172 if (chan) 07173 ast_channel_lock(chan); 07174 } 07175 if (!chan) { 07176 ast_free(as); 07177 res = -1; 07178 goto outgoing_exten_cleanup; 07179 } 07180 as->chan = chan; 07181 ast_copy_string(as->context, context, sizeof(as->context)); 07182 set_ext_pri(as->chan, exten, priority); 07183 as->timeout = timeout; 07184 ast_set_variables(chan, vars); 07185 if (account) 07186 ast_cdr_setaccount(chan, account); 07187 if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) { 07188 ast_log(LOG_WARNING, "Failed to start async wait\n"); 07189 ast_free(as); 07190 if (channel) { 07191 *channel = NULL; 07192 ast_channel_unlock(chan); 07193 } 07194 ast_hangup(chan); 07195 res = -1; 07196 goto outgoing_exten_cleanup; 07197 } 07198 res = 0; 07199 } 07200 outgoing_exten_cleanup: 07201 ast_variables_destroy(vars); 07202 return res; 07203 }
enum ast_pbx_result ast_pbx_run | ( | struct ast_channel * | c | ) |
Execute the PBX in the current thread.
c | channel to run the pbx on |
Zero | on success | |
non-zero | on failure |
Definition at line 4021 of file pbx.c.
References ast_pbx_run_args().
Referenced by ast_pbx_outgoing_exten(), async_wait(), do_idle_thread(), mgcp_ss(), skinny_newcall(), ss_thread(), and unistim_ss().
04022 { 04023 return ast_pbx_run_args(c, NULL); 04024 }
enum ast_pbx_result ast_pbx_run_args | ( | struct ast_channel * | c, | |
struct ast_pbx_args * | args | |||
) |
Execute the PBX in the current thread.
c | channel to run the pbx on | |
args | options for the pbx |
Zero | on success | |
non-zero | on failure |
Definition at line 4006 of file pbx.c.
References __ast_pbx_run(), AST_PBX_CALL_LIMIT, AST_PBX_SUCCESS, decrease_call_count(), and increase_call_count().
Referenced by ast_pbx_run(), dial_exec_full(), and handle_gosub().
04007 { 04008 enum ast_pbx_result res = AST_PBX_SUCCESS; 04009 04010 if (increase_call_count(c)) { 04011 return AST_PBX_CALL_LIMIT; 04012 } 04013 04014 res = __ast_pbx_run(c, args); 04015 04016 decrease_call_count(); 04017 04018 return res; 04019 }
enum ast_pbx_result ast_pbx_start | ( | struct ast_channel * | c | ) |
Create a new thread and start the PBX.
c | channel to start the pbx on |
Zero | on success | |
non-zero | on failure |
Definition at line 3984 of file pbx.c.
References ast_log(), AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, decrease_call_count(), increase_call_count(), LOG_WARNING, and pbx_thread().
Referenced by __oh323_new(), alsa_new(), ast_async_goto(), ast_bridge_call_thread(), ast_iax2_new(), ast_pbx_outgoing_exten(), bridge_exec(), check_goto_on_transfer(), console_new(), dahdi_new(), dial_exec_full(), do_parking_thread(), gtalk_new(), gtalk_newcall(), handle_request_invite(), jingle_new(), jingle_newcall(), local_call(), mgcp_new(), nbs_new(), oss_new(), pbx_start_chan(), phone_new(), rpt_call(), sip_new(), skinny_new(), unistim_new(), and usbradio_new().
03985 { 03986 pthread_t t; 03987 03988 if (!c) { 03989 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 03990 return AST_PBX_FAILED; 03991 } 03992 03993 if (increase_call_count(c)) 03994 return AST_PBX_CALL_LIMIT; 03995 03996 /* Start a new thread, and get something handling this channel. */ 03997 if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) { 03998 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 03999 decrease_call_count(); 04000 return AST_PBX_FAILED; 04001 } 04002 04003 return AST_PBX_SUCCESS; 04004 }
int ast_processed_calls | ( | void | ) |
Retrieve the total number of calls processed through the PBX since last restart.
Definition at line 4031 of file pbx.c.
Referenced by handle_chanlist(), and handle_showcalls().
04032 { 04033 return totalcalls; 04034 }
int ast_rdlock_context | ( | struct ast_context * | con | ) |
Read locks a given context.
con | context to lock |
0 | on success | |
-1 | on failure |
Definition at line 8426 of file pbx.c.
References ast_rwlock_rdlock(), and ast_context::lock.
Referenced by _macro_exec(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_cli_dialplan_save(), lookup_c_ip(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
08427 { 08428 return ast_rwlock_rdlock(&con->lock); 08429 }
int ast_rdlock_contexts | ( | void | ) |
Read locks the context list.
0 | on success | |
-1 | on error |
Definition at line 8408 of file pbx.c.
References ast_rwlock_rdlock(), and conlock.
Referenced by _macro_exec(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_dialplan_helper(), and unreference_cached_app().
08409 { 08410 return ast_rwlock_rdlock(&conlock); 08411 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
Definition at line 4506 of file pbx.c.
References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_switch::list, LOG_WARNING, and ast_switch::name.
Referenced by load_module().
04507 { 04508 struct ast_switch *tmp; 04509 04510 AST_RWLIST_WRLOCK(&switches); 04511 AST_RWLIST_TRAVERSE(&switches, tmp, list) { 04512 if (!strcasecmp(tmp->name, sw->name)) { 04513 AST_RWLIST_UNLOCK(&switches); 04514 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 04515 return -1; 04516 } 04517 } 04518 AST_RWLIST_INSERT_TAIL(&switches, sw, list); 04519 AST_RWLIST_UNLOCK(&switches); 04520 04521 return 0; 04522 }
int ast_spawn_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | callerid, | |||
int * | found, | |||
int | combined_find_spawn | |||
) |
Launch a new extension (i.e. new stack).
c | not important | |
context | which context to generate the extension within | |
exten | new extension to add | |
priority | priority of new extension | |
callerid | callerid of extension | |
found | ||
combined_find_spawn |
0 | on success | |
-1 | on failure. |
Definition at line 3614 of file pbx.c.
References E_SPAWN, and pbx_extension_helper().
Referenced by __ast_pbx_run(), _macro_exec(), ast_bridge_call(), dial_exec_full(), and loopback_exec().
03615 { 03616 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn); 03617 }
int ast_unlock_context | ( | struct ast_context * | con | ) |
Unlocks | the given context |
con | context to unlock |
0 | on success | |
-1 | on failure |
Definition at line 8431 of file pbx.c.
References ast_rwlock_unlock(), and ast_context::lock.
Referenced by __ast_context_destroy(), _macro_exec(), ast_add_extension2_lockopt(), ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_extension_callerid2(), ast_context_remove_ignorepat2(), ast_context_remove_include2(), ast_context_remove_switch2(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), dundi_precache_full(), find_matching_endwhile(), handle_cli_dialplan_save(), lookup_c_ip(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
08432 { 08433 return ast_rwlock_unlock(&con->lock); 08434 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 8413 of file pbx.c.
References ast_rwlock_unlock(), and conlock.
Referenced by _macro_exec(), ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_destroy(), ast_context_find(), ast_context_find_or_create(), ast_context_lockmacro(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), ast_context_remove_switch(), ast_context_unlockmacro(), ast_hint_extension(), ast_merge_contexts_and_delete(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), handle_cli_dialplan_save(), handle_statechange(), manager_show_dialplan_helper(), pbx_extension_helper(), show_dialplan_helper(), and unreference_cached_app().
08414 { 08415 return ast_rwlock_unlock(&conlock); 08416 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 4524 of file pbx.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and ast_switch::list.
Referenced by __unload_module(), and unload_module().
04525 { 04526 AST_RWLIST_WRLOCK(&switches); 04527 AST_RWLIST_REMOVE(&switches, sw, list); 04528 AST_RWLIST_UNLOCK(&switches); 04529 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | priority | |||
) |
Definition at line 8545 of file pbx.c.
References exten, and ast_context::root.
Referenced by complete_dialplan_remove_extension(), dundi_precache_full(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
08547 { 08548 if (!exten) 08549 return con ? con->root : NULL; 08550 else 08551 return exten->next; 08552 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) |
Definition at line 8578 of file pbx.c.
References ast_context::ignorepats, and ast_ignorepat::next.
Referenced by complete_dialplan_remove_ignorepat(), context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), lookup_c_ip(), manager_show_dialplan_helper(), and show_dialplan_helper().
08580 { 08581 if (!ip) 08582 return con ? con->ignorepats : NULL; 08583 else 08584 return ip->next; 08585 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) |
Definition at line 8569 of file pbx.c.
References ast_context::includes, and ast_include::next.
Referenced by ast_context_verify_includes(), complete_dialplan_remove_include(), context_merge_incls_swits_igps_other_registrars(), find_matching_priority(), handle_cli_dialplan_save(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper().
08571 { 08572 if (!inc) 08573 return con ? con->includes : NULL; 08574 else 08575 return inc->next; 08576 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) |
Definition at line 8554 of file pbx.c.
References ast_context::alts, AST_LIST_FIRST, AST_LIST_NEXT, and ast_sw::list.
Referenced by context_merge_incls_swits_igps_other_registrars(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().
08556 { 08557 if (!sw) 08558 return con ? AST_LIST_FIRST(&con->alts) : NULL; 08559 else 08560 return AST_LIST_NEXT(sw, list); 08561 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) |
Definition at line 8540 of file pbx.c.
References contexts, and ast_context::next.
Referenced by _macro_exec(), ast_context_find(), ast_context_lockmacro(), ast_context_unlockmacro(), complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), find_matching_endwhile(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), pbx_load_module(), show_dialplan_helper(), and unreference_cached_app().
struct ast_exten* ast_walk_extension_priorities | ( | struct ast_exten * | exten, | |
struct ast_exten * | priority | |||
) |
Definition at line 8563 of file pbx.c.
References exten, and ast_exten::priority.
Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().
int ast_wrlock_context | ( | struct ast_context * | con | ) |
Write locks a given context.
con | context to lock |
0 | on success | |
-1 | on failure |
Definition at line 8421 of file pbx.c.
References ast_rwlock_wrlock(), and ast_context::lock.
Referenced by __ast_context_destroy(), ast_add_extension2_lockopt(), ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_remove_extension_callerid2(), ast_context_remove_ignorepat2(), ast_context_remove_include2(), and ast_context_remove_switch2().
08422 { 08423 return ast_rwlock_wrlock(&con->lock); 08424 }
int ast_wrlock_contexts | ( | void | ) |
Write locks the context list.
0 | on success | |
-1 | on error |
Definition at line 8400 of file pbx.c.
References ast_atomic_fetchadd_int(), ast_rwlock_wrlock(), and conlock.
Referenced by ast_context_destroy(), ast_context_find_or_create(), ast_merge_contexts_and_delete(), and complete_dialplan_remove_include().
08401 { 08402 int res = ast_rwlock_wrlock(&conlock); 08403 if (!res) 08404 ast_atomic_fetchadd_int(&conlock_wrlock_version, 1); 08405 return res; 08406 }
int ast_wrlock_contexts_version | ( | void | ) |
Definition at line 8392 of file pbx.c.
Referenced by ast_merge_contexts_and_delete().
08393 { 08394 return conlock_wrlock_version; 08395 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 8244 of file pbx.c.
References AST_LIST_REMOVE_HEAD, ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_var_delete(), ast_var_t::entries, globals, and globalslock.
Referenced by handle_cli_dialplan_reload(), and reload().
08245 { 08246 struct ast_var_t *vardata; 08247 08248 ast_rwlock_wrlock(&globalslock); 08249 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 08250 ast_var_delete(vardata); 08251 ast_rwlock_unlock(&globalslock); 08252 }
const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
const char * | name | |||
) |
This function will return a pointer to the buffer inside the channel variable. This value should only be accessed with the channel locked. If the value needs to be kept around, it should be done by using the following thread-safe code:
const char *var; ast_channel_lock(chan); if ((var = pbx_builtin_getvar_helper(chan, "MYVAR"))) { var = ast_strdupa(var); } ast_channel_unlock(chan);
Definition at line 8014 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_var_name(), ast_var_value(), chan, globals, and globalslock.
Referenced by _macro_exec(), _while_exec(), agent_hangup(), agent_read(), agentmonitoroutgoing_exec(), array(), ast_bridge_call(), ast_call_forward(), ast_eivr_getvariable(), ast_feature_interpret(), ast_monitor_stop(), builtin_automixmonitor(), builtin_automonitor(), check_goto_on_transfer(), common_exec(), conf_exec(), conf_run(), dahdi_call(), dahdi_hangup(), dial_exec_full(), do_forward(), do_timelimit(), dundi_exec(), dundi_helper(), get_also_info(), get_index(), get_refer_info(), global_read(), hash_read(), iax2_exec(), import_ch(), leave_voicemail(), local_hangup(), local_read(), login_exec(), macro_fixup(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), oh323_call(), oh323_hangup(), park_call_full(), park_space_reserve(), pickup_by_mark(), queue_exec(), real_ctx(), retrydial_exec(), ring_entry(), run_agi(), set_config_flags(), set_local_info(), sip_addheader(), sla_trunk_exec(), speech_background(), try_suggested_sip_codec(), and update_bridge_vars().
08015 { 08016 struct ast_var_t *variables; 08017 const char *ret = NULL; 08018 int i; 08019 struct varshead *places[2] = { NULL, &globals }; 08020 08021 if (!name) 08022 return NULL; 08023 08024 if (chan) { 08025 ast_channel_lock(chan); 08026 places[0] = &chan->varshead; 08027 } 08028 08029 for (i = 0; i < 2; i++) { 08030 if (!places[i]) 08031 continue; 08032 if (places[i] == &globals) 08033 ast_rwlock_rdlock(&globalslock); 08034 AST_LIST_TRAVERSE(places[i], variables, entries) { 08035 if (!strcmp(name, ast_var_name(variables))) { 08036 ret = ast_var_value(variables); 08037 break; 08038 } 08039 } 08040 if (places[i] == &globals) 08041 ast_rwlock_unlock(&globalslock); 08042 if (ret) 08043 break; 08044 } 08045 08046 if (chan) 08047 ast_channel_unlock(chan); 08048 08049 return ret; 08050 }
void pbx_builtin_pushvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Definition at line 8052 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, ast_log(), ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_strdupa, ast_var_assign(), ast_verb, chan, globals, globalslock, and LOG_WARNING.
Referenced by acf_odbc_read(), acf_odbc_write(), and frame_set_var().
08053 { 08054 struct ast_var_t *newvariable; 08055 struct varshead *headp; 08056 08057 if (name[strlen(name)-1] == ')') { 08058 char *function = ast_strdupa(name); 08059 08060 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 08061 ast_func_write(chan, function, value); 08062 return; 08063 } 08064 08065 if (chan) { 08066 ast_channel_lock(chan); 08067 headp = &chan->varshead; 08068 } else { 08069 ast_rwlock_wrlock(&globalslock); 08070 headp = &globals; 08071 } 08072 08073 if (value) { 08074 if (headp == &globals) 08075 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 08076 newvariable = ast_var_assign(name, value); 08077 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 08078 } 08079 08080 if (chan) 08081 ast_channel_unlock(chan); 08082 else 08083 ast_rwlock_unlock(&globalslock); 08084 }
int pbx_builtin_raise_exception | ( | struct ast_channel * | chan, | |
void * | data | |||
) |
Definition at line 2498 of file pbx.c.
References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_alloc(), ast_channel_datastore_find(), ast_channel_datastore_free(), ast_free, ast_string_field_init, ast_string_field_set, chan, ast_channel::context, context, ast_datastore::data, exception_store_info, ast_channel::exten, exten, ast_channel::priority, pbx_exception::priority, and set_ext_pri().
Referenced by __ast_pbx_run().
02499 { 02500 const char *reason = vreason; 02501 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); 02502 struct pbx_exception *exception = NULL; 02503 02504 if (!ds) { 02505 ds = ast_channel_datastore_alloc(&exception_store_info, NULL); 02506 if (!ds) 02507 return -1; 02508 exception = ast_calloc(1, sizeof(struct pbx_exception)); 02509 if (!exception) { 02510 ast_channel_datastore_free(ds); 02511 return -1; 02512 } 02513 if (ast_string_field_init(exception, 128)) { 02514 ast_free(exception); 02515 ast_channel_datastore_free(ds); 02516 return -1; 02517 } 02518 ds->data = exception; 02519 ast_channel_datastore_add(chan, ds); 02520 } else 02521 exception = ds->data; 02522 02523 ast_string_field_set(exception, reason, reason); 02524 ast_string_field_set(exception, context, chan->context); 02525 ast_string_field_set(exception, exten, chan->exten); 02526 exception->priority = chan->priority; 02527 set_ext_pri(chan, "e", 0); 02528 return 0; 02529 }
int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
struct ast_str ** | buf | |||
) |
Definition at line 7982 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_var_name(), ast_var_value(), buf, chan, ast_var_t::entries, LOG_ERROR, total, var, and ast_channel::varshead.
Referenced by dumpchan_exec(), handle_showchan(), and vars2manager().
07983 { 07984 struct ast_var_t *variables; 07985 const char *var, *val; 07986 int total = 0; 07987 07988 if (!chan) 07989 return 0; 07990 07991 (*buf)->used = 0; 07992 (*buf)->str[0] = '\0'; 07993 07994 ast_channel_lock(chan); 07995 07996 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 07997 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables)) 07998 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 07999 ) { 08000 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) { 08001 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 08002 break; 08003 } else 08004 total++; 08005 } else 08006 break; 08007 } 08008 08009 ast_channel_unlock(chan); 08010 08011 return total; 08012 }
int pbx_builtin_setvar | ( | struct ast_channel * | chan, | |
void * | data | |||
) |
void pbx_builtin_setvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Definition at line 8086 of file pbx.c.
References ast_channel_lock, ast_channel_unlock, ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE, AST_LIST_TRAVERSE, ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verb, chan, EVENT_FLAG_DIALPLAN, globals, globalslock, manager_event, ast_channel::name, and ast_channel::uniqueid.
Referenced by __oh323_new(), _macro_exec(), _while_exec(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), action_setvar(), agi_exec_full(), aji_status_exec(), aqm_exec(), array(), ast_bridge_call(), ast_eivr_setvariable(), ast_feature_request_and_dial(), ast_iax2_new(), ast_monitor_start(), ast_pbx_outgoing_exten(), ast_set_variables(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), cb_events(), chanavail_exec(), channel_spy(), conf_run(), controlplayback_exec(), count_exec(), dahdi_handle_dtmfup(), dahdi_new(), dial_exec_full(), do_parking_thread(), do_waiting(), end_bridge_callback(), export_aoc_vars(), export_ch(), frame_set_var(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), handle_request_bye(), handle_request_refer(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), hash_read(), hash_write(), isAnsweringMachine(), leave_voicemail(), local_hangup(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), park_exec(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), read_exec(), readexten_exec(), readfile_exec(), record_exec(), return_exec(), rotate_file(), rqm_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_agentbycallerid(), set_queue_result(), sip_addheader(), sip_hangup(), sip_new(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), socket_process(), speech_create(), ss_thread(), start_monitor_exec(), system_exec_helper(), transfer_exec(), transmit(), tryexec_exec(), update_bridge_vars(), update_qe_rule(), upqm_exec(), vm_box_exists(), vm_exec(), vmauthenticate(), waituntil_exec(), and zapateller_exec().
08087 { 08088 struct ast_var_t *newvariable; 08089 struct varshead *headp; 08090 const char *nametail = name; 08091 08092 if (name[strlen(name) - 1] == ')') { 08093 char *function = ast_strdupa(name); 08094 08095 ast_func_write(chan, function, value); 08096 return; 08097 } 08098 08099 if (chan) { 08100 ast_channel_lock(chan); 08101 headp = &chan->varshead; 08102 } else { 08103 ast_rwlock_wrlock(&globalslock); 08104 headp = &globals; 08105 } 08106 08107 /* For comparison purposes, we have to strip leading underscores */ 08108 if (*nametail == '_') { 08109 nametail++; 08110 if (*nametail == '_') 08111 nametail++; 08112 } 08113 08114 AST_LIST_TRAVERSE (headp, newvariable, entries) { 08115 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) { 08116 /* there is already such a variable, delete it */ 08117 AST_LIST_REMOVE(headp, newvariable, entries); 08118 ast_var_delete(newvariable); 08119 break; 08120 } 08121 } 08122 08123 if (value) { 08124 if (headp == &globals) 08125 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); 08126 newvariable = ast_var_assign(name, value); 08127 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 08128 manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 08129 "Channel: %s\r\n" 08130 "Variable: %s\r\n" 08131 "Value: %s\r\n" 08132 "Uniqueid: %s\r\n", 08133 chan ? chan->name : "none", name, value, 08134 chan ? chan->uniqueid : "none"); 08135 } 08136 08137 if (chan) 08138 ast_channel_unlock(chan); 08139 else 08140 ast_rwlock_unlock(&globalslock); 08141 }
int pbx_builtin_setvar_multiple | ( | struct ast_channel * | chan, | |
void * | data | |||
) |
int pbx_checkcondition | ( | const char * | condition | ) |
Evaluate a condition.
0 | if the condition is NULL or of zero length | |
int | If the string is an integer, the integer representation of the integer is returned | |
1 | Any other non-empty string |
Definition at line 8254 of file pbx.c.
References ast_strlen_zero().
Referenced by _macro_exec(), _while_exec(), acf_if(), execif_exec(), gosubif_exec(), macroif_exec(), and pbx_builtin_gotoif().
08255 { 08256 if (ast_strlen_zero(condition)) /* NULL or empty strings are false */ 08257 return 0; 08258 else if (*condition >= '0' && *condition <= '9') /* Numbers are evaluated for truth */ 08259 return atoi(condition); 08260 else /* Strings are true */ 08261 return 1; 08262 }
int pbx_exec | ( | struct ast_channel * | c, | |
struct ast_app * | app, | |||
void * | data | |||
) |
Execute an application.
c | channel to execute on | |
app | which app to execute | |
data | the data passed into the app |
c | Channel |
app | Application |
data | Data for execution |
Definition at line 925 of file pbx.c.
References __ast_module_user_add(), __ast_module_user_remove(), app, ast_channel::appl, ast_cdr_setapp(), ast_check_hangup(), ast_log(), ast_strlen_zero(), ast_channel::cdr, ast_channel::data, LOG_WARNING, ast_channel::name, and S_OR.
Referenced by answer_exec_run(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), milliwatt_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), and tryexec_exec().
00928 { 00929 int res; 00930 struct ast_module_user *u = NULL; 00931 const char *saved_c_appl; 00932 const char *saved_c_data; 00933 00934 if (c->cdr && !ast_check_hangup(c)) 00935 ast_cdr_setapp(c->cdr, app->name, data); 00936 00937 /* save channel values */ 00938 saved_c_appl= c->appl; 00939 saved_c_data= c->data; 00940 00941 c->appl = app->name; 00942 c->data = data; 00943 if (app->module) 00944 u = __ast_module_user_add(app->module, c); 00945 if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) && 00946 strchr(data, '|') && !strchr(data, ',')) { 00947 ast_log(LOG_WARNING, "The application delimiter is now the comma, not " 00948 "the pipe. Did you forget to convert your dialplan? (%s(%s))\n", 00949 app->name, (char *) data); 00950 } 00951 res = app->execute(c, S_OR(data, "")); 00952 if (app->module && u) 00953 __ast_module_user_remove(app->module, u); 00954 /* restore channel values */ 00955 c->appl = saved_c_appl; 00956 c->data = saved_c_data; 00957 return res; 00958 }
struct ast_exten* pbx_find_extension | ( | struct ast_channel * | chan, | |
struct ast_context * | bypass, | |||
struct pbx_find_info * | q, | |||
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | label, | |||
const char * | callerid, | |||
enum ext_match_t | action | |||
) |
Definition at line 2036 of file pbx.c.
References ast_context::alts, ast_autoservice_start(), ast_autoservice_stop(), ast_hashtab_lookup(), AST_LIST_TRAVERSE, ast_log(), AST_PBX_MAX_STACK, ast_str_thread_get(), ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), ast_switch::canmatch, scoreboard::canmatch_exten, chan, contexts_table, create_match_char_tree(), ast_sw::data, pbx_find_info::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_sw::eval, ast_switch::exists, ast_exten::exten, scoreboard::exten, extension_match_core(), pbx_find_info::foundcontext, include_valid(), ast_context::includes, pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, ast_str::len, LOG_DEBUG, log_match_char_tree(), LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, ast_sw::name, ast_context::name, fake_context::name, new_find_extension(), ast_include::next, scoreboard::node, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), ast_exten::priority, ast_include::rname, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, ast_str::str, switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().
Referenced by ast_hint_extension(), ast_merge_contexts_and_delete(), pbx_extension_helper(), pbx_find_extension(), and register_peer_exten().
02040 { 02041 int x, res; 02042 struct ast_context *tmp = NULL; 02043 struct ast_exten *e = NULL, *eroot = NULL; 02044 struct ast_include *i = NULL; 02045 struct ast_sw *sw = NULL; 02046 struct ast_exten pattern = {NULL, }; 02047 struct scoreboard score = {0, }; 02048 struct ast_str *tmpdata = NULL; 02049 02050 pattern.label = label; 02051 pattern.priority = priority; 02052 #ifdef NEED_DEBUG_HERE 02053 ast_log(LOG_NOTICE,"Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int)action); 02054 #endif 02055 /* Initialize status if appropriate */ 02056 if (q->stacklen == 0) { 02057 q->status = STATUS_NO_CONTEXT; 02058 q->swo = NULL; 02059 q->data = NULL; 02060 q->foundcontext = NULL; 02061 } else if (q->stacklen >= AST_PBX_MAX_STACK) { 02062 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n"); 02063 return NULL; 02064 } 02065 02066 /* Check first to see if we've already been checked */ 02067 for (x = 0; x < q->stacklen; x++) { 02068 if (!strcasecmp(q->incstack[x], context)) 02069 return NULL; 02070 } 02071 02072 if (bypass) /* bypass means we only look there */ 02073 tmp = bypass; 02074 else { /* look in contexts */ 02075 struct fake_context item; 02076 strncpy(item.name,context,256); 02077 tmp = ast_hashtab_lookup(contexts_table,&item); 02078 #ifdef NOTNOW 02079 tmp = NULL; 02080 while ((tmp = ast_walk_contexts(tmp)) ) { 02081 if (!strcmp(tmp->name, context)) 02082 break; 02083 } 02084 #endif 02085 if (!tmp) 02086 return NULL; 02087 02088 } 02089 02090 if (q->status < STATUS_NO_EXTENSION) 02091 q->status = STATUS_NO_EXTENSION; 02092 02093 /* Do a search for matching extension */ 02094 02095 eroot = NULL; 02096 score.total_specificity = 0; 02097 score.exten = 0; 02098 score.total_length = 0; 02099 if (!tmp->pattern_tree && tmp->root_table) 02100 { 02101 create_match_char_tree(tmp); 02102 #ifdef NEED_DEBUG 02103 ast_log(LOG_DEBUG,"Tree Created in context %s:\n", context); 02104 log_match_char_tree(tmp->pattern_tree," "); 02105 #endif 02106 } 02107 #ifdef NEED_DEBUG 02108 ast_log(LOG_NOTICE,"The Trie we are searching in:\n"); 02109 log_match_char_tree(tmp->pattern_tree, ":: "); 02110 #endif 02111 02112 if (extenpatternmatchnew) { 02113 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action); 02114 eroot = score.exten; 02115 02116 if (score.last_char == '!' && action == E_MATCHMORE) { 02117 /* We match an extension ending in '!'. 02118 * The decision in this case is final and is NULL (no match). 02119 */ 02120 #ifdef NEED_DEBUG_HERE 02121 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n"); 02122 #endif 02123 return NULL; 02124 } 02125 02126 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) { 02127 q->status = STATUS_SUCCESS; 02128 #ifdef NEED_DEBUG_HERE 02129 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten); 02130 #endif 02131 return score.canmatch_exten; 02132 } 02133 02134 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) { 02135 if (score.node) { 02136 struct ast_exten *z = trie_find_next_match(score.node); 02137 if (z) { 02138 #ifdef NEED_DEBUG_HERE 02139 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten); 02140 #endif 02141 } else { 02142 if (score.canmatch_exten) { 02143 #ifdef NEED_DEBUG_HERE 02144 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten); 02145 #endif 02146 return score.canmatch_exten; 02147 } else { 02148 #ifdef NEED_DEBUG_HERE 02149 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n"); 02150 #endif 02151 } 02152 } 02153 return z; 02154 } 02155 #ifdef NEED_DEBUG_HERE 02156 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE NULL (no next_match)\n"); 02157 #endif 02158 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */ 02159 } 02160 02161 if (eroot) { 02162 /* found entry, now look for the right priority */ 02163 if (q->status < STATUS_NO_PRIORITY) 02164 q->status = STATUS_NO_PRIORITY; 02165 e = NULL; 02166 if (action == E_FINDLABEL && label ) { 02167 if (q->status < STATUS_NO_LABEL) 02168 q->status = STATUS_NO_LABEL; 02169 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02170 } else { 02171 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02172 } 02173 if (e) { /* found a valid match */ 02174 q->status = STATUS_SUCCESS; 02175 q->foundcontext = context; 02176 #ifdef NEED_DEBUG_HERE 02177 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten); 02178 #endif 02179 return e; 02180 } 02181 } 02182 } else { /* the old/current default exten pattern match algorithm */ 02183 02184 /* scan the list trying to match extension and CID */ 02185 eroot = NULL; 02186 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) { 02187 int match = extension_match_core(eroot->exten, exten, action); 02188 /* 0 on fail, 1 on match, 2 on earlymatch */ 02189 02190 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid))) 02191 continue; /* keep trying */ 02192 if (match == 2 && action == E_MATCHMORE) { 02193 /* We match an extension ending in '!'. 02194 * The decision in this case is final and is NULL (no match). 02195 */ 02196 return NULL; 02197 } 02198 /* found entry, now look for the right priority */ 02199 if (q->status < STATUS_NO_PRIORITY) 02200 q->status = STATUS_NO_PRIORITY; 02201 e = NULL; 02202 if (action == E_FINDLABEL && label ) { 02203 if (q->status < STATUS_NO_LABEL) 02204 q->status = STATUS_NO_LABEL; 02205 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern); 02206 } else { 02207 e = ast_hashtab_lookup(eroot->peer_table, &pattern); 02208 } 02209 #ifdef NOTNOW 02210 while ( (e = ast_walk_extension_priorities(eroot, e)) ) { 02211 /* Match label or priority */ 02212 if (action == E_FINDLABEL) { 02213 if (q->status < STATUS_NO_LABEL) 02214 q->status = STATUS_NO_LABEL; 02215 if (label && e->label && !strcmp(label, e->label)) 02216 break; /* found it */ 02217 } else if (e->priority == priority) { 02218 break; /* found it */ 02219 } /* else keep searching */ 02220 } 02221 #endif 02222 if (e) { /* found a valid match */ 02223 q->status = STATUS_SUCCESS; 02224 q->foundcontext = context; 02225 return e; 02226 } 02227 } 02228 } 02229 02230 02231 /* Check alternative switches */ 02232 AST_LIST_TRAVERSE(&tmp->alts, sw, list) { 02233 struct ast_switch *asw = pbx_findswitch(sw->name); 02234 ast_switch_f *aswf = NULL; 02235 char *datap; 02236 02237 if (!asw) { 02238 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); 02239 continue; 02240 } 02241 /* Substitute variables now */ 02242 02243 if (sw->eval) { 02244 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) { 02245 ast_log(LOG_WARNING, "Can't evaluate switch?!"); 02246 continue; 02247 } 02248 pbx_substitute_variables_helper(chan, sw->data, tmpdata->str, tmpdata->len); 02249 } 02250 02251 /* equivalent of extension_match_core() at the switch level */ 02252 if (action == E_CANMATCH) 02253 aswf = asw->canmatch; 02254 else if (action == E_MATCHMORE) 02255 aswf = asw->matchmore; 02256 else /* action == E_MATCH */ 02257 aswf = asw->exists; 02258 datap = sw->eval ? tmpdata->str : sw->data; 02259 if (!aswf) 02260 res = 0; 02261 else { 02262 if (chan) 02263 ast_autoservice_start(chan); 02264 res = aswf(chan, context, exten, priority, callerid, datap); 02265 if (chan) 02266 ast_autoservice_stop(chan); 02267 } 02268 if (res) { /* Got a match */ 02269 q->swo = asw; 02270 q->data = datap; 02271 q->foundcontext = context; 02272 /* XXX keep status = STATUS_NO_CONTEXT ? */ 02273 return NULL; 02274 } 02275 } 02276 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */ 02277 /* Now try any includes we have in this context */ 02278 for (i = tmp->includes; i; i = i->next) { 02279 if (include_valid(i)) { 02280 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) { 02281 #ifdef NEED_DEBUG_HERE 02282 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten); 02283 #endif 02284 return e; 02285 } 02286 if (q->swo) 02287 return NULL; 02288 } 02289 } 02290 return NULL; 02291 }
struct ast_app* pbx_findapp | ( | const char * | app | ) |
Look up an application.
app | name of the app |
Definition at line 966 of file pbx.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_app::list, and ast_app::name.
Referenced by answer_exec_run(), ast_bridge_call(), ast_pbx_run_app(), async_wait(), builtin_automixmonitor(), builtin_automonitor(), conf_run(), dial_exec_full(), dundi_exec(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_exec(), handle_gosub(), iax2_exec(), lua_pbx_exec(), milliwatt_exec(), page_exec(), pbx_builtin_execiftime(), pbx_extension_helper(), and tryexec_exec().
00967 { 00968 struct ast_app *tmp; 00969 00970 AST_RWLIST_RDLOCK(&apps); 00971 AST_RWLIST_TRAVERSE(&apps, tmp, list) { 00972 if (!strcasecmp(tmp->name, app)) 00973 break; 00974 } 00975 AST_RWLIST_UNLOCK(&apps); 00976 00977 return tmp; 00978 }
void pbx_retrieve_variable | ( | struct ast_channel * | c, | |
const char * | var, | |||
char ** | ret, | |||
char * | workspace, | |||
int | workspacelen, | |||
struct varshead * | headp | |||
) |
Support for Asterisk built-in variables in the dialplan.
Definition at line 2373 of file pbx.c.
References ARRAY_LEN, ast_channel_lock, ast_channel_unlock, ast_config_AST_SYSTEM_NAME, ast_copy_string(), ast_get_hint(), AST_LIST_TRAVERSE, ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_strdupa, ast_var_name(), ast_var_value(), ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_pres, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_channel::exten, globals, globalslock, ast_channel::hangupcause, ast_channel::name, parse_variable_name(), ast_channel::priority, s, substring(), and ast_channel::uniqueid.
Referenced by action_getvar(), handle_getvariable(), lua_get_variable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full().
02374 { 02375 const char not_found = '\0'; 02376 char *tmpvar; 02377 const char *s; /* the result */ 02378 int offset, length; 02379 int i, need_substring; 02380 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 02381 02382 if (c) { 02383 ast_channel_lock(c); 02384 places[0] = &c->varshead; 02385 } 02386 /* 02387 * Make a copy of var because parse_variable_name() modifies the string. 02388 * Then if called directly, we might need to run substring() on the result; 02389 * remember this for later in 'need_substring', 'offset' and 'length' 02390 */ 02391 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 02392 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 02393 02394 /* 02395 * Look first into predefined variables, then into variable lists. 02396 * Variable 's' points to the result, according to the following rules: 02397 * s == ¬_found (set at the beginning) means that we did not find a 02398 * matching variable and need to look into more places. 02399 * If s != ¬_found, s is a valid result string as follows: 02400 * s = NULL if the variable does not have a value; 02401 * you typically do this when looking for an unset predefined variable. 02402 * s = workspace if the result has been assembled there; 02403 * typically done when the result is built e.g. with an snprintf(), 02404 * so we don't need to do an additional copy. 02405 * s != workspace in case we have a string, that needs to be copied 02406 * (the ast_copy_string is done once for all at the end). 02407 * Typically done when the result is already available in some string. 02408 */ 02409 s = ¬_found; /* default value */ 02410 if (c) { /* This group requires a valid channel */ 02411 /* Names with common parts are looked up a piece at a time using strncmp. */ 02412 if (!strncmp(var, "CALL", 4)) { 02413 if (!strncmp(var + 4, "ING", 3)) { 02414 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 02415 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres); 02416 s = workspace; 02417 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 02418 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2); 02419 s = workspace; 02420 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 02421 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton); 02422 s = workspace; 02423 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 02424 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns); 02425 s = workspace; 02426 } 02427 } 02428 } else if (!strcmp(var, "HINT")) { 02429 s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL; 02430 } else if (!strcmp(var, "HINTNAME")) { 02431 s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL; 02432 } else if (!strcmp(var, "EXTEN")) { 02433 s = c->exten; 02434 } else if (!strcmp(var, "CONTEXT")) { 02435 s = c->context; 02436 } else if (!strcmp(var, "PRIORITY")) { 02437 snprintf(workspace, workspacelen, "%d", c->priority); 02438 s = workspace; 02439 } else if (!strcmp(var, "CHANNEL")) { 02440 s = c->name; 02441 } else if (!strcmp(var, "UNIQUEID")) { 02442 s = c->uniqueid; 02443 } else if (!strcmp(var, "HANGUPCAUSE")) { 02444 snprintf(workspace, workspacelen, "%d", c->hangupcause); 02445 s = workspace; 02446 } 02447 } 02448 if (s == ¬_found) { /* look for more */ 02449 if (!strcmp(var, "EPOCH")) { 02450 snprintf(workspace, workspacelen, "%u",(int)time(NULL)); 02451 s = workspace; 02452 } else if (!strcmp(var, "SYSTEMNAME")) { 02453 s = ast_config_AST_SYSTEM_NAME; 02454 } 02455 } 02456 /* if not found, look into chanvars or global vars */ 02457 for (i = 0; s == ¬_found && i < ARRAY_LEN(places); i++) { 02458 struct ast_var_t *variables; 02459 if (!places[i]) 02460 continue; 02461 if (places[i] == &globals) 02462 ast_rwlock_rdlock(&globalslock); 02463 AST_LIST_TRAVERSE(places[i], variables, entries) { 02464 if (!strcasecmp(ast_var_name(variables), var)) { 02465 s = ast_var_value(variables); 02466 break; 02467 } 02468 } 02469 if (places[i] == &globals) 02470 ast_rwlock_unlock(&globalslock); 02471 } 02472 if (s == ¬_found || s == NULL) 02473 *ret = NULL; 02474 else { 02475 if (s != workspace) 02476 ast_copy_string(workspace, s, workspacelen); 02477 *ret = workspace; 02478 if (need_substring) 02479 *ret = substring(*ret, offset, length, workspace, workspacelen); 02480 } 02481 02482 if (c) 02483 ast_channel_unlock(c); 02484 }
int pbx_set_autofallthrough | ( | int | newval | ) |
Set "autofallthrough" flag, if newval is <0, does not acutally set. If set to 1, sets to auto fall through. If newval set to 0, sets to no auto fall through (reads extension instead). Returns previous value.
Definition at line 4036 of file pbx.c.
Referenced by pbx_load_module().
04037 { 04038 int oldval = autofallthrough; 04039 autofallthrough = newval; 04040 return oldval; 04041 }
int pbx_set_extenpatternmatchnew | ( | int | newval | ) |
Set "extenpatternmatchnew" flag, if newval is <0, does not acutally set. If set to 1, sets to use the new Trie-based pattern matcher. If newval set to 0, sets to use the old linear-search algorithm. Returns previous value.
Definition at line 4043 of file pbx.c.
Referenced by handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().
04044 { 04045 int oldval = extenpatternmatchnew; 04046 extenpatternmatchnew = newval; 04047 return oldval; 04048 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 3011 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
Referenced by _macro_exec(), acf_import(), acf_odbc_read(), acf_odbc_write(), config_curl(), custom_log(), cut_internal(), destroy_curl(), exec_exec(), function_eval(), function_fieldqty(), get_mapping_weight(), handle_cli_rpt_lstats(), handle_getvariablefull(), launch_monitor_thread(), make_email_file(), manager_log(), pbx_builtin_importvar(), pbx_find_extension(), pbx_load_config(), pbx_substitute_variables(), realtime_curl(), realtime_multi_curl(), rotate_file(), sendmail(), sendpage(), sqlite3_log(), store_curl(), substituted(), tryexec_exec(), and update_curl().
03012 { 03013 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count); 03014 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 3016 of file pbx.c.
References pbx_substitute_variables_helper_full().
Referenced by ast_add_extension2_lockopt(), build_user_routes(), dundi_lookup_local(), loopback_subst(), phoneprov_callback(), and pp_each_user_exec().
03017 { 03018 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count); 03019 }