#include "asterisk/sched.h"
#include "asterisk/channel.h"
Include dependency graph for pbx.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.
Data Structures | |
| struct | ast_custom_function |
| struct | ast_pbx |
| struct | ast_switch |
| struct | ast_timing |
| struct | cfextension_states |
Defines | |
| #define | AST_MAX_APP 32 |
| #define | AST_PBX_KEEP 0 |
| #define | AST_PBX_KEEPALIVE 10 |
| #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) |
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 } |
| enum | ast_pbx_result { AST_PBX_SUCCESS = 0, AST_PBX_FAILED = -1, AST_PBX_CALL_LIMIT = -2 } |
Functions | |
| int | ast_active_calls (void) |
| 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) |
| 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) |
| 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, char *context, char *exten, int priority) |
| int | ast_build_timing (struct ast_timing *i, char *info) |
| int | ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| int | ast_check_timing (struct ast_timing *i) |
| int | ast_context_add_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
| 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) |
| int | ast_context_add_include2 (struct ast_context *con, const char *include, const char *registrar) |
| int | ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar) |
| int | ast_context_add_switch2 (struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar) |
| ast_context * | ast_context_create (struct ast_context **extcontexts, const char *name, const char *registrar) |
| void | ast_context_destroy (struct ast_context *con, const char *registrar) |
| ast_context * | ast_context_find (const char *name) |
| int | ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar) |
| 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) |
| int | ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar) |
| int | ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar) |
| 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_verify_includes (struct ast_context *con) |
| ast_custom_function * | ast_custom_function_find (char *name) |
| int | ast_custom_function_register (struct ast_custom_function *acf) |
| int | ast_custom_function_unregister (struct ast_custom_function *acf) |
| int | ast_exec_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| int | ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| 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) |
| int | ast_extension_patmatch (const char *pattern, const char *data) |
| int | ast_extension_state (struct ast_channel *c, char *context, char *exten) |
| ast_extension_state: Check extension state for an extension by using hint | |
| const char * | ast_extension_state2str (int extension_state) |
| ast_extension_state2str: Return extension_state as string | |
| int | ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type callback, void *data) |
| ast_extension_state_add: Add watcher for extension states | |
| int | ast_extension_state_del (int id, ast_state_cb_type callback) |
| ast_extension_state_del: Remove a watcher from the callback list | |
| int | ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid) |
| int | ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid) |
| char * | ast_func_read (struct ast_channel *chan, const char *in, char *workspace, size_t len) |
| void | ast_func_write (struct ast_channel *chan, const char *in, const char *value) |
| 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) |
| 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) |
| ast_get_hint: Get hint for channel | |
| 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, char *context, char *exten, int priority) |
| void | ast_hint_state_changed (const char *device) |
| int | ast_ignore_pattern (const char *context, const char *pattern) |
| int | ast_lock_context (struct ast_context *con) |
| int | ast_lock_contexts (void) |
| int | ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| void | ast_merge_contexts_and_delete (struct ast_context **extcontexts, const char *registrar) |
| 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) |
| enum ast_pbx_result | ast_pbx_start (struct ast_channel *c) |
| int | ast_register_application (const char *app, int(*execute)(struct ast_channel *, void *), const char *synopsis, const char *description) |
| Dynamically register a new dial plan application. | |
| int | ast_register_switch (struct ast_switch *sw) |
| int | ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| int | ast_unlock_context (struct ast_context *con) |
| int | ast_unlock_contexts (void) |
| int | ast_unregister_application (const char *app) |
| void | ast_unregister_switch (struct ast_switch *sw) |
| ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority) |
| ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
| ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
| ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
| ast_context * | ast_walk_contexts (struct ast_context *con) |
| ast_exten * | ast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority) |
| void | pbx_builtin_clear_globals (void) |
| 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 (char *condition) |
| int | pbx_exec (struct ast_channel *c, struct ast_app *app, void *data, int newstack) |
| ast_app * | pbx_findapp (const char *app) |
| Find application handle in linked list. | |
| 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) |
Variables | |
| static struct cfextension_states | extension_states [] |
Definition in file pbx.h.
| #define AST_MAX_APP 32 |
Max length of an application
Definition at line 37 of file pbx.h.
Referenced by handle_show_application(), and handle_show_function().
| #define AST_PBX_KEEPALIVE 10 |
Special return values from applications to the PBX
Definition at line 40 of file pbx.h.
Referenced by __ast_pbx_run(), agi_handle_command(), builtin_blindtransfer(), dial_exec_full(), feature_exec_app(), macro_exec(), 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(), dial_exec_full(), feature_exec_app(), park_exec(), and try_calling().
| #define PRIORITY_HINT -1 |
Special Priority for an hint
Definition at line 44 of file pbx.h.
Referenced by ast_add_extension2(), ast_context_remove_extension2(), ast_hint_extension(), destroy_exten(), handle_context_add_extension(), handle_context_remove_extension(), handle_save_dialplan(), pbx_load_module(), and show_dialplan_helper().
| typedef int(*) ast_state_cb_type(char *context, char *id, enum ast_extension_states state, void *data) |
| enum ast_extension_states |
Extension states
Definition at line 47 of file pbx.h.
00047 { 00048 /*! Extension removed */ 00049 AST_EXTENSION_REMOVED = -2, 00050 /*! Extension hint removed */ 00051 AST_EXTENSION_DEACTIVATED = -1, 00052 /*! No device INUSE or BUSY */ 00053 AST_EXTENSION_NOT_INUSE = 0, 00054 /*! One or more devices INUSE */ 00055 AST_EXTENSION_INUSE = 1 << 0, 00056 /*! All devices BUSY */ 00057 AST_EXTENSION_BUSY = 1 << 1, 00058 /*! All devices UNAVAILABLE/UNREGISTERED */ 00059 AST_EXTENSION_UNAVAILABLE = 1 << 2, 00060 /*! All devices RINGING */ 00061 AST_EXTENSION_RINGING = 1 << 3, 00062 };
| enum ast_pbx_result |
Definition at line 209 of file pbx.h.
00209 { 00210 AST_PBX_SUCCESS = 0, 00211 AST_PBX_FAILED = -1, 00212 AST_PBX_CALL_LIMIT = -2, 00213 };
| int ast_active_calls | ( | void | ) |
Definition at line 2584 of file pbx.c.
References countcalls.
Referenced by handle_chanlist().
02585 { 02586 return countcalls; 02587 }
| 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 | |||
| ) |
| context | context to add the extension to | |
| replace | ||
| extension | extension to add | |
| priority | priority level of extension addition | |
| label | extension label | |
| callerid | callerid of extension | |
| application | application to run on the extension with that priority level | |
| data | data to pass to the application | |
| datad | ||
| registrar | who registered the extension Add and extension to an extension context. Callerid is a pattern to match CallerID, or NULL to match any callerid Returns 0 on success, -1 on failure |
Definition at line 4527 of file pbx.c.
References ast_add_extension2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
Referenced by handle_context_add_extension(), and register_peer_exten().
04529 { 04530 struct ast_context *c; 04531 04532 if (ast_lock_contexts()) { 04533 errno = EBUSY; 04534 return -1; 04535 } 04536 04537 c = ast_walk_contexts(NULL); 04538 while (c) { 04539 if (!strcmp(context, ast_get_context_name(c))) { 04540 int ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 04541 application, data, datad, registrar); 04542 ast_unlock_contexts(); 04543 return ret; 04544 } 04545 c = ast_walk_contexts(c); 04546 } 04547 04548 ast_unlock_contexts(); 04549 errno = ENOENT; 04550 return -1; 04551 }
| 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 | |||
| ) |
For details about the arguements, check ast_add_extension()
Definition at line 4666 of file pbx.c.
References ast_add_hint(), ast_change_hint(), AST_LIST_FIRST, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_exten::cidmatch, ast_exten::data, ast_exten::datad, el, ext_strncpy(), ast_exten::exten, free, globals, ast_context::lock, LOG, LOG_ERROR, LOG_WARNING, malloc, ast_exten::matchcid, ast_context::name, ast_exten::next, null_datad(), pbx_substitute_variables_varshead(), ast_exten::peer, ast_exten::priority, PRIORITY_HINT, ast_context::registrar, ast_context::root, and VAR_BUF_SIZE.
Referenced by __build_step(), ast_add_extension(), ast_park_call(), do_parking_thread(), fillin_process(), handle_macro(), load_config(), and pbx_load_module().
04670 { 04671 04672 #define LOG do { if (option_debug) {\ 04673 if (tmp->matchcid) { \ 04674 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \ 04675 } else { \ 04676 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \ 04677 } \ 04678 } \ 04679 if (option_verbose > 2) { \ 04680 if (tmp->matchcid) { \ 04681 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \ 04682 } else { \ 04683 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \ 04684 } \ 04685 } } while(0) 04686 04687 /* 04688 * This is a fairly complex routine. Different extensions are kept 04689 * in order by the extension number. Then, extensions of different 04690 * priorities (same extension) are kept in a list, according to the 04691 * peer pointer. 04692 */ 04693 struct ast_exten *tmp, *e, *el = NULL, *ep = NULL; 04694 int res; 04695 int length; 04696 char *p; 04697 char expand_buf[VAR_BUF_SIZE] = { 0, }; 04698 04699 /* if we are adding a hint, and there are global variables, and the hint 04700 contains variable references, then expand them 04701 */ 04702 ast_mutex_lock(&globalslock); 04703 if ((priority == PRIORITY_HINT) && AST_LIST_FIRST(&globals) && strstr(application, "${")) { 04704 pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf)); 04705 application = expand_buf; 04706 } 04707 ast_mutex_unlock(&globalslock); 04708 04709 length = sizeof(struct ast_exten); 04710 length += strlen(extension) + 1; 04711 length += strlen(application) + 1; 04712 if (label) 04713 length += strlen(label) + 1; 04714 if (callerid) 04715 length += strlen(callerid) + 1; 04716 else 04717 length ++; 04718 04719 /* Be optimistic: Build the extension structure first */ 04720 if (datad == NULL) 04721 datad = null_datad; 04722 tmp = malloc(length); 04723 if (tmp) { 04724 memset(tmp, 0, length); 04725 p = tmp->stuff; 04726 if (label) { 04727 tmp->label = p; 04728 strcpy(tmp->label, label); 04729 p += strlen(label) + 1; 04730 } 04731 tmp->exten = p; 04732 p += ext_strncpy(tmp->exten, extension, strlen(extension) + 1) + 1; 04733 tmp->priority = priority; 04734 tmp->cidmatch = p; 04735 if (callerid) { 04736 p += ext_strncpy(tmp->cidmatch, callerid, strlen(callerid) + 1) + 1; 04737 tmp->matchcid = 1; 04738 } else { 04739 tmp->cidmatch[0] = '\0'; 04740 tmp->matchcid = 0; 04741 p++; 04742 } 04743 tmp->app = p; 04744 strcpy(tmp->app, application); 04745 tmp->parent = con; 04746 tmp->data = data; 04747 tmp->datad = datad; 04748 tmp->registrar = registrar; 04749 tmp->peer = NULL; 04750 tmp->next = NULL; 04751 } else { 04752 ast_log(LOG_ERROR, "Out of memory\n"); 04753 errno = ENOMEM; 04754 return -1; 04755 } 04756 if (ast_mutex_lock(&con->lock)) { 04757 free(tmp); 04758 /* And properly destroy the data */ 04759 datad(data); 04760 ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name); 04761 errno = EBUSY; 04762 return -1; 04763 } 04764 e = con->root; 04765 while(e) { 04766 /* Make sure patterns are always last! */ 04767 if ((e->exten[0] != '_') && (extension[0] == '_')) 04768 res = -1; 04769 else if ((e->exten[0] == '_') && (extension[0] != '_')) 04770 res = 1; 04771 else 04772 res= strcmp(e->exten, extension); 04773 if (!res) { 04774 if (!e->matchcid && !tmp->matchcid) 04775 res = 0; 04776 else if (tmp->matchcid && !e->matchcid) 04777 res = 1; 04778 else if (e->matchcid && !tmp->matchcid) 04779 res = -1; 04780 else 04781 res = strcasecmp(e->cidmatch, tmp->cidmatch); 04782 } 04783 if (res == 0) { 04784 /* We have an exact match, now we find where we are 04785 and be sure there's no duplicates */ 04786 while(e) { 04787 if (e->priority == tmp->priority) { 04788 /* Can't have something exactly the same. Is this a 04789 replacement? If so, replace, otherwise, bonk. */ 04790 if (replace) { 04791 if (ep) { 04792 /* We're in the peer list, insert ourselves */ 04793 ep->peer = tmp; 04794 tmp->peer = e->peer; 04795 } else if (el) { 04796 /* We're the first extension. Take over e's functions */ 04797 el->next = tmp; 04798 tmp->next = e->next; 04799 tmp->peer = e->peer; 04800 } else { 04801 /* We're the very first extension. */ 04802 con->root = tmp; 04803 tmp->next = e->next; 04804 tmp->peer = e->peer; 04805 } 04806 if (tmp->priority == PRIORITY_HINT) 04807 ast_change_hint(e,tmp); 04808 /* Destroy the old one */ 04809 e->datad(e->data); 04810 free(e); 04811 ast_mutex_unlock(&con->lock); 04812 if (tmp->priority == PRIORITY_HINT) 04813 ast_change_hint(e, tmp); 04814 /* And immediately return success. */ 04815 LOG; 04816 return 0; 04817 } else { 04818 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 04819 tmp->datad(tmp->data); 04820 free(tmp); 04821 ast_mutex_unlock(&con->lock); 04822 errno = EEXIST; 04823 return -1; 04824 } 04825 } else if (e->priority > tmp->priority) { 04826 /* Slip ourselves in just before e */ 04827 if (ep) { 04828 /* Easy enough, we're just in the peer list */ 04829 ep->peer = tmp; 04830 tmp->peer = e; 04831 } else if (el) { 04832 /* We're the first extension in this peer list */ 04833 el->next = tmp; 04834 tmp->next = e->next; 04835 e->next = NULL; 04836 tmp->peer = e; 04837 } else { 04838 /* We're the very first extension altogether */ 04839 tmp->next = con->root->next; 04840 /* Con->root must always exist or we couldn't get here */ 04841 tmp->peer = con->root; 04842 con->root = tmp; 04843 } 04844 ast_mutex_unlock(&con->lock); 04845 04846 /* And immediately return success. */ 04847 if (tmp->priority == PRIORITY_HINT) 04848 ast_add_hint(tmp); 04849 04850 LOG; 04851 return 0; 04852 } 04853 ep = e; 04854 e = e->peer; 04855 } 04856 /* If we make it here, then it's time for us to go at the very end. 04857 ep *must* be defined or we couldn't have gotten here. */ 04858 ep->peer = tmp; 04859 ast_mutex_unlock(&con->lock); 04860 if (tmp->priority == PRIORITY_HINT) 04861 ast_add_hint(tmp); 04862 04863 /* And immediately return success. */ 04864 LOG; 04865 return 0; 04866 04867 } else if (res > 0) { 04868 /* Insert ourselves just before 'e'. We're the first extension of 04869 this kind */ 04870 tmp->next = e; 04871 if (el) { 04872 /* We're in the list somewhere */ 04873 el->next = tmp; 04874 } else { 04875 /* We're at the top of the list */ 04876 con->root = tmp; 04877 } 04878 ast_mutex_unlock(&con->lock); 04879 if (tmp->priority == PRIORITY_HINT) 04880 ast_add_hint(tmp); 04881 04882 /* And immediately return success. */ 04883 LOG; 04884 return 0; 04885 } 04886 04887 el = e; 04888 e = e->next; 04889 } 04890 /* If we fall all the way through to here, then we need to be on the end. */ 04891 if (el) 04892 el->next = tmp; 04893 else 04894 con->root = tmp; 04895 ast_mutex_unlock(&con->lock); 04896 if (tmp->priority == PRIORITY_HINT) 04897 ast_add_hint(tmp); 04898 LOG; 04899 return 0; 04900 }
| int ast_async_goto | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) |
Definition at line 4572 of file pbx.c.
References ast_channel::_state, ast_channel_alloc(), ast_channel_masquerade(), ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_setstate(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_strlen_zero(), ast_channel::context, ast_channel::exten, ast_channel::lock, LOG_WARNING, ast_channel::name, ast_channel::pbx, ast_channel::readformat, and ast_channel::writeformat.
Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), handle_request_bye(), handle_request_refer(), monitor_handle_owned(), process_ast_dsp(), socket_read(), and zt_handle_dtmfup().
04573 { 04574 int res = 0; 04575 04576 ast_mutex_lock(&chan->lock); 04577 04578 if (chan->pbx) { 04579 /* This channel is currently in the PBX */ 04580 ast_explicit_goto(chan, context, exten, priority); 04581 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 04582 } else { 04583 /* In order to do it when the channel doesn't really exist within 04584 the PBX, we have to make a new channel, masquerade, and start the PBX 04585 at the new location */ 04586 struct ast_channel *tmpchan; 04587 tmpchan = ast_channel_alloc(0); 04588 if (tmpchan) { 04589 snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name); 04590 ast_setstate(tmpchan, chan->_state); 04591 /* Make formats okay */ 04592 tmpchan->readformat = chan->readformat; 04593 tmpchan->writeformat = chan->writeformat; 04594 /* Setup proper location */ 04595 ast_explicit_goto(tmpchan, 04596 (!ast_strlen_zero(context)) ? context : chan->context, 04597 (!ast_strlen_zero(exten)) ? exten : chan->exten, 04598 priority); 04599 04600 /* Masquerade into temp channel */ 04601 ast_channel_masquerade(tmpchan, chan); 04602 04603 /* Grab the locks and get going */ 04604 ast_mutex_lock(&tmpchan->lock); 04605 ast_do_masquerade(tmpchan); 04606 ast_mutex_unlock(&tmpchan->lock); 04607 /* Start the PBX going on our stolen channel */ 04608 if (ast_pbx_start(tmpchan)) { 04609 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 04610 ast_hangup(tmpchan); 04611 res = -1; 04612 } 04613 } else { 04614 res = -1; 04615 } 04616 } 04617