Thu Oct 9 06:45:27 2008

Asterisk developer's documentation


pbx.h File Reference

Core PBX routines and definitions. More...

#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_contextast_context_create (struct ast_context **extcontexts, const char *name, const char *registrar)
void ast_context_destroy (struct ast_context *con, const char *registrar)
ast_contextast_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_functionast_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_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority)
ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
ast_contextast_walk_contexts (struct ast_context *con)
ast_extenast_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_apppbx_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 []


Detailed Description

Core PBX routines and definitions.

Definition in file pbx.h.


Define Documentation

#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_KEEP   0

Definition at line 33 of file pbx.h.

#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 AST_PBX_REPLACE   1

Definition at line 34 of file pbx.h.

#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 Documentation

typedef int(*) ast_state_cb_type(char *context, char *id, enum ast_extension_states state, void *data)

Definition at line 83 of file pbx.h.


Enumeration Type Documentation

enum ast_extension_states

Extension states

Enumerator:
AST_EXTENSION_REMOVED  Extension removed
AST_EXTENSION_DEACTIVATED  Extension hint removed
AST_EXTENSION_NOT_INUSE  No device INUSE or BUSY
AST_EXTENSION_INUSE  One or more devices INUSE
AST_EXTENSION_BUSY  All devices BUSY
AST_EXTENSION_UNAVAILABLE  All devices UNAVAILABLE/UNREGISTERED
AST_EXTENSION_RINGING  All devices RINGING

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

Enumerator:
AST_PBX_SUCCESS 
AST_PBX_FAILED 
AST_PBX_CALL_LIMIT 

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 };


Function Documentation

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 
)

Parameters:
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