#include "asterisk/sched.h"
#include "asterisk/channel.h"
#include "asterisk/linkedlists.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_switch |
struct | ast_timing |
Defines | |
#define | AST_MAX_APP 32 |
#define | AST_PBX_KEEP 0 |
#define | AST_PBX_KEEPALIVE 10 |
Special return values from applications to the PBX {. | |
#define | AST_PBX_NO_HANGUP_PEER 11 |
#define | AST_PBX_REPLACE 1 |
#define | PRIORITY_HINT -1 |
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 } |
Functions | |
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_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). | |
struct ast_context * | ast_context_create (struct ast_context **extcontexts, const char *name, const char *registrar) |
Register a new context. | |
void | ast_context_destroy (struct ast_context *con, const char *registrar) |
Destroy a context (matches the specified context (or ANY context if NULL). | |
struct ast_context * | ast_context_find (const char *name) |
Find a context. | |
struct ast_context * | ast_context_find_or_create (struct ast_context **extcontexts, const char *name, const char *registrar) |
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) |
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_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
int | ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
int | ast_context_remove_include (const char *context, const char *include, const char *registrar) |
Remove a context include. | |
int | ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar) |
Removes an include by an ast_context structure. | |
int | ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar) |
Remove a switch. | |
int | ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar) |
This function locks given context, removes switch, unlock context and return. | |
int | ast_context_unlockmacro (const char *macrocontext) |
Unlocks the macrolock in the given context. | |
int | ast_context_verify_includes (struct ast_context *con) |
Verifies includes in an ast_contect structure. | |
struct ast_custom_function * | ast_custom_function_find (const char *name) |
int | ast_custom_function_register (struct ast_custom_function *acf) |
Reigster a custom function. | |
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_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, char *function, char *workspace, size_t len) |
executes a read operation on a function | |
int | ast_func_write (struct ast_channel *chan, char *function, const char *value) |
executes a write operation on a function | |
const char * | ast_get_context_name (struct ast_context *con) |
const char * | ast_get_context_registrar (struct ast_context *c) |
const char * | ast_get_extension_app (struct ast_exten *e) |
void * | ast_get_extension_app_data (struct ast_exten *e) |
const char * | ast_get_extension_cidmatch (struct ast_exten *e) |
struct ast_context * | ast_get_extension_context (struct ast_exten *exten) |
const char * | ast_get_extension_label (struct ast_exten *e) |
int | ast_get_extension_matchcid (struct ast_exten *e) |
const char * | ast_get_extension_name (struct ast_exten *exten) |
int | ast_get_extension_priority (struct ast_exten *exten) |
const char * | ast_get_extension_registrar (struct ast_exten *e) |
int | ast_get_hint (char *hint, int maxlen, char *name, int maxnamelen, struct ast_channel *c, const char *context, const char *exten) |
If an extension exists, return non-zero. | |
const char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
const char * | ast_get_ignorepat_registrar (struct ast_ignorepat *ip) |
const char * | ast_get_include_name (struct ast_include *include) |
const char * | ast_get_include_registrar (struct ast_include *i) |
const char * | ast_get_switch_data (struct ast_sw *sw) |
const char * | ast_get_switch_name (struct ast_sw *sw) |
const char * | ast_get_switch_registrar (struct ast_sw *sw) |
int | ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
void | ast_hint_state_changed (const char *device) |
int | ast_ignore_pattern (const char *context, const char *pattern) |
Checks to see if a number should be ignored. | |
int | ast_lock_context (struct ast_context *con) |
Locks a given context. | |
int | ast_lock_contexts (void) |
Locks the context list. | |
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, 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_start (struct ast_channel *c) |
Create a new thread and start the PBX. | |
int | ast_register_application (const char *app, int(*execute)(struct ast_channel *, void *), const char *synopsis, const char *description) |
Register an application. | |
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) |
Launch a new extension (i.e. new stack). | |
int | ast_unlock_context (struct ast_context *con) |
int | ast_unlock_contexts (void) |
Unlocks contexts. | |
int | ast_unregister_application (const char *app) |
Unregister an application. | |
void | ast_unregister_switch (struct ast_switch *sw) |
Unregister an alternative switch. | |
struct ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority) |
struct ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
struct ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
struct ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
struct ast_context * | ast_walk_contexts (struct ast_context *con) |
struct ast_exten * | ast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority) |
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_serialize_variables (struct ast_channel *chan, char *buf, size_t size) |
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_checkcondition (const char *condition) |
Evaluate a condition. | |
int | pbx_exec (struct ast_channel *c, struct ast_app *app, void *data) |
Execute an application. | |
struct ast_app * | pbx_findapp (const char *app) |
Look up an application. | |
void | pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp) |
pbx_retrieve_variable: Support for Asterisk built-in variables --- | |
int | pbx_set_autofallthrough (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_MAX_APP 32 |
Max length of an application
Definition at line 34 of file pbx.h.
Referenced by destroy_station(), handle_show_application(), handle_show_application_deprecated(), handle_show_function(), handle_show_function_deprecated(), and sla_build_station().
#define AST_PBX_KEEPALIVE 10 |
Special return values from applications to the PBX {.
Destroy the thread, but don't hang up the channel
Definition at line 40 of file pbx.h.
Referenced by __ast_pbx_run(), _macro_exec(), agi_handle_command(), builtin_blindtransfer(), builtin_parkcall(), feature_exec_app(), park_call_exec(), queue_exec(), rpt_exec(), and run_agi().
#define AST_PBX_NO_HANGUP_PEER 11 |
Definition at line 41 of file pbx.h.
Referenced by builtin_blindtransfer(), builtin_parkcall(), feature_exec_app(), park_exec(), and try_calling().
#define PRIORITY_HINT -1 |
} Special Priority for a hint
Definition at line 44 of file pbx.h.
Referenced by add_extensions(), add_pri(), ast_add_extension2(), ast_hint_extension(), destroy_exten(), destroy_station(), handle_context_add_extension(), handle_context_add_extension_deprecated(), handle_context_remove_extension(), handle_context_remove_extension_deprecated(), handle_save_dialplan(), park_add_hints(), pbx_load_config(), print_ext(), and sla_build_station().
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 47 of file pbx.h.
00047 { 00048 AST_EXTENSION_REMOVED = -2, /*!< Extension removed */ 00049 AST_EXTENSION_DEACTIVATED = -1, /*!< Extension hint removed */ 00050 AST_EXTENSION_NOT_INUSE = 0, /*!< No device INUSE or BUSY */ 00051 AST_EXTENSION_INUSE = 1 << 0, /*!< One or more devices INUSE */ 00052 AST_EXTENSION_BUSY = 1 << 1, /*!< All devices BUSY */ 00053 AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */ 00054 AST_EXTENSION_RINGING = 1 << 3, /*!< All devices RINGING */ 00055 AST_EXTENSION_ONHOLD = 1 << 4, /*!< All devices ONHOLD */ 00056 };
enum ast_pbx_result |
Definition at line 214 of file pbx.h.
00214 { 00215 AST_PBX_SUCCESS = 0, 00216 AST_PBX_FAILED = -1, 00217 AST_PBX_CALL_LIMIT = -2, 00218 };
int ast_active_calls | ( | void | ) |
Retrieve the number of active calls.
Definition at line 2650 of file pbx.c.
References countcalls.
02651 { 02652 return countcalls; 02653 }
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 4530 of file pbx.c.
References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked().
04533 { 04534 int ret = -1; 04535 struct ast_context *c = find_context_locked(context); 04536 04537 if (c) { 04538 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 04539 application, data, datad, registrar); 04540 ast_unlock_contexts(); 04541 } 04542 return ret; 04543 }
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 4734 of file pbx.c.
References add_pri(), ast_exten::app, ast_add_hint(), ast_calloc, AST_LIST_FIRST, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_exten::cidmatch, ast_exten::data, ast_exten::datad, el, ext_cmp(), ext_strncpy(), ast_exten::exten, globals, ast_exten::label, ast_context::lock, LOG_DEBUG, ast_exten::matchcid, ast_exten::next, option_debug, option_verbose, ast_exten::parent, pbx_substitute_variables_varshead(), ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, ast_context::root, ast_exten::stuff, VAR_BUF_SIZE, and VERBOSE_PREFIX_3.
04738 { 04739 /* 04740 * Sort extensions (or patterns) according to the rules indicated above. 04741 * These are implemented by the function ext_cmp()). 04742 * All priorities for the same ext/pattern/cid are kept in a list, 04743 * using the 'peer' field as a link field.. 04744 */ 04745 struct ast_exten *tmp, *e, *el = NULL; 04746 int res; 04747 int length; 04748 char *p; 04749 char expand_buf[VAR_BUF_SIZE] = { 0, }; 04750 04751 /* if we are adding a hint, and there are global variables, and the hint 04752 contains variable references, then expand them 04753 */ 04754 ast_mutex_lock(&globalslock); 04755 if (priority == PRIORITY_HINT && AST_LIST_FIRST(&globals) && strstr(application, "${")) { 04756 pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf)); 04757 application = expand_buf; 04758 } 04759 ast_mutex_unlock(&globalslock); 04760 04761 length = sizeof(struct ast_exten); 04762 length += strlen(extension) + 1; 04763 length += strlen(application) + 1; 04764 if (label) 04765 length += strlen(label) + 1; 04766 if (callerid) 04767 length += strlen(callerid) + 1; 04768 else 04769 length ++; /* just the '\0' */ 04770 04771 /* Be optimistic: Build the extension structure first */ 04772 if (!(tmp = ast_calloc(1, length))) 04773 return -1; 04774 04775 /* use p as dst in assignments, as the fields are const char * */ 04776 p = tmp->stuff; 04777 if (label) { 04778 tmp->label = p; 04779 strcpy(p, label); 04780 p += strlen(label) + 1; 04781 } 04782 tmp->exten = p; 04783 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 04784 tmp->priority = priority; 04785 tmp->cidmatch = p; /* but use p for assignments below */ 04786 if (callerid) { 04787 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 04788 tmp->matchcid = 1; 04789 } else { 04790 *p++ = '\0'; 04791 tmp->matchcid = 0; 04792 } 04793 tmp->app = p; 04794 strcpy(p, application); 04795 tmp->parent = con; 04796 tmp->data = data; 04797 tmp->datad = datad; 04798 tmp->registrar = registrar; 04799 04800 ast_mutex_lock(&con->lock); 04801 res = 0; /* some compilers will think it is uninitialized otherwise */ 04802 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 04803 res = ext_cmp(e->exten, extension); 04804 if (res == 0) { /* extension match, now look at cidmatch */ 04805 if (!e->matchcid && !tmp->matchcid) 04806 res = 0; 04807 else if (tmp->matchcid && !e->matchcid) 04808 res = 1; 04809 else if (e->matchcid && !tmp->matchcid) 04810 res = -1; 04811 else 04812 res = strcasecmp(e->cidmatch, tmp->cidmatch); 04813 } 04814 if (res >= 0) 04815 break; 04816 } 04817 if (e && res == 0) { /* exact match, insert in the pri chain */ 04818 res = add_pri(con, tmp, el, e, replace); 04819 ast_mutex_unlock(&con->lock); 04820 if (res < 0) { 04821 errno = EEXIST; /* XXX do we care ? */ 04822 return 0; /* XXX should we return -1 maybe ? */ 04823 } 04824 } else { 04825 /* 04826 * not an exact match, this is the first entry with this pattern, 04827 * so insert in the main list right before 'e' (if any) 04828 */ 04829 tmp->next = e; 04830 if (el) 04831 el->next = tmp; 04832 else 04833 con->root = tmp; 04834 ast_mutex_unlock(&con->lock); 04835 if (tmp->priority == PRIORITY_HINT) 04836 ast_add_hint(tmp); 04837 } 04838 if (option_debug) { 04839 if (tmp->matchcid) { 04840 if (option_debug) 04841 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", 04842 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04843 } else { 04844 if (option_debug) 04845 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", 04846 tmp->exten, tmp->priority, con->name); 04847 } 04848 } 04849 if (option_verbose > 2) { 04850 if (tmp->matchcid) { 04851 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", 04852 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04853 } else { 04854 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", 04855 tmp->exten, tmp->priority, con->name); 04856 } 04857 } 04858 return 0; 04859 }
int ast_async_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 4564 of file pbx.c.
References ast_channel::_state, ast_channel::amaflags, ast_cdr_dup(), ast_channel_alloc(), ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_channel::cdr, ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat.
04565 { 04566 int res = 0; 04567 04568 ast_channel_lock(chan); 04569 04570 if (chan->pbx) { /* This channel is currently in the PBX */ 04571 ast_explicit_goto(chan, context, exten, priority); 04572 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 04573 } else { 04574 /* In order to do it when the channel doesn't really exist within 04575 the PBX, we have to make a new channel, masquerade, and start the PBX 04576 at the new location */ 04577 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name); 04578 if (chan->cdr) { 04579 tmpchan->cdr = ast_cdr_dup(chan->cdr); 04580 } 04581 if (!tmpchan) 04582 res = -1; 04583 else { 04584 /* Make formats okay */ 04585 tmpchan->readformat = chan->readformat; 04586 tmpchan->writeformat = chan->writeformat; 04587 /* Setup proper location */ 04588 ast_explicit_goto(tmpchan, 04589 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 04590 04591 /* Masquerade into temp channel */ 04592 ast_channel_masquerade(tmpchan, chan); 04593 04594 /* Grab the locks and get going */ 04595 ast_channel_lock(tmpchan); 04596 ast_do_masquerade(tmpchan); 04597 ast_channel_unlock(tmpchan); 04598 /* Start the PBX going on our stolen channel */ 04599 if (ast_pbx_start(tmpchan)) { 04600 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 04601 ast_hangup(tmpchan); 04602 res = -1; 04603 } 04604 } 04605 } 04606 ast_channel_unlock(chan); 04607 return res; 04608 }
int ast_async_goto_by_name | ( | const char * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 4610 of file pbx.c.
References ast_async_goto(), ast_channel_unlock, and ast_get_channel_by_name_locked().
04611 { 04612 struct ast_channel *chan; 04613 int res = -1; 04614 04615 chan = ast_get_channel_by_name_locked(channame); 04616 if (chan) { 04617 res = ast_async_goto(chan, context, exten, priority); 04618 ast_channel_unlock(chan); 04619 } 04620 return res; 04621 }
int ast_async_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6269 of file pbx.c.
References __ast_goto_if_exists().
06270 { 06271 return __ast_goto_if_exists(chan, context, exten, priority, 1); 06272 }
int ast_build_timing | ( | struct ast_timing * | i, | |
const char * | info | |||
) |
Definition at line 4206 of file pbx.c.
References ast_strlen_zero(), ast_timing::daymask, days, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, months, and strsep().
04207 { 04208 char info_save[256]; 04209 char *info; 04210 04211 /* Check for empty just in case */ 04212 if (ast_strlen_zero(info_in)) 04213 return 0; 04214 /* make a copy just in case we were passed a static string */ 04215 ast_copy_string(info_save, info_in, sizeof(info_save)); 04216 info = info_save; 04217 /* Assume everything except time */ 04218 i->monthmask = 0xfff; /* 12 bits */ 04219 i->daymask = 0x7fffffffU; /* 31 bits */ 04220 i->dowmask = 0x7f; /* 7 bits */ 04221 /* on each call, use strsep() to move info to the next argument */ 04222 get_timerange(i, strsep(&info, "|")); 04223 if (info) 04224 i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week"); 04225 if (info) 04226 i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day"); 04227 if (info) 04228 i->monthmask = get_range(strsep(&info, "|"), 12, months, "month"); 04229 return 1; 04230 }
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 2276 of file pbx.c.
References E_CANMATCH, and pbx_extension_helper().
02277 { 02278 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH); 02279 }
int ast_check_timing | ( | const struct ast_timing * | i | ) |
Definition at line 4232 of file pbx.c.
References ast_localtime(), ast_log(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, ast_timing::monthmask, and t.
04233 { 04234 struct tm tm; 04235 time_t t = time(NULL); 04236 04237 ast_localtime(&t, &tm, NULL); 04238 04239 /* If it's not the right month, return */ 04240 if (!(i->monthmask & (1 << tm.tm_mon))) 04241 return 0; 04242 04243 /* If it's not that time of the month.... */ 04244 /* Warning, tm_mday has range 1..31! */ 04245 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 04246 return 0; 04247 04248 /* If it's not the right day of the week */ 04249 if (!(i->dowmask & (1 << tm.tm_wday))) 04250 return 0; 04251 04252 /* Sanity check the hour just to be safe */ 04253 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 04254 ast_log(LOG_WARNING, "Insane time...\n"); 04255 return 0; 04256 } 04257 04258 /* Now the tough part, we calculate if it fits 04259 in the right time based on min/hour */ 04260 if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2)))) 04261 return 0; 04262 04263 /* If we got this far, then we're good */ 04264 return 1; 04265 }
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 4466 of file pbx.c.
References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
04467 { 04468 int ret = -1; 04469 struct ast_context *c = find_context_locked(context); 04470 04471 if (c) { 04472 ret = ast_context_add_ignorepat2(c, value, registrar); 04473 ast_unlock_contexts(); 04474 } 04475 return ret; 04476 }
int ast_context_add_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4478 of file pbx.c.
References ast_calloc, ast_mutex_lock(), ast_mutex_unlock(), ast_context::ignorepats, ast_context::lock, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
04479 { 04480 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 04481 int length; 04482 length = sizeof(struct ast_ignorepat); 04483 length += strlen(value) + 1; 04484 if (!(ignorepat = ast_calloc(1, length))) 04485 return -1; 04486 /* The cast to char * is because we need to write the initial value. 04487 * The field is not supposed to be modified otherwise 04488 */ 04489 strcpy((char *)ignorepat->pattern, value); 04490 ignorepat->next = NULL; 04491 ignorepat->registrar = registrar; 04492 ast_mutex_lock(&con->lock); 04493 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 04494 ignorepatl = ignorepatc; 04495 if (!strcasecmp(ignorepatc->pattern, value)) { 04496 /* Already there */ 04497 ast_mutex_unlock(&con->lock); 04498 errno = EEXIST; 04499 return -1; 04500 } 04501 } 04502 if (ignorepatl) 04503 ignorepatl->next = ignorepat; 04504 else 04505 con->ignorepats = ignorepat; 04506 ast_mutex_unlock(&con->lock); 04507 return 0; 04508 04509 }
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 4012 of file pbx.c.
References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked().
04013 { 04014 int ret = -1; 04015 struct ast_context *c = find_context_locked(context); 04016 04017 if (c) { 04018 ret = ast_context_add_include2(c, include, registrar); 04019 ast_unlock_contexts(); 04020 } 04021 return ret; 04022 }
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 4274 of file pbx.c.
References ast_build_timing(), ast_calloc, ast_get_context_name(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), free, ast_include::hastime, ast_context::includes, ast_context::lock, ast_include::name, ast_include::next, option_verbose, ast_include::registrar, ast_include::rname, ast_include::stuff, ast_include::timing, and VERBOSE_PREFIX_3.
04276 { 04277 struct ast_include *new_include; 04278 char *c; 04279 struct ast_include *i, *il = NULL; /* include, include_last */ 04280 int length; 04281 char *p; 04282 04283 length = sizeof(struct ast_include); 04284 length += 2 * (strlen(value) + 1); 04285 04286 /* allocate new include structure ... */ 04287 if (!(new_include = ast_calloc(1, length))) 04288 return -1; 04289 /* Fill in this structure. Use 'p' for assignments, as the fields 04290 * in the structure are 'const char *' 04291 */ 04292 p = new_include->stuff; 04293 new_include->name = p; 04294 strcpy(p, value); 04295 p += strlen(value) + 1; 04296 new_include->rname = p; 04297 strcpy(p, value); 04298 /* Strip off timing info, and process if it is there */ 04299 if ( (c = strchr(p, '|')) ) { 04300 *c++ = '\0'; 04301 new_include->hastime = ast_build_timing(&(new_include->timing), c); 04302 } 04303 new_include->next = NULL; 04304 new_include->registrar = registrar; 04305 04306 ast_mutex_lock(&con->lock); 04307 04308 /* ... go to last include and check if context is already included too... */ 04309 for (i = con->includes; i; i = i->next) { 04310 if (!strcasecmp(i->name, new_include->name)) { 04311 free(new_include); 04312 ast_mutex_unlock(&con->lock); 04313 errno = EEXIST; 04314 return -1; 04315 } 04316 il = i; 04317 } 04318 04319 /* ... include new context into context list, unlock, return */ 04320 if (il) 04321 il->next = new_include; 04322 else 04323 con->includes = new_include; 04324 if (option_verbose > 2) 04325 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 04326 ast_mutex_unlock(&con->lock); 04327 04328 return 0; 04329 }
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 4336 of file pbx.c.
References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked().
04337 { 04338 int ret = -1; 04339 struct ast_context *c = find_context_locked(context); 04340 04341 if (c) { /* found, add switch to this context */ 04342 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 04343 ast_unlock_contexts(); 04344 } 04345 return ret; 04346 }
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 4355 of file pbx.c.
References ast_calloc, ast_get_context_name(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_sw::data, ast_sw::eval, free, ast_context::lock, ast_sw::name, option_verbose, ast_sw::registrar, SWITCH_DATA_LENGTH, and VERBOSE_PREFIX_3.
04357 { 04358 struct ast_sw *new_sw; 04359 struct ast_sw *i; 04360 int length; 04361 char *p; 04362 04363 length = sizeof(struct ast_sw); 04364 length += strlen(value) + 1; 04365 if (data) 04366 length += strlen(data); 04367 length++; 04368 if (eval) { 04369 /* Create buffer for evaluation of variables */ 04370 length += SWITCH_DATA_LENGTH; 04371 length++; 04372 } 04373 04374 /* allocate new sw structure ... */ 04375 if (!(new_sw = ast_calloc(1, length))) 04376 return -1; 04377 /* ... fill in this structure ... */ 04378 p = new_sw->stuff; 04379 new_sw->name = p; 04380 strcpy(new_sw->name, value); 04381 p += strlen(value) + 1; 04382 new_sw->data = p; 04383 if (data) { 04384 strcpy(new_sw->data, data); 04385 p += strlen(data) + 1; 04386 } else { 04387 strcpy(new_sw->data, ""); 04388 p++; 04389 } 04390 if (eval) 04391 new_sw->tmpdata = p; 04392 new_sw->eval = eval; 04393 new_sw->registrar = registrar; 04394 04395 /* ... try to lock this context ... */ 04396 ast_mutex_lock(&con->lock); 04397 04398 /* ... go to last sw and check if context is already swd too... */ 04399 AST_LIST_TRAVERSE(&con->alts, i, list) { 04400 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 04401 free(new_sw); 04402 ast_mutex_unlock(&con->lock); 04403 errno = EEXIST; 04404 return -1; 04405 } 04406 } 04407 04408 /* ... sw new context into context list, unlock, return */ 04409 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 04410 04411 if (option_verbose > 2) 04412 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 04413 04414 ast_mutex_unlock(&con->lock); 04415 04416 return 0; 04417 }
struct ast_context* ast_context_create | ( | struct ast_context ** | extcontexts, | |
const char * | name, | |||
const char * | registrar | |||
) | [read] |
Register a new context.
extcontexts | pointer to the ast_context structure pointer | |
name | name of the new context | |
registrar | registrar of the context |
Definition at line 3883 of file pbx.c.
References __ast_context_create().
03884 { 03885 return __ast_context_create(extcontexts, name, registrar, 0); 03886 }
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 5320 of file pbx.c.
References __ast_context_destroy().
05321 { 05322 __ast_context_destroy(con,registrar); 05323 }
struct ast_context* ast_context_find | ( | const char * | name | ) | [read] |
Find a context.
name | name of the context to find |
Definition at line 890 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), and ast_walk_contexts().
00891 { 00892 struct ast_context *tmp = NULL; 00893 ast_mutex_lock(&conlock); 00894 while ( (tmp = ast_walk_contexts(tmp)) ) { 00895 if (!name || !strcasecmp(name, tmp->name)) 00896 break; 00897 } 00898 ast_mutex_unlock(&conlock); 00899 return tmp; 00900 }
struct ast_context* ast_context_find_or_create | ( | struct ast_context ** | extcontexts, | |
const char * | name, | |||
const char * | registrar | |||
) | [read] |
Definition at line 3888 of file pbx.c.
References __ast_context_create().
03889 { 03890 return __ast_context_create(extcontexts, name, registrar, 1); 03891 }
int ast_context_lockmacro | ( | const char * | context | ) |
locks the macrolock in the given given context
macrocontext | name of the macro-context to lock |
0 | on success | |
-1 | on failure |
Definition at line 2887 of file pbx.c.
References ast_get_context_name(), ast_lock_contexts(), ast_mutex_lock(), ast_unlock_contexts(), and ast_walk_contexts().
02888 { 02889 struct ast_context *c = NULL; 02890 int ret = -1; 02891 02892 ast_lock_contexts(); 02893 02894 while ((c = ast_walk_contexts(c))) { 02895 if (!strcmp(ast_get_context_name(c), context)) { 02896 ret = 0; 02897 break; 02898 } 02899 } 02900 02901 ast_unlock_contexts(); 02902 02903 /* if we found context, lock macrolock */ 02904 if (ret == 0) 02905 ret = ast_mutex_lock(&c->macrolock); 02906 02907 return ret; 02908 }
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 | |
registrar | registrar of the extension |
0 | on success | |
-1 | on failure |
Definition at line 2788 of file pbx.c.
References ast_context_remove_extension2(), ast_unlock_contexts(), and find_context_locked().
02789 { 02790 int ret = -1; /* default error return */ 02791 struct ast_context *c = find_context_locked(context); 02792 02793 if (c) { /* ... remove extension ... */ 02794 ret = ast_context_remove_extension2(c, extension, priority, registrar); 02795 ast_unlock_contexts(); 02796 } 02797 return ret; 02798 }
int ast_context_remove_extension2 | ( | struct ast_context * | con, | |
const char * | extension, | |||
int | priority, | |||
const char * | registrar | |||
) |
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 2810 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), destroy_exten(), ast_exten::exten, exten, ast_context::lock, ast_exten::next, ast_exten::peer, ast_exten::registrar, and ast_context::root.
02811 { 02812 struct ast_exten *exten, *prev_exten = NULL; 02813 struct ast_exten *peer; 02814 02815 ast_mutex_lock(&con->lock); 02816 02817 /* scan the extension list to find matching extension-registrar */ 02818 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 02819 if (!strcmp(exten->exten, extension) && 02820 (!registrar || !strcmp(exten->registrar, registrar))) 02821 break; 02822 } 02823 if (!exten) { 02824 /* we can't find right extension */ 02825 ast_mutex_unlock(&con->lock); 02826 return -1; 02827 } 02828 02829 /* should we free all peers in this extension? (priority == 0)? */ 02830 if (priority == 0) { 02831 /* remove this extension from context list */ 02832 if (prev_exten) 02833 prev_exten->next = exten->next; 02834 else 02835 con->root = exten->next; 02836 02837 /* fire out all peers */ 02838 while ( (peer = exten) ) { 02839 exten = peer->peer; /* prepare for next entry */ 02840 destroy_exten(peer); 02841 } 02842 } else { 02843 /* scan the priority list to remove extension with exten->priority == priority */ 02844 struct ast_exten *previous_peer = NULL; 02845 02846 for (peer = exten; peer; previous_peer = peer, peer = peer->peer) { 02847 if (peer->priority == priority && 02848 (!registrar || !strcmp(peer->registrar, registrar) )) 02849 break; /* found our priority */ 02850 } 02851 if (!peer) { /* not found */ 02852 ast_mutex_unlock(&con->lock); 02853 return -1; 02854 } 02855 /* we are first priority extension? */ 02856 if (!previous_peer) { 02857 /* 02858 * We are first in the priority chain, so must update the extension chain. 02859 * The next node is either the next priority or the next extension 02860 */ 02861 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 02862 02863 if (!prev_exten) /* change the root... */ 02864 con->root = next_node; 02865 else 02866 prev_exten->next = next_node; /* unlink */ 02867 if (peer->peer) /* XXX update the new head of the pri list */ 02868 peer->peer->next = peer->next; 02869 } else { /* easy, we are not first priority in extension */ 02870 previous_peer->peer = peer->peer; 02871 } 02872 02873 /* now, free whole priority extension */ 02874 destroy_exten(peer); 02875 /* XXX should we return -1 ? */ 02876 } 02877 ast_mutex_unlock(&con->lock); 02878 return 0; 02879 }
int ast_context_remove_ignorepat | ( | const char * | context, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4423 of file pbx.c.
References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked().
04424 { 04425 int ret = -1; 04426 struct ast_context *c = find_context_locked(context); 04427 04428 if (c) { 04429 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 04430 ast_unlock_contexts(); 04431 } 04432 return ret; 04433 }
int ast_context_remove_ignorepat2 | ( | struct ast_context * | con, | |
const char * | ignorepat, | |||
const char * | registrar | |||
) |
Definition at line 4435 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), free, ast_context::ignorepats, ast_context::lock, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar.
04436 { 04437 struct ast_ignorepat *ip, *ipl = NULL; 04438 04439 ast_mutex_lock(&con->lock); 04440 04441 for (ip = con->ignorepats; ip; ip = ip->next) { 04442 if (!strcmp(ip->pattern, ignorepat) && 04443 (!registrar || (registrar == ip->registrar))) { 04444 if (ipl) { 04445 ipl->next = ip->next; 04446 free(ip); 04447 } else { 04448 con->ignorepats = ip->next; 04449 free(ip); 04450 } 04451 ast_mutex_unlock(&con->lock); 04452 return 0; 04453 } 04454 ipl = ip; 04455 } 04456 04457 ast_mutex_unlock(&con->lock); 04458 errno = EINVAL; 04459 return -1; 04460 }
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 2684 of file pbx.c.
References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked().
02685 { 02686 int ret = -1; 02687 struct ast_context *c = find_context_locked(context); 02688 02689 if (c) { 02690 /* found, remove include from this context ... */ 02691 ret = ast_context_remove_include2(c, include, registrar); 02692 ast_unlock_contexts(); 02693 } 02694 return ret; 02695 }
int ast_context_remove_include2 | ( | struct ast_context * | con, | |
const char * | include, | |||
const char * | registrar | |||
) |
Removes an include by an ast_context structure.
0 | on success | |
-1 | on success |
Definition at line 2705 of file pbx.c.
References ast_mutex_lock(), ast_mutex_unlock(), free, ast_context::includes, ast_context::lock, ast_include::name, ast_include::next, and ast_include::registrar.
02706 { 02707 struct ast_include *i, *pi = NULL; 02708 int ret = -1; 02709 02710 ast_mutex_lock(&con->lock); 02711 02712 /* find our include */ 02713 for (i = con->includes; i; pi = i, i = i->next) { 02714 if (!strcmp(i->name, include) && 02715 (!registrar || !strcmp(i->registrar, registrar))) { 02716 /* remove from list */ 02717 if (pi) 02718 pi->next = i->next; 02719 else 02720 con->includes = i->next; 02721 /* free include and return */ 02722 free(i); 02723 ret = 0; 02724 break; 02725 } 02726 } 02727 02728 ast_mutex_unlock(&con->lock); 02729 return ret; 02730 }
int ast_context_remove_switch | ( | const char * | context, | |
const char * | sw, | |||
const char * | data, | |||
const char * | registrar | |||
) |
Remove a switch.
Removes a switch with the given parameters
0 | on success | |
-1 | on failure |
Definition at line 2737 of file pbx.c.
References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked().
02738 { 02739 int ret = -1; /* default error return */ 02740 struct ast_context *c = find_context_locked(context); 02741 02742 if (c) { 02743 /* remove switch from this context ... */ 02744 ret = ast_context_remove_switch2(c, sw, data, registrar); 02745 ast_unlock_contexts(); 02746 } 02747 return ret; 02748 }
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 2758 of file pbx.c.
References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_lock(), ast_mutex_unlock(), ast_sw::data, free, ast_context::lock, ast_sw::name, and ast_sw::registrar.
02759 { 02760 struct ast_sw *i; 02761 int ret = -1; 02762 02763 ast_mutex_lock(&con->lock); 02764 02765 /* walk switches */ 02766 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 02767 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 02768 (!registrar || !strcmp(i->registrar, registrar))) { 02769 /* found, remove from list */ 02770 AST_LIST_REMOVE_CURRENT(&con->alts, list); 02771 free(i); /* free switch and return */ 02772 ret = 0; 02773 break; 02774 } 02775 } 02776 AST_LIST_TRAVERSE_SAFE_END 02777 02778 ast_mutex_unlock(&con->lock); 02779 02780 return ret; 02781 }
int ast_context_unlockmacro | ( | const char * | context | ) |
Unlocks the macrolock in the given context.
macrocontext | name of the macro-context to unlock |
0 | on success | |
-1 | on failure |
Definition at line 2915 of file pbx.c.
References ast_get_context_name(), ast_lock_contexts(), ast_mutex_unlock(), ast_unlock_contexts(), and ast_walk_contexts().
02916 { 02917 struct ast_context *c = NULL; 02918 int ret = -1; 02919 02920 ast_lock_contexts(); 02921 02922 while ((c = ast_walk_contexts(c))) { 02923 if (!strcmp(ast_get_context_name(c), context)) { 02924 ret = 0; 02925 break; 02926 } 02927 } 02928 02929 ast_unlock_contexts(); 02930 02931 /* if we found context, unlock macrolock */ 02932 if (ret == 0) 02933 ret = ast_mutex_unlock(&c->macrolock); 02934 02935 return ret; 02936 }
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 6230 of file pbx.c.
References ast_context_find(), ast_get_context_name(), ast_log(), ast_walk_context_includes(), LOG_WARNING, and ast_include::rname.
06231 { 06232 struct ast_include *inc = NULL; 06233 int res = 0; 06234 06235 while ( (inc = ast_walk_context_includes(con, inc)) ) 06236 if (!ast_context_find(inc->rname)) { 06237 res = -1; 06238 ast_log(LOG_WARNING, "Context '%s' tries includes nonexistent context '%s'\n", 06239 ast_get_context_name(con), inc->rname); 06240 } 06241 return res; 06242 }
struct ast_custom_function* ast_custom_function_find | ( | const char * | name | ) | [read] |
Definition at line 1427 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_custom_function::name.
01428 { 01429 struct ast_custom_function *acf = NULL; 01430 01431 AST_LIST_LOCK(&acf_root); 01432 AST_LIST_TRAVERSE(&acf_root, acf, acflist) { 01433 if (!strcmp(name, acf->name)) 01434 break; 01435 } 01436 AST_LIST_UNLOCK(&acf_root); 01437 01438 return acf; 01439 }
int ast_custom_function_register | ( | struct ast_custom_function * | acf | ) |
Reigster a custom function.
Definition at line 1463 of file pbx.c.
References ast_custom_function_find(), AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_verbose(), LOG_ERROR, ast_custom_function::name, option_verbose, and VERBOSE_PREFIX_2.
01464 { 01465 struct ast_custom_function *cur; 01466 01467 if (!acf) 01468 return -1; 01469 01470 AST_LIST_LOCK(&acf_root); 01471 01472 if (ast_custom_function_find(acf->name)) { 01473 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 01474 AST_LIST_UNLOCK(&acf_root); 01475 return -1; 01476 } 01477 01478 /* Store in alphabetical order */ 01479 AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 01480 if (strcasecmp(acf->name, cur->name) < 0) { 01481 AST_LIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist); 01482 break; 01483 } 01484 } 01485 AST_LIST_TRAVERSE_SAFE_END 01486 if (!cur) 01487 AST_LIST_INSERT_TAIL(&acf_root, acf, acflist); 01488 01489 AST_LIST_UNLOCK(&acf_root); 01490 01491 if (option_verbose > 1) 01492 ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name); 01493 01494 return 0; 01495 }
int ast_custom_function_unregister | ( | struct ast_custom_function * | acf | ) |
Unregister a custom function.
Definition at line 1441 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verbose(), ast_custom_function::name, option_verbose, and VERBOSE_PREFIX_2.
01442 { 01443 struct ast_custom_function *cur; 01444 01445 if (!acf) 01446 return -1; 01447 01448 AST_LIST_LOCK(&acf_root); 01449 AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 01450 if (cur == acf) { 01451 AST_LIST_REMOVE_CURRENT(&acf_root, acflist); 01452 if (option_verbose > 1) 01453 ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name); 01454 break; 01455 } 01456 } 01457 AST_LIST_TRAVERSE_SAFE_END 01458 AST_LIST_UNLOCK(&acf_root); 01459 01460 return acf ? 0 : -1; 01461 }
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 2261 of file pbx.c.
References E_MATCH, and pbx_extension_helper().
02262 { 02263 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH); 02264 }
int ast_explicit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 4545 of file pbx.c.
References AST_FLAG_IN_AUTOLOOP, ast_strlen_zero(), ast_test_flag, ast_channel::context, ast_channel::exten, and ast_channel::priority.
04546 { 04547 if (!chan) 04548 return -1; 04549 04550 if (!ast_strlen_zero(context)) 04551 ast_copy_string(chan->context, context, sizeof(chan->context)); 04552 if (!ast_strlen_zero(exten)) 04553 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 04554 if (priority > -1) { 04555 chan->priority = priority; 04556 /* see flag description in channel.h for explanation */ 04557 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 04558 chan->priority--; 04559 } 04560 04561 return 0; 04562 }
int ast_extension_close | ( | const char * | pattern, | |
const char * | data, | |||
int | needmore | |||
) |
Definition at line 883 of file pbx.c.
References ast_log(), E_CANMATCH, E_MATCHMORE, extension_match_core(), and LOG_WARNING.
00884 { 00885 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 00886 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 00887 return extension_match_core(pattern, data, needmore); 00888 }
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 878 of file pbx.c.
References E_MATCH, and extension_match_core().
00879 { 00880 return extension_match_core(pattern, data, E_MATCH); 00881 }
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 1985 of file pbx.c.
References ast_extension_state2(), and ast_hint_extension().
01986 { 01987 struct ast_exten *e; 01988 01989 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */ 01990 if (!e) 01991 return -1; /* No hint, return -1 */ 01992 01993 return ast_extension_state2(e); /* Check all devices in the hint */ 01994 }
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 1973 of file pbx.c.
References extension_states, and cfextension_states::text.
01974 { 01975 int i; 01976 01977 for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) { 01978 if (extension_states[i].extension_state == extension_state) 01979 return extension_states[i].text; 01980 } 01981 return "Unknown"; 01982 }
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 2040 of file pbx.c.
References ast_calloc, ast_hint_extension(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_hint::exten, ast_state_cb::id, ast_state_cb::next, statecbs, and stateid.
02042 { 02043 struct ast_hint *hint; 02044 struct ast_state_cb *cblist; 02045 struct ast_exten *e; 02046 02047 /* If there's no context and extension: add callback to statecbs list */ 02048 if (!context && !exten) { 02049 AST_LIST_LOCK(&hints); 02050 02051 for (cblist = statecbs; cblist; cblist = cblist->next) { 02052 if (cblist->callback == callback) { 02053 cblist->data = data; 02054 AST_LIST_UNLOCK(&hints); 02055 return 0; 02056 } 02057 } 02058 02059 /* Now insert the callback */ 02060 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 02061 AST_LIST_UNLOCK(&hints); 02062 return -1; 02063 } 02064 cblist->id = 0; 02065 cblist->callback = callback; 02066 cblist->data = data; 02067 02068 cblist->next = statecbs; 02069 statecbs = cblist; 02070 02071 AST_LIST_UNLOCK(&hints); 02072 return 0; 02073 } 02074 02075 if (!context || !exten) 02076 return -1; 02077 02078 /* This callback type is for only one hint, so get the hint */ 02079 e = ast_hint_extension(NULL, context, exten); 02080 if (!e) { 02081 return -1; 02082 } 02083 02084 /* Find the hint in the list of hints */ 02085 AST_LIST_LOCK(&hints); 02086 02087 AST_LIST_TRAVERSE(&hints, hint, list) { 02088 if (hint->exten == e) 02089 break; 02090 } 02091 02092 if (!hint) { 02093 /* We have no hint, sorry */ 02094 AST_LIST_UNLOCK(&hints); 02095 return -1; 02096 } 02097 02098 /* Now insert the callback in the callback list */ 02099 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 02100 AST_LIST_UNLOCK(&hints); 02101 return -1; 02102 } 02103 cblist->id = stateid++; /* Unique ID for this callback */ 02104 cblist->callback = callback; /* Pointer to callback routine */ 02105 cblist->data = data; /* Data for the callback */ 02106 02107 cblist->next = hint->callbacks; 02108 hint->callbacks = cblist; 02109 02110 AST_LIST_UNLOCK(&hints); 02111 return cblist->id; 02112 }
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 2115 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_hint::callbacks, free, ast_state_cb::next, and statecbs.
02116 { 02117 struct ast_state_cb **p_cur = NULL; /* address of pointer to us */ 02118 int ret = -1; 02119 02120 if (!id && !callback) 02121 return -1; 02122 02123 AST_LIST_LOCK(&hints); 02124 02125 if (!id) { /* id == 0 is a callback without extension */ 02126 for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) { 02127 if ((*p_cur)->callback == callback) 02128 break; 02129 } 02130 } else { /* callback with extension, find the callback based on ID */ 02131 struct ast_hint *hint; 02132 AST_LIST_TRAVERSE(&hints, hint, list) { 02133 for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) { 02134 if ((*p_cur)->id == id) 02135 break; 02136 } 02137 if (*p_cur) /* found in the inner loop */ 02138 break; 02139 } 02140 } 02141 if (p_cur && *p_cur) { 02142 struct ast_state_cb *cur = *p_cur; 02143 *p_cur = cur->next; 02144 free(cur); 02145 ret = 0; 02146 } 02147 AST_LIST_UNLOCK(&hints); 02148 return ret; 02149 }
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 |
Definition at line 2266 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
02267 { 02268 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL); 02269 }
int ast_findlabel_extension2 | ( | struct ast_channel * | c, | |
struct ast_context * | con, | |||
const char * | exten, | |||
const char * | label, | |||
const char * | callerid | |||
) |
Find the priority of an extension that has the specified label.
Definition at line 2271 of file pbx.c.
References E_FINDLABEL, and pbx_extension_helper().
02272 { 02273 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL); 02274 }
int ast_func_read | ( | struct ast_channel * | chan, | |
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 1517 of file pbx.c.
References ast_custom_function_find(), ast_log(), func_args(), LOG_ERROR, and ast_custom_function::read.
01518 { 01519 char *args = func_args(function); 01520 struct ast_custom_function *acfptr = ast_custom_function_find(function); 01521 01522 if (acfptr == NULL) 01523 ast_log(LOG_ERROR, "Function %s not registered\n", function); 01524 else if (!acfptr->read) 01525 ast_log(LOG_ERROR, "Function %s cannot be read\n", function); 01526 else 01527 return acfptr->read(chan, function, args, workspace, len); 01528 return -1; 01529 }
int ast_func_write | ( | struct ast_channel * | chan, | |
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 1531 of file pbx.c.
References ast_custom_function_find(), ast_log(), func_args(), LOG_ERROR, and ast_custom_function::write.
01532 { 01533 char *args = func_args(function); 01534 struct ast_custom_function *acfptr = ast_custom_function_find(function); 01535 01536 if (acfptr == NULL) 01537 ast_log(LOG_ERROR, "Function %s not registered\n", function); 01538 else if (!acfptr->write) 01539 ast_log(LOG_ERROR, "Function %s cannot be written to\n", function); 01540 else 01541 return acfptr->write(chan, function, args, value); 01542 01543 return -1; 01544 }
const char* ast_get_context_name | ( | struct ast_context * | con | ) |
const char* ast_get_context_registrar | ( | struct ast_context * | c | ) |
Definition at line 6125 of file pbx.c.
References ast_context::registrar.
06126 { 06127 return c ? c->registrar : NULL; 06128 }
const char* ast_get_extension_app | ( | struct ast_exten * | e | ) |
Definition at line 6155 of file pbx.c.
References ast_exten::app.
06156 { 06157 return e ? e->app : NULL; 06158 }
void* ast_get_extension_app_data | ( | struct ast_exten * | e | ) |
Definition at line 6160 of file pbx.c.
References ast_exten::data.
06161 { 06162 return e ? e->data : NULL; 06163 }
const char* ast_get_extension_cidmatch | ( | struct ast_exten * | e | ) |
Definition at line 6150 of file pbx.c.
References ast_exten::cidmatch.
06151 { 06152 return e ? e->cidmatch : NULL; 06153 }
struct ast_context* ast_get_extension_context | ( | struct ast_exten * | exten | ) | [read] |
Definition at line 6092 of file pbx.c.
References ast_exten::parent.
06093 { 06094 return exten ? exten->parent : NULL; 06095 }
const char* ast_get_extension_label | ( | struct ast_exten * | e | ) |
int ast_get_extension_matchcid | ( | struct ast_exten * | e | ) |
Definition at line 6145 of file pbx.c.
References ast_exten::matchcid.
06146 { 06147 return e ? e->matchcid : 0; 06148 }
const char* ast_get_extension_name | ( | struct ast_exten * | exten | ) |
Definition at line 6097 of file pbx.c.
References ast_exten::exten.
06098 { 06099 return exten ? exten->exten : NULL; 06100 }
int ast_get_extension_priority | ( | struct ast_exten * | exten | ) |
Definition at line 6117 of file pbx.c.
References ast_exten::priority.
06118 { 06119 return exten ? exten->priority : -1; 06120 }
const char* ast_get_extension_registrar | ( | struct ast_exten * | e | ) |
Definition at line 6130 of file pbx.c.
References ast_exten::registrar.
06131 { 06132 return e ? e->registrar : NULL; 06133 }
int ast_get_hint | ( | char * | hint, | |
int | hintsize, | |||
char * | name, | |||
int | namesize, | |||
struct ast_channel * | c, | |||
const char * | context, | |||
const char * | exten | |||
) |
If an extension 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 2244 of file pbx.c.
References ast_get_extension_app(), ast_get_extension_app_data(), and ast_hint_extension().
02245 { 02246 struct ast_exten *e = ast_hint_extension(c, context, exten); 02247 02248 if (e) { 02249 if (hint) 02250 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 02251 if (name) { 02252 const char *tmp = ast_get_extension_app_data(e); 02253 if (tmp) 02254 ast_copy_string(name, tmp, namesize); 02255 } 02256 return -1; 02257 } 02258 return 0; 02259 }
const char* ast_get_ignorepat_name | ( | struct ast_ignorepat * | ip | ) |
Definition at line 6112 of file pbx.c.
References ast_ignorepat::pattern.
06113 { 06114 return ip ? ip->pattern : NULL; 06115 }
const char* ast_get_ignorepat_registrar | ( | struct ast_ignorepat * | ip | ) |
Definition at line 6140 of file pbx.c.
References ast_ignorepat::registrar.
06141 { 06142 return ip ? ip->registrar : NULL; 06143 }
const char* ast_get_include_name | ( | struct ast_include * | include | ) |
const char* ast_get_include_registrar | ( | struct ast_include * | i | ) |
Definition at line 6135 of file pbx.c.
References ast_include::registrar.
06136 { 06137 return i ? i->registrar : NULL; 06138 }
const char* ast_get_switch_data | ( | struct ast_sw * | sw | ) |
Definition at line 6170 of file pbx.c.
References ast_sw::data.
06171 { 06172 return sw ? sw->data : NULL; 06173 }
const char* ast_get_switch_name | ( | struct ast_sw * | sw | ) |
Definition at line 6165 of file pbx.c.
References ast_sw::name.
06166 { 06167 return sw ? sw->name : NULL; 06168 }
const char* ast_get_switch_registrar | ( | struct ast_sw * | sw | ) |
Definition at line 6175 of file pbx.c.
References ast_sw::registrar.
06176 { 06177 return sw ? sw->registrar : NULL; 06178 }
int ast_goto_if_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) |
Definition at line 6264 of file pbx.c.
References __ast_goto_if_exists().
06265 { 06266 return __ast_goto_if_exists(chan, context, exten, priority, 0); 06267 }
void ast_hint_state_changed | ( | const char * | device | ) |
Definition at line 1996 of file pbx.c.
References ast_extension_state2(), ast_get_extension_app(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_MAX_EXTENSION, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_exten::exten, ast_hint::exten, ast_hint::laststate, ast_state_cb::next, ast_exten::parent, parse(), statecbs, and strsep().
01997 { 01998 struct ast_hint *hint; 01999 02000 AST_LIST_LOCK(&hints); 02001 02002 AST_LIST_TRAVERSE(&hints, hint, list) { 02003 struct ast_state_cb *cblist; 02004 char buf[AST_MAX_EXTENSION]; 02005 char *parse = buf; 02006 char *cur; 02007 int state; 02008 02009 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf)); 02010 while ( (cur = strsep(&parse, "&")) ) { 02011 if (!strcasecmp(cur, device)) 02012 break; 02013 } 02014 if (!cur) 02015 continue; 02016 02017 /* Get device state for this hint */ 02018 state = ast_extension_state2(hint->exten); 02019 02020 if ((state == -1) || (state == hint->laststate)) 02021 continue; 02022 02023 /* Device state changed since last check - notify the watchers */ 02024 02025 /* For general callbacks */ 02026 for (cblist = statecbs; cblist; cblist = cblist->next) 02027 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 02028 02029 /* For extension callbacks */ 02030 for (cblist = hint->callbacks; cblist; cblist = cblist->next) 02031 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data); 02032 02033 hint->laststate = state; /* record we saw the change */ 02034 } 02035 02036 AST_LIST_UNLOCK(&hints); 02037 }
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 4511 of file pbx.c.
References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.
04512 { 04513 struct ast_context *con = ast_context_find(context); 04514 if (con) { 04515 struct ast_ignorepat *pat; 04516 for (pat = con->ignorepats; pat; pat = pat->next) { 04517 if (ast_extension_match(pat->pattern, pattern)) 04518 return 1; 04519 } 04520 } 04521 04522 return 0; 04523 }
int ast_lock_context | ( | struct ast_context * | con | ) |
Locks a given context.
con | context to lock |
0 | on success | |
-1 | on failure |
Definition at line 6074 of file pbx.c.
References ast_mutex_lock(), and ast_context::lock.
06075 { 06076 return ast_mutex_lock(&con->lock); 06077 }
int ast_lock_contexts | ( | void | ) |
Locks the context list.
0 | on success | |
-1 | on error |
Definition at line 6061 of file pbx.c.
References ast_mutex_lock().
06062 { 06063 return ast_mutex_lock(&conlock); 06064 }
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 2281 of file pbx.c.
References E_MATCHMORE, and pbx_extension_helper().
02282 { 02283 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE); 02284 }
void ast_merge_contexts_and_delete | ( | struct ast_context ** | extcontexts, | |
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 pointer | |
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 3906 of file pbx.c.
References __ast_context_destroy(), ast_calloc, AST_EXTENSION_REMOVED, ast_hint_extension(), AST_LIST_HEAD_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_state_cb::callback, ast_hint::callbacks, context, contexts, ast_state_cb::data, ast_exten::exten, ast_hint::exten, exten, free, ast_hint::laststate, LOG_DEBUG, LOG_WARNING, ast_state_cb::next, ast_context::next, option_debug, ast_exten::parent, and ast_context::registrar.
03907 { 03908 struct ast_context *tmp, *lasttmp = NULL; 03909 struct store_hints store = AST_LIST_HEAD_INIT_VALUE; 03910 struct store_hint *this; 03911 struct ast_hint *hint; 03912 struct ast_exten *exten; 03913 int length; 03914 struct ast_state_cb *thiscb, *prevcb; 03915 03916 /* it is very important that this function hold the hint list lock _and_ the conlock 03917 during its operation; not only do we need to ensure that the list of contexts 03918 and extensions does not change, but also that no hint callbacks (watchers) are 03919 added or removed during the merge/delete process 03920 03921 in addition, the locks _must_ be taken in this order, because there are already 03922 other code paths that use this order 03923 */ 03924 ast_mutex_lock(&conlock); 03925 AST_LIST_LOCK(&hints); 03926 03927 /* preserve all watchers for hints associated with this registrar */ 03928 AST_LIST_TRAVERSE(&hints, hint, list) { 03929 if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) { 03930 length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this); 03931 if (!(this = ast_calloc(1, length))) 03932 continue; 03933 this->callbacks = hint->callbacks; 03934 hint->callbacks = NULL; 03935 this->laststate = hint->laststate; 03936 this->context = this->data; 03937 strcpy(this->data, hint->exten->parent->name); 03938 this->exten = this->data + strlen(this->context) + 1; 03939 strcpy(this->exten, hint->exten->exten); 03940 AST_LIST_INSERT_HEAD(&store, this, list); 03941 } 03942 } 03943 03944 tmp = *extcontexts; 03945 if (registrar) { 03946 /* XXX remove previous contexts from same registrar */ 03947 if (option_debug) 03948 ast_log(LOG_DEBUG, "must remove any reg %s\n", registrar); 03949 __ast_context_destroy(NULL,registrar); 03950 while (tmp) { 03951 lasttmp = tmp; 03952 tmp = tmp->next; 03953 } 03954 } else { 03955 /* XXX remove contexts with the same name */ 03956 while (tmp) { 03957 ast_log(LOG_WARNING, "must remove %s reg %s\n", tmp->name, tmp->registrar); 03958 __ast_context_destroy(tmp,tmp->registrar); 03959 lasttmp = tmp; 03960 tmp = tmp->next; 03961 } 03962 } 03963 if (lasttmp) { 03964 lasttmp->next = contexts; 03965 contexts = *extcontexts; 03966 *extcontexts = NULL; 03967 } else 03968 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n"); 03969 03970 /* restore the watchers for hints that can be found; notify those that 03971 cannot be restored 03972 */ 03973 while ((this = AST_LIST_REMOVE_HEAD(&store, list))) { 03974 exten = ast_hint_extension(NULL, this->context, this->exten); 03975 /* Find the hint in the list of hints */ 03976 AST_LIST_TRAVERSE(&hints, hint, list) { 03977 if (hint->exten == exten) 03978 break; 03979 } 03980 if (!exten || !hint) { 03981 /* this hint has been removed, notify the watchers */ 03982 prevcb = NULL; 03983 thiscb = this->callbacks; 03984 while (thiscb) { 03985 prevcb = thiscb; 03986 thiscb = thiscb->next; 03987 prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data); 03988 free(prevcb); 03989 } 03990 } else { 03991 thiscb = this->callbacks; 03992 while (thiscb->next) 03993 thiscb = thiscb->next; 03994 thiscb->next = hint->callbacks; 03995 hint->callbacks = this->callbacks; 03996 hint->laststate = this->laststate; 03997 } 03998 free(this); 03999 } 04000 04001 AST_LIST_UNLOCK(&hints); 04002 ast_mutex_unlock(&conlock); 04003 04004 return; 04005 }
int ast_parseable_goto | ( | struct ast_channel * | chan, | |
const char * | goto_string | |||
) |
Definition at line 6274 of file pbx.c.
References ast_cdr_update(), ast_explicit_goto(), ast_findlabel_extension(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, exten, LOG_WARNING, ast_channel::priority, and strsep().
06275 { 06276 char *exten, *pri, *context; 06277 char *stringp; 06278 int ipri; 06279 int mode = 0; 06280 06281 if (ast_strlen_zero(goto_string)) { 06282 ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n"); 06283 return -1; 06284 } 06285 stringp = ast_strdupa(goto_string); 06286 context = strsep(&stringp, "|"); /* guaranteed non-null */ 06287 exten = strsep(&stringp, "|"); 06288 pri = strsep(&stringp, "|"); 06289 if (!exten) { /* Only a priority in this one */ 06290 pri = context; 06291 exten = NULL; 06292 context = NULL; 06293 } else if (!pri) { /* Only an extension and priority in this one */ 06294 pri = exten; 06295 exten = context; 06296 context = NULL; 06297 } 06298 if (*pri == '+') { 06299 mode = 1; 06300 pri++; 06301 } else if (*pri == '-') { 06302 mode = -1; 06303 pri++; 06304 } 06305 if (sscanf(pri, "%d", &ipri) != 1) { 06306 if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten, 06307 pri, chan->cid.cid_num)) < 1) { 06308 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri); 06309 return -1; 06310 } else 06311 mode = 0; 06312 } 06313 /* At this point we have a priority and maybe an extension and a context */ 06314 06315 if (mode) 06316 ipri = chan->priority + (ipri * mode); 06317 06318 ast_explicit_goto(chan, context, exten, ipri); 06319 ast_cdr_update(chan); 06320 return 0; 06321 06322 }
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 5116 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, outgoing_helper::account, async_stat::app, app_tmp::app, async_stat::appdata, ast_calloc, ast_cdr_alloc(), ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_init(), ast_cdr_setaccount(), ast_cdr_start(), ast_channel_lock, ast_channel_unlock, ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run_app(), ast_pthread_create, ast_set_variables(), AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verbose(), async_wait(), ast_channel::cdr, async_stat::chan, app_tmp::chan, app_tmp::data, free, ast_channel::hangupcause, LOG_WARNING, option_verbose, async_stat::p, ast_channel::pbx, app_tmp::t, async_stat::timeout, outgoing_helper::vars, and VERBOSE_PREFIX_4.
05117 { 05118 struct ast_channel *chan; 05119 struct app_tmp *tmp; 05120 int res = -1, cdr_res = -1; 05121 struct outgoing_helper oh; 05122 pthread_attr_t attr; 05123 05124 memset(&oh, 0, sizeof(oh)); 05125 oh.vars = vars; 05126 oh.account = account; 05127 05128 if (locked_channel) 05129 *locked_channel = NULL; 05130 if (ast_strlen_zero(app)) { 05131 res = -1; 05132 goto outgoing_app_cleanup; 05133 } 05134 if (sync) { 05135 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 05136 if (chan) { 05137 if (chan->cdr) { /* check if the channel already has a cdr record, if not give it one */ 05138 ast_log(LOG_WARNING, "%s already has a call record??\n", chan->name); 05139 } else { 05140 chan->cdr = ast_cdr_alloc(); /* allocate a cdr for the channel */ 05141 if(!chan->cdr) { 05142 /* allocation of the cdr failed */ 05143 free(chan->pbx); 05144 res = -1; 05145 goto outgoing_app_cleanup; 05146 } 05147 /* allocation of the cdr was successful */ 05148 ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */ 05149 ast_cdr_start(chan->cdr); 05150 } 05151 ast_set_variables(chan, vars); 05152 if (account) 05153 ast_cdr_setaccount(chan, account); 05154 if (chan->_state == AST_STATE_UP) { 05155 res = 0; 05156 if (option_verbose > 3) 05157 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 05158 tmp = ast_calloc(1, sizeof(*tmp)); 05159 if (!tmp) 05160 res = -1; 05161 else { 05162 ast_copy_string(tmp->app, app, sizeof(tmp->app)); 05163 if (appdata) 05164 ast_copy_string(tmp->data, appdata, sizeof(tmp->data)); 05165 tmp->chan = chan; 05166 if (sync > 1) { 05167 if (locked_channel) 05168 ast_channel_unlock(chan); 05169 ast_pbx_run_app(tmp); 05170 } else { 05171 pthread_attr_init(&attr); 05172 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05173 if (locked_channel) 05174 ast_channel_lock(chan); 05175 if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) { 05176 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 05177 free(tmp); 05178 if (locked_channel) 05179 ast_channel_unlock(chan); 05180 ast_hangup(chan); 05181 res = -1; 05182 } else { 05183 if (locked_channel) 05184 *locked_channel = chan; 05185 } 05186 pthread_attr_destroy(&attr); 05187 } 05188 } 05189 } else { 05190 if (option_verbose > 3) 05191 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 05192 if (chan->cdr) { /* update the cdr */ 05193 /* here we update the status of the call, which sould be busy. 05194 * if that fails then we set the status to failed */ 05195 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 05196 ast_cdr_failed(chan->cdr); 05197 } 05198 ast_hangup(chan); 05199 } 05200 } 05201 05202 if (res < 0) { /* the call failed for some reason */ 05203 if (*reason == 0) { /* if the call failed (not busy or no answer) 05204 * update the cdr with the failed message */ 05205 cdr_res = ast_pbx_outgoing_cdr_failed(); 05206 if (cdr_res != 0) { 05207 res = cdr_res; 05208 goto outgoing_app_cleanup; 05209 } 05210 } 05211 } 05212 05213 } else { 05214 struct async_stat *as; 05215 if (!(as = ast_calloc(1, sizeof(*as)))) { 05216 res = -1; 05217 goto outgoing_app_cleanup; 05218 } 05219 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 05220 if (!chan) { 05221 free(as); 05222 res = -1; 05223 goto outgoing_app_cleanup; 05224 } 05225 as->chan = chan; 05226 ast_copy_string(as->app, app, sizeof(as->app)); 05227 if (appdata) 05228 ast_copy_string(as->appdata, appdata, sizeof(as->appdata)); 05229 as->timeout = timeout; 05230 ast_set_variables(chan, vars); 05231 if (account) 05232 ast_cdr_setaccount(chan, account); 05233 /* Start a new thread, and get something handling this channel. */ 05234 pthread_attr_init(&attr); 05235 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05236 if (locked_channel) 05237 ast_channel_lock(chan); 05238 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 05239 ast_log(LOG_WARNING, "Failed to start async wait\n"); 05240 free(as); 05241 if (locked_channel) 05242 ast_channel_unlock(chan); 05243 ast_hangup(chan); 05244 res = -1; 05245 pthread_attr_destroy(&attr); 05246 goto outgoing_app_cleanup; 05247 } else { 05248 if (locked_channel) 05249 *locked_channel = chan; 05250 } 05251 pthread_attr_destroy(&attr); 05252 res = 0; 05253 } 05254 outgoing_app_cleanup: 05255 ast_variables_destroy(vars); 05256 return res; 05257 }
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 4960 of file pbx.c.
References __ast_request_and_dial(), ast_channel::_state, ast_calloc, ast_cdr_disposition(), ast_cdr_failed(), ast_cdr_setaccount(), ast_channel_alloc(), ast_channel_lock, ast_channel_unlock, ast_exists_extension(), ast_hangup(), ast_log(), ast_pbx_outgoing_cdr_failed(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create, ast_request_and_dial(), ast_set_variables(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_variables_destroy(), ast_verbose(), async_wait(), ast_channel::cdr, async_stat::chan, async_stat::context, ast_channel::context, free, ast_channel::hangupcause, LOAD_OH, LOG_ERROR, LOG_WARNING, option_verbose, async_stat::p, set_ext_pri(), async_stat::timeout, and VERBOSE_PREFIX_4.
04961 { 04962 struct ast_channel *chan; 04963 struct async_stat *as; 04964 int res = -1, cdr_res = -1; 04965 struct outgoing_helper oh; 04966 pthread_attr_t attr; 04967 04968 if (sync) { 04969 LOAD_OH(oh); 04970 chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); 04971 if (channel) { 04972 *channel = chan; 04973 if (chan) 04974 ast_channel_lock(chan); 04975 } 04976 if (chan) { 04977 if (chan->_state == AST_STATE_UP) { 04978 res = 0; 04979 if (option_verbose > 3) 04980 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 04981 04982 if (sync > 1) { 04983 if (channel) 04984 ast_channel_unlock(chan); 04985 if (ast_pbx_run(chan)) { 04986 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 04987 if (channel) 04988 *channel = NULL; 04989 ast_hangup(chan); 04990 res = -1; 04991 } 04992 } else { 04993 if (ast_pbx_start(chan)) { 04994 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 04995 if (channel) { 04996 *channel = NULL; 04997 ast_channel_unlock(chan); 04998 } 04999 ast_hangup(chan); 05000 res = -1; 05001 } 05002 } 05003 } else { 05004 if (option_verbose > 3) 05005 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 05006 05007 if (chan->cdr) { /* update the cdr */ 05008 /* here we update the status of the call, which sould be busy. 05009 * if that fails then we set the status to failed */ 05010 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) 05011 ast_cdr_failed(chan->cdr); 05012 } 05013 05014 if (channel) { 05015 *channel = NULL; 05016 ast_channel_unlock(chan); 05017 } 05018 ast_hangup(chan); 05019 } 05020 } 05021 05022 if (res < 0) { /* the call failed for some reason */ 05023 if (*reason == 0) { /* if the call failed (not busy or no answer) 05024 * update the cdr with the failed message */ 05025 cdr_res = ast_pbx_outgoing_cdr_failed(); 05026 if (cdr_res != 0) { 05027 res = cdr_res; 05028 goto outgoing_exten_cleanup; 05029 } 05030 } 05031 05032 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 05033 /* check if "failed" exists */ 05034 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 05035 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed"); 05036 if (chan) { 05037 if (!ast_strlen_zero(context)) 05038 ast_copy_string(chan->context, context, sizeof(chan->context)); 05039 set_ext_pri(chan, "failed", 1); 05040 ast_set_variables(chan, vars); 05041 if (account) 05042 ast_cdr_setaccount(chan, account); 05043 ast_pbx_run(chan); 05044 } 05045 } 05046 } 05047 } else { 05048 if (!(as = ast_calloc(1, sizeof(*as)))) { 05049 res = -1; 05050 goto outgoing_exten_cleanup; 05051 } 05052 chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name); 05053 if (channel) { 05054 *channel = chan; 05055 if (chan) 05056 ast_channel_lock(chan); 05057 } 05058 if (!chan) { 05059 free(as); 05060 res = -1; 05061 goto outgoing_exten_cleanup; 05062 } 05063 as->chan = chan; 05064 ast_copy_string(as->context, context, sizeof(as->context)); 05065 set_ext_pri(as->chan, exten, priority); 05066 as->timeout = timeout; 05067 ast_set_variables(chan, vars); 05068 if (account) 05069 ast_cdr_setaccount(chan, account); 05070 pthread_attr_init(&attr); 05071 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 05072 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 05073 ast_log(LOG_WARNING, "Failed to start async wait\n"); 05074 free(as); 05075 if (channel) { 05076 *channel = NULL; 05077 ast_channel_unlock(chan); 05078 } 05079 ast_hangup(chan); 05080 res = -1; 05081 pthread_attr_destroy(&attr); 05082 goto outgoing_exten_cleanup; 05083 } 05084 pthread_attr_destroy(&attr); 05085 res = 0; 05086 } 05087 outgoing_exten_cleanup: 05088 ast_variables_destroy(vars); 05089 return res; 05090 }
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 |
Definition at line 2637 of file pbx.c.
References __ast_pbx_run(), AST_PBX_CALL_LIMIT, AST_PBX_SUCCESS, decrease_call_count(), and increase_call_count().
02638 { 02639 enum ast_pbx_result res = AST_PBX_SUCCESS; 02640 02641 if (increase_call_count(c)) 02642 return AST_PBX_CALL_LIMIT; 02643 02644 res = __ast_pbx_run(c); 02645 decrease_call_count(); 02646 02647 return res; 02648 }
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 |
Definition at line 2611 of file pbx.c.
References ast_log(), AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create, increase_call_count(), LOG_WARNING, pbx_thread(), and t.
02612 { 02613 pthread_t t; 02614 pthread_attr_t attr; 02615 02616 if (!c) { 02617 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 02618 return AST_PBX_FAILED; 02619 } 02620 02621 if (increase_call_count(c)) 02622 return AST_PBX_CALL_LIMIT; 02623 02624 /* Start a new thread, and get something handling this channel. */ 02625 pthread_attr_init(&attr); 02626 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 02627 if (ast_pthread_create(&t, &attr, pbx_thread, c)) { 02628 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 02629 pthread_attr_destroy(&attr); 02630 return AST_PBX_FAILED; 02631 } 02632 pthread_attr_destroy(&attr); 02633 02634 return AST_PBX_SUCCESS; 02635 }
int ast_register_application | ( | const char * | app, | |
int(*)(struct ast_channel *, void *) | execute, | |||
const char * | synopsis, | |||
const char * | description | |||
) |
Register an application.
app | Short name of the application | |
execute | a function callback to execute the application. It should return non-zero if the channel needs to be hung up. | |
synopsis | a short description (one line synopsis) of the application | |
description | long description with all of the details about the use of the application |
0 | success | |
-1 | failure. |
Definition at line 2939 of file pbx.c.
References ast_calloc, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_verbose(), COLOR_BRCYAN, ast_app::description, ast_app::execute, LOG_WARNING, option_verbose, ast_app::synopsis, term_color(), and VERBOSE_PREFIX_2.
02940 { 02941 struct ast_app *tmp, *cur = NULL; 02942 char tmps[80]; 02943 int length; 02944 02945 AST_LIST_LOCK(&apps); 02946 AST_LIST_TRAVERSE(&apps, tmp, list) { 02947 if (!strcasecmp(app, tmp->name)) { 02948 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 02949 AST_LIST_UNLOCK(&apps); 02950 return -1; 02951 } 02952 } 02953 02954 length = sizeof(*tmp) + strlen(app) + 1; 02955 02956 if (!(tmp = ast_calloc(1, length))) { 02957 AST_LIST_UNLOCK(&apps); 02958 return -1; 02959 } 02960 02961 strcpy(tmp->name, app); 02962 tmp->execute = execute; 02963 tmp->synopsis = synopsis; 02964 tmp->description = description; 02965 02966 /* Store in alphabetical order */ 02967 AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) { 02968 if (strcasecmp(tmp->name, cur->name) < 0) { 02969 AST_LIST_INSERT_BEFORE_CURRENT(&apps, tmp, list); 02970 break; 02971 } 02972 } 02973 AST_LIST_TRAVERSE_SAFE_END 02974 if (!cur) 02975 AST_LIST_INSERT_TAIL(&apps, tmp, list); 02976 02977 if (option_verbose > 1) 02978 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 02979 02980 AST_LIST_UNLOCK(&apps); 02981 02982 return 0; 02983 }
int ast_register_switch | ( | struct ast_switch * | sw | ) |
Register an alternative dialplan switch.
sw | switch to register |
Definition at line 2989 of file pbx.c.
References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), LOG_WARNING, and ast_switch::name.
02990 { 02991 struct ast_switch *tmp; 02992 02993 AST_LIST_LOCK(&switches); 02994 AST_LIST_TRAVERSE(&switches, tmp, list) { 02995 if (!strcasecmp(tmp->name, sw->name)) { 02996 AST_LIST_UNLOCK(&switches); 02997 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 02998 return -1; 02999 } 03000 } 03001 AST_LIST_INSERT_TAIL(&switches, sw, list); 03002 AST_LIST_UNLOCK(&switches); 03003 03004 return 0; 03005 }
int ast_spawn_extension | ( | struct ast_channel * | c, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | callerid | |||
) |
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 |
0 | on success | |
-1 | on failure. |
Definition at line 2286 of file pbx.c.
References E_SPAWN, and pbx_extension_helper().
02287 { 02288 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN); 02289 }
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 6079 of file pbx.c.
References ast_mutex_unlock(), and ast_context::lock.
06080 { 06081 return ast_mutex_unlock(&con->lock); 06082 }
int ast_unlock_contexts | ( | void | ) |
Unlocks contexts.
0 | on success | |
-1 | on failure |
Definition at line 6066 of file pbx.c.
References ast_mutex_unlock().
06067 { 06068 return ast_mutex_unlock(&conlock); 06069 }
int ast_unregister_application | ( | const char * | app | ) |
Unregister an application.
app | name of the application (does not have to be the same string as the one that was registered) |
0 | success | |
-1 | failure |
Definition at line 3820 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verbose(), free, option_verbose, and VERBOSE_PREFIX_2.
03821 { 03822 struct ast_app *tmp; 03823 03824 AST_LIST_LOCK(&apps); 03825 AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) { 03826 if (!strcasecmp(app, tmp->name)) { 03827 AST_LIST_REMOVE_CURRENT(&apps, list); 03828 if (option_verbose > 1) 03829 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name); 03830 free(tmp); 03831 break; 03832 } 03833 } 03834 AST_LIST_TRAVERSE_SAFE_END 03835 AST_LIST_UNLOCK(&apps); 03836 03837 return tmp ? 0 : -1; 03838 }
void ast_unregister_switch | ( | struct ast_switch * | sw | ) |
Unregister an alternative switch.
sw | switch to unregister |
Definition at line 3007 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.
03008 { 03009 AST_LIST_LOCK(&switches); 03010 AST_LIST_REMOVE(&switches, sw, list); 03011 AST_LIST_UNLOCK(&switches); 03012 }
struct ast_exten* ast_walk_context_extensions | ( | struct ast_context * | con, | |
struct ast_exten * | priority | |||
) | [read] |
Definition at line 6188 of file pbx.c.
References ast_exten::next, and ast_context::root.
06190 { 06191 if (!exten) 06192 return con ? con->root : NULL; 06193 else 06194 return exten->next; 06195 }
struct ast_ignorepat* ast_walk_context_ignorepats | ( | struct ast_context * | con, | |
struct ast_ignorepat * | ip | |||
) | [read] |
Definition at line 6221 of file pbx.c.
References ast_context::ignorepats, and ast_ignorepat::next.
06223 { 06224 if (!ip) 06225 return con ? con->ignorepats : NULL; 06226 else 06227 return ip->next; 06228 }
struct ast_include* ast_walk_context_includes | ( | struct ast_context * | con, | |
struct ast_include * | inc | |||
) | [read] |
Definition at line 6212 of file pbx.c.
References ast_context::includes, and ast_include::next.
06214 { 06215 if (!inc) 06216 return con ? con->includes : NULL; 06217 else 06218 return inc->next; 06219 }
struct ast_sw* ast_walk_context_switches | ( | struct ast_context * | con, | |
struct ast_sw * | sw | |||
) | [read] |
Definition at line 6197 of file pbx.c.
References AST_LIST_FIRST, and AST_LIST_NEXT.
06199 { 06200 if (!sw) 06201 return con ? AST_LIST_FIRST(&con->alts) : NULL; 06202 else 06203 return AST_LIST_NEXT(sw, list); 06204 }
struct ast_context* ast_walk_contexts | ( | struct ast_context * | con | ) | [read] |
struct ast_exten* ast_walk_extension_priorities | ( | struct ast_exten * | exten, | |
struct ast_exten * | priority | |||
) | [read] |
Definition at line 6206 of file pbx.c.
References ast_exten::peer.
06208 { 06209 return priority ? priority->peer : exten; 06210 }
void pbx_builtin_clear_globals | ( | void | ) |
Definition at line 5937 of file pbx.c.
References AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), ast_var_delete(), and globals.
05938 { 05939 struct ast_var_t *vardata; 05940 05941 ast_mutex_lock(&globalslock); 05942 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries))) 05943 ast_var_delete(vardata); 05944 ast_mutex_unlock(&globalslock); 05945 }
const char* pbx_builtin_getvar_helper | ( | struct ast_channel * | chan, | |
const char * | name | |||
) |
Definition at line 5737 of file pbx.c.
References AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_var_name(), ast_var_value(), globals, and ast_channel::varshead.
05738 { 05739 struct ast_var_t *variables; 05740 const char *ret = NULL; 05741 int i; 05742 struct varshead *places[2] = { NULL, &globals }; 05743 05744 if (!name) 05745 return NULL; 05746 if (chan) 05747 places[0] = &chan->varshead; 05748 05749 for (i = 0; i < 2; i++) { 05750 if (!places[i]) 05751 continue; 05752 if (places[i] == &globals) 05753 ast_mutex_lock(&globalslock); 05754 AST_LIST_TRAVERSE(places[i], variables, entries) { 05755 if (!strcmp(name, ast_var_name(variables))) { 05756 ret = ast_var_value(variables); 05757 break; 05758 } 05759 } 05760 if (places[i] == &globals) 05761 ast_mutex_unlock(&globalslock); 05762 if (ret) 05763 break; 05764 } 05765 05766 return ret; 05767 }
void pbx_builtin_pushvar_helper | ( | struct ast_channel * | chan, | |
const char * | name, | |||
const char * | value | |||
) |
Definition at line 5769 of file pbx.c.
References ast_func_write(), AST_LIST_INSERT_HEAD, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_var_assign(), ast_verbose(), globals, LOG_WARNING, option_verbose, ast_channel::varshead, and VERBOSE_PREFIX_2.
05770 { 05771 struct ast_var_t *newvariable; 05772 struct varshead *headp; 05773 05774 if (name[strlen(name)-1] == ')') { 05775 char *function = ast_strdupa(name); 05776 05777 ast_log(LOG_WARNING, "Cannot push a value onto a function\n"); 05778 ast_func_write(chan, function, value); 05779 return; 05780 } 05781 05782 headp = (chan) ? &chan->varshead : &globals; 05783 05784 if (value) { 05785 if ((option_verbose > 1) && (headp == &globals)) 05786 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value); 05787 newvariable = ast_var_assign(name, value); 05788 if (headp == &globals) 05789 ast_mutex_lock(&globalslock); 05790 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 05791 if (headp == &globals) 05792 ast_mutex_unlock(&globalslock); 05793 } 05794 }
int pbx_builtin_serialize_variables | ( | struct ast_channel * | chan, | |
char * | buf, | |||
size_t | size | |||
) |
Definition at line 5710 of file pbx.c.
References ast_build_string(), AST_LIST_TRAVERSE, ast_log(), ast_var_name(), ast_var_value(), LOG_ERROR, total, var, and ast_channel::varshead.
05711 { 05712 struct ast_var_t *variables; 05713 const char *var, *val; 05714 int total = 0; 05715 05716 if (!chan) 05717 return 0; 05718 05719 memset(buf, 0, size); 05720 05721 AST_LIST_TRAVERSE(&chan->varshead, variables, entries) { 05722 if ((var=ast_var_name(variables)) && (val=ast_var_value(variables)) 05723 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */ 05724 ) { 05725 if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) { 05726 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 05727 break; 05728 } else 05729 total++; 05730 } else 05731 break; 05732 } 05733 05734 return total; 05735 }
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 5796 of file pbx.c.
References ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE, AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verbose(), globals, option_verbose, ast_channel::varshead, and VERBOSE_PREFIX_2.
05797 { 05798 struct ast_var_t *newvariable; 05799 struct varshead *headp; 05800 const char *nametail = name; 05801 05802 /* XXX may need locking on the channel ? */ 05803 if (name[strlen(name)-1] == ')') { 05804 char *function = ast_strdupa(name); 05805 05806 ast_func_write(chan, function, value); 05807 return; 05808 } 05809 05810 headp = (chan) ? &chan->varshead : &globals; 05811 05812 /* For comparison purposes, we have to strip leading underscores */ 05813 if (*nametail == '_') { 05814 nametail++; 05815 if (*nametail == '_') 05816 nametail++; 05817 } 05818 05819 if (headp == &globals) 05820 ast_mutex_lock(&globalslock); 05821 AST_LIST_TRAVERSE (headp, newvariable, entries) { 05822 if (strcasecmp(ast_var_name(newvariable), nametail) == 0) { 05823 /* there is already such a variable, delete it */ 05824 AST_LIST_REMOVE(headp, newvariable, entries); 05825 ast_var_delete(newvariable); 05826 break; 05827 } 05828 } 05829 05830 if (value) { 05831 if ((option_verbose > 1) && (headp == &globals)) 05832 ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value); 05833 newvariable = ast_var_assign(name, value); 05834 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 05835 } 05836 05837 if (headp == &globals) 05838 ast_mutex_unlock(&globalslock); 05839 }
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 5947 of file pbx.c.
References ast_strlen_zero().
05948 { 05949 if (ast_strlen_zero(condition)) /* NULL or empty strings are false */ 05950 return 0; 05951 else if (*condition >= '0' && *condition <= '9') /* Numbers are evaluated for truth */ 05952 return atoi(condition); 05953 else /* Strings are true */ 05954 return 1; 05955 }
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 510 of file pbx.c.
References ast_channel::appl, ast_cdr_setapp(), ast_check_hangup(), ast_channel::cdr, ast_channel::data, and ast_app::execute.
00513 { 00514 int res; 00515 00516 const char *saved_c_appl; 00517 const char *saved_c_data; 00518 00519 if (c->cdr && !ast_check_hangup(c)) 00520 ast_cdr_setapp(c->cdr, app->name, data); 00521 00522 /* save channel values */ 00523 saved_c_appl= c->appl; 00524 saved_c_data= c->data; 00525 00526 c->appl = app->name; 00527 c->data = data; 00528 /* XXX remember what to to when we have linked apps to modules */ 00529 if (app->module) { 00530 /* XXX LOCAL_USER_ADD(app->module) */ 00531 } 00532 res = app->execute(c, data); 00533 if (app->module) { 00534 /* XXX LOCAL_USER_REMOVE(app->module) */ 00535 } 00536 /* restore channel values */ 00537 c->appl = saved_c_appl; 00538 c->data = saved_c_data; 00539 return res; 00540 }
struct ast_app* pbx_findapp | ( | const char * | app | ) | [read] |
Look up an application.
app | name of the app |
Definition at line 548 of file pbx.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, and AST_LIST_UNLOCK.
00549 { 00550 struct ast_app *tmp; 00551 00552 AST_LIST_LOCK(&apps); 00553 AST_LIST_TRAVERSE(&apps, tmp, list) { 00554 if (!strcasecmp(tmp->name, app)) 00555 break; 00556 } 00557 AST_LIST_UNLOCK(&apps); 00558 00559 return tmp; 00560 }
void pbx_retrieve_variable | ( | struct ast_channel * | c, | |
const char * | var, | |||
char ** | ret, | |||
char * | workspace, | |||
int | workspacelen, | |||
struct varshead * | headp | |||
) |
pbx_retrieve_variable: Support for Asterisk built-in variables ---
Definition at line 1128 of file pbx.c.
References ast_config_AST_SYSTEM_NAME, ast_get_hint(), AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_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, ast_channel::hangupcause, offset, parse_variable_name(), ast_channel::priority, s, substring(), and ast_channel::varshead.
01129 { 01130 const char not_found = '\0'; 01131 char *tmpvar; 01132 const char *s; /* the result */ 01133 int offset, length; 01134 int i, need_substring; 01135 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */ 01136 01137 if (c) { 01138 places[0] = &c->varshead; 01139 } 01140 /* 01141 * Make a copy of var because parse_variable_name() modifies the string. 01142 * Then if called directly, we might need to run substring() on the result; 01143 * remember this for later in 'need_substring', 'offset' and 'length' 01144 */ 01145 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */ 01146 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */); 01147 01148 /* 01149 * Look first into predefined variables, then into variable lists. 01150 * Variable 's' points to the result, according to the following rules: 01151 * s == ¬_found (set at the beginning) means that we did not find a 01152 * matching variable and need to look into more places. 01153 * If s != ¬_found, s is a valid result string as follows: 01154 * s = NULL if the variable does not have a value; 01155 * you typically do this when looking for an unset predefined variable. 01156 * s = workspace if the result has been assembled there; 01157 * typically done when the result is built e.g. with an snprintf(), 01158 * so we don't need to do an additional copy. 01159 * s != workspace in case we have a string, that needs to be copied 01160 * (the ast_copy_string is done once for all at the end). 01161 * Typically done when the result is already available in some string. 01162 */ 01163 s = ¬_found; /* default value */ 01164 if (c) { /* This group requires a valid channel */ 01165 /* Names with common parts are looked up a piece at a time using strncmp. */ 01166 if (!strncmp(var, "CALL", 4)) { 01167 if (!strncmp(var + 4, "ING", 3)) { 01168 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */ 01169 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres); 01170 s = workspace; 01171 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */ 01172 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2); 01173 s = workspace; 01174 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */ 01175 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton); 01176 s = workspace; 01177 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */ 01178 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns); 01179 s = workspace; 01180 } 01181 } 01182 } else if (!strcmp(var, "HINT")) { 01183 s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL; 01184 } else if (!strcmp(var, "HINTNAME")) { 01185 s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL; 01186 } else if (!strcmp(var, "EXTEN")) { 01187 s = c->exten; 01188 } else if (!strcmp(var, "CONTEXT")) { 01189 s = c->context; 01190 } else if (!strcmp(var, "PRIORITY")) { 01191 snprintf(workspace, workspacelen, "%d", c->priority); 01192 s = workspace; 01193 } else if (!strcmp(var, "CHANNEL")) { 01194 s = c->name; 01195 } else if (!strcmp(var, "UNIQUEID")) { 01196 s = c->uniqueid; 01197 } else if (!strcmp(var, "HANGUPCAUSE")) { 01198 snprintf(workspace, workspacelen, "%d", c->hangupcause); 01199 s = workspace; 01200 } 01201 } 01202 if (s == ¬_found) { /* look for more */ 01203 if (!strcmp(var, "EPOCH")) { 01204 snprintf(workspace, workspacelen, "%u",(int)time(NULL)); 01205 s = workspace; 01206 } else if (!strcmp(var, "SYSTEMNAME")) { 01207 s = ast_config_AST_SYSTEM_NAME; 01208 } 01209 } 01210 /* if not found, look into chanvars or global vars */ 01211 for (i = 0; s == ¬_found && i < (sizeof(places) / sizeof(places[0])); i++) { 01212 struct ast_var_t *variables; 01213 if (!places[i]) 01214 continue; 01215 if (places[i] == &globals) 01216 ast_mutex_lock(&globalslock); 01217 AST_LIST_TRAVERSE(places[i], variables, entries) { 01218 if (strcasecmp(ast_var_name(variables), var)==0) { 01219 s = ast_var_value(variables); 01220 break; 01221 } 01222 } 01223 if (places[i] == &globals) 01224 ast_mutex_unlock(&globalslock); 01225 } 01226 if (s == ¬_found || s == NULL) 01227 *ret = NULL; 01228 else { 01229 if (s != workspace) 01230 ast_copy_string(workspace, s, workspacelen); 01231 *ret = workspace; 01232 if (need_substring) 01233 *ret = substring(*ret, offset, length, workspace, workspacelen); 01234 } 01235 }
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 2655 of file pbx.c.
References autofallthrough.
02656 { 02657 int oldval = autofallthrough; 02658 autofallthrough = newval; 02659 return oldval; 02660 }
void pbx_substitute_variables_helper | ( | struct ast_channel * | c, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 1739 of file pbx.c.
References pbx_substitute_variables_helper_full(), and ast_channel::varshead.
01740 { 01741 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count); 01742 }
void pbx_substitute_variables_varshead | ( | struct varshead * | headp, | |
const char * | cp1, | |||
char * | cp2, | |||
int | count | |||
) |
Definition at line 1744 of file pbx.c.
References pbx_substitute_variables_helper_full().
01745 { 01746 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count); 01747 }