Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

pbx.h File Reference

#include <asterisk/sched.h>
#include <asterisk/channel.h>

Go to the source code of this file.

Data Structures

struct  ast_pbx
struct  ast_switch
 Data structure associated with an asterisk switch. More...


Defines

#define AST_PBX_KEEP   0
#define AST_PBX_REPLACE   1
#define AST_MAX_APP   32
 Max length of an application.

#define AST_PBX_KEEPALIVE   10
 Special return values from applications to the PBX.

#define AST_PBX_NO_HANGUP_PEER   11
#define PRIORITY_HINT   -1
 Special Priority for an hint.

#define AST_EXTENSION_NOT_INUSE   0
#define AST_EXTENSION_INUSE   1
 One or more devices INUSE.

#define AST_EXTENSION_BUSY   2
 All devices BUSY.

#define AST_EXTENSION_UNAVAILABLE   3
 All devices UNAVAILABLE/UNREGISTERED.


Typedefs

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

Functions

int ast_register_switch (struct ast_switch *sw)
 Register an alternative switch.

void ast_unregister_switch (struct ast_switch *sw)
 Unregister an alternative switch.

ast_apppbx_findapp (char *app)
 Look up an application.

int pbx_exec (struct ast_channel *c, struct ast_app *app, void *data, int newstack)
 executes an application

ast_contextast_context_create (struct ast_context **extcontexts, char *name, char *registrar)
 Register a new context.

void ast_merge_contexts_and_delete (struct ast_context **extcontexts, char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.

void ast_context_destroy (struct ast_context *con, char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL).

ast_contextast_context_find (char *name)
 Find a context.

int ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX (or whatever).

int ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread.

int ast_add_extension (char *context, int replace, char *extension, int priority, char *callerid, char *application, void *data, void(*datad)(void *), char *registrar)
int ast_add_extension2 (struct ast_context *con, int replace, char *extension, int priority, char *callerid, char *application, void *data, void(*datad)(void *), char *registrar)
 Add an extension to an extension context, this time with an ast_context *. CallerID is a pattern to match on callerid, or NULL to not care about callerid.

int ast_register_application (char *app, int(*execute)(struct ast_channel *, void *), char *synopsis, char *description)
 Add an application. The function 'execute' should return non-zero if the line needs to be hung up.

int ast_unregister_application (char *app)
 Remove an application.

int ast_extension_state (struct ast_channel *c, char *context, char *exten)
 Uses hint and devicestate callback to get the state of an extension.

int ast_device_state_changed (const char *fmt,...) __attribute__((format(printf
 Tells Asterisk the State for Device is changed.

int ast_extension_state_add (char *context, 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_get_hint (char *hint, int maxlen, struct ast_channel *c, char *context, char *exten)
 If an extension exists, return non-zero.

int ast_exists_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 If an extension exists, return non-zero.

int ast_canmatch_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Looks for a valid matching extension.

int ast_matchmore_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch).

int ast_extension_match (char *pattern, char *extension)
 Determine if a given extension matches a given pattern (in NXX format).

int ast_spawn_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Launch a new extension (i.e. new stack).

int ast_exec_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
 Execute an extension.

int ast_context_add_include (char *context, char *include, char *registrar)
 Add an include.

int ast_context_add_include2 (struct ast_context *con, char *include, char *registrar)
 Add an include.

int ast_context_remove_include (char *context, char *include, char *registrar)
 Removes an include.

int ast_context_remove_include2 (struct ast_context *con, char *include, char *registrar)
 Removes an include by an ast_context structure.

int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure.

int ast_context_add_switch (char *context, char *sw, char *data, char *registrar)
 Add a switch.

int ast_context_add_switch2 (struct ast_context *con, char *sw, char *data, char *registrar)
 Adds a switch (first param is a ast_context).

int ast_context_remove_switch (char *context, char *sw, char *data, char *registrar)
 Remove a switch.

int ast_context_remove_switch2 (struct ast_context *con, char *sw, char *data, char *registrar)
int ast_context_remove_extension (char *context, char *extension, int priority, char *registrar)
 Simply remove extension from context.

int ast_context_remove_extension2 (struct ast_context *con, char *extension, int priority, char *registrar)
int ast_context_add_ignorepat (char *context, char *ignorepat, char *registrar)
 Add an ignorepat.

int ast_context_add_ignorepat2 (struct ast_context *con, char *ignorepat, char *registrar)
int ast_context_remove_ignorepat (char *context, char *ignorepat, char *registrar)
int ast_context_remove_ignorepat2 (struct ast_context *con, char *ignorepat, char *registrar)
int ast_ignore_pattern (char *context, char *pattern)
 Checks to see if a number should be ignored.

int ast_lock_contexts (void)
 Locks the contexts.

int ast_unlock_contexts (void)
 Unlocks contexts.

int ast_lock_context (struct ast_context *con)
 Locks a given context.

int ast_unlock_context (struct ast_context *con)
 Unlocks the given context.

int ast_async_goto (struct ast_channel *chan, char *context, char *exten, int priority, int needlock)
int ast_async_goto_by_name (char *chan, char *context, char *exten, int priority)
int ast_pbx_outgoing_exten (char *type, int format, void *data, int timeout, char *context, char *exten, int priority, int *reason, int sync, char *callerid, char *variable, char *account)
int ast_pbx_outgoing_app (char *type, int format, void *data, int timeout, char *app, char *appdata, int *reason, int sync, char *callerid, char *variable, char *account)
char * ast_get_context_name (struct ast_context *con)
char * ast_get_extension_name (struct ast_exten *exten)
char * ast_get_include_name (struct ast_include *include)
char * ast_get_ignorepat_name (struct ast_ignorepat *ip)
char * ast_get_switch_name (struct ast_sw *sw)
char * ast_get_switch_data (struct ast_sw *sw)
int ast_get_extension_priority (struct ast_exten *exten)
char * ast_get_extension_app (struct ast_exten *e)
void * ast_get_extension_app_data (struct ast_exten *e)
char * ast_get_context_registrar (struct ast_context *c)
char * ast_get_extension_registrar (struct ast_exten *e)
char * ast_get_include_registrar (struct ast_include *i)
char * ast_get_ignorepat_registrar (struct ast_ignorepat *ip)
char * ast_get_switch_registrar (struct ast_sw *sw)
ast_contextast_walk_contexts (struct ast_context *con)
ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority)
ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
char * pbx_builtin_getvar_helper (struct ast_channel *chan, char *name)
void pbx_builtin_setvar_helper (struct ast_channel *chan, char *name, char *value)
void pbx_builtin_clear_globals (void)
int pbx_builtin_setvar (struct ast_channel *chan, void *data)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
int ast_extension_patmatch (const char *pattern, const char *data)


Define Documentation

#define AST_EXTENSION_BUSY   2
 

All devices BUSY.

Definition at line 42 of file pbx.h.

#define AST_EXTENSION_INUSE   1
 

One or more devices INUSE.

Definition at line 40 of file pbx.h.

#define AST_EXTENSION_NOT_INUSE   0
 

Extension states No device INUSE or BUSY

Definition at line 38 of file pbx.h.

#define AST_EXTENSION_UNAVAILABLE   3
 

All devices UNAVAILABLE/UNREGISTERED.

Definition at line 44 of file pbx.h.

#define AST_MAX_APP   32
 

Max length of an application.

Definition at line 27 of file pbx.h.

#define AST_PBX_KEEP   0
 

Definition at line 23 of file pbx.h.

#define AST_PBX_KEEPALIVE   10
 

Special return values from applications to the PBX.

Definition at line 30 of file pbx.h.

Referenced by ast_pbx_run().

#define AST_PBX_NO_HANGUP_PEER   11
 

Definition at line 31 of file pbx.h.

#define AST_PBX_REPLACE   1
 

Definition at line 24 of file pbx.h.

#define PRIORITY_HINT   -1
 

Special Priority for an hint.

Definition at line 34 of file pbx.h.

Referenced by ast_context_remove_extension2().


Typedef Documentation

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

Definition at line 52 of file pbx.h.

Referenced by ast_extension_state_add(), and ast_extension_state_del().


Function Documentation

int ast_add_extension char *  context,
int  replace,
char *  extension,
int  priority,
char *  callerid,
char *  application,
void *  data,
void(*  datad)(void *),
char *  registrar
 

Parameters:
context context to add the extension to
replace 
extension extension to add
priority priority level of extension addition
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 3470 of file pbx.c.

03472 {
03473    struct ast_context *c;
03474 
03475    if (ast_lock_contexts()) {
03476       errno = EBUSY;
03477       return -1;
03478    }
03479 
03480    c = ast_walk_contexts(NULL);
03481    while (c) {
03482       if (!strcmp(context, ast_get_context_name(c))) {
03483          int ret = ast_add_extension2(c, replace, extension, priority, callerid,
03484             application, data, datad, registrar);
03485          ast_unlock_contexts();
03486          return ret;
03487       }
03488       c = ast_walk_contexts(c);
03489    }
03490 
03491    ast_unlock_contexts();
03492    errno = ENOENT;
03493    return -1;
03494 }

int ast_add_extension2 struct ast_context con,
int  replace,
char *  extension,
int  priority,
char *  callerid,
char *  application,
void *  data,
void(*  datad)(void *),
char *  registrar
 

Add an extension to an extension context, this time with an ast_context *. CallerID is a pattern to match on callerid, or NULL to not care about callerid.

For details about the arguements, check ast_add_extension()

Definition at line 3602 of file pbx.c.

Referenced by ast_ignore_pattern().

03606 {
03607 
03608 #define LOG do {  if (option_debug) {\
03609       if (tmp->matchcid) { \
03610          ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
03611       } else { \
03612          ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
03613       } \
03614    } else if (option_verbose > 2) { \
03615       if (tmp->matchcid) { \
03616          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
03617       } else {  \
03618          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
03619       } \
03620    } } while(0)
03621 
03622    /*
03623     * This is a fairly complex routine.  Different extensions are kept
03624     * in order by the extension number.  Then, extensions of different
03625     * priorities (same extension) are kept in a list, according to the
03626     * peer pointer.
03627     */
03628    struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
03629    int res;
03630    /* Be optimistic:  Build the extension structure first */
03631    tmp = malloc(sizeof(struct ast_exten));
03632    if (tmp) {
03633       memset(tmp, 0, sizeof(struct ast_exten));
03634       ext_strncpy(tmp->exten, extension, sizeof(tmp->exten));
03635       tmp->priority = priority;
03636       if (callerid) {
03637          ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch));
03638          tmp->matchcid = 1;
03639       } else {
03640          strcpy(tmp->cidmatch, "");
03641          tmp->matchcid = 0;
03642       }
03643       strncpy(tmp->app, application, sizeof(tmp->app)-1);
03644       tmp->parent = con;
03645       tmp->data = data;
03646       tmp->datad = datad;
03647       tmp->registrar = registrar;
03648       tmp->peer = NULL;
03649       tmp->next =  NULL;
03650    } else {
03651       ast_log(LOG_ERROR, "Out of memory\n");
03652       errno = ENOMEM;
03653       return -1;
03654    }
03655    if (ast_mutex_lock(&con->lock)) {
03656       free(tmp);
03657       /* And properly destroy the data */
03658       datad(data);
03659       ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
03660       errno = EBUSY;
03661       return -1;
03662    }
03663    e = con->root;
03664    while(e) {
03665       res= strcasecmp(e->exten, extension);
03666       if (!res) {
03667          if (!e->matchcid && !tmp->matchcid)
03668             res = 0;
03669          else if (tmp->matchcid && !e->matchcid)
03670             res = 1;
03671          else if (e->matchcid && !tmp->matchcid)
03672             res = -1;
03673          else
03674             res = strcasecmp(e->cidmatch, tmp->cidmatch);
03675       }
03676       if (res == 0) {
03677          /* We have an exact match, now we find where we are
03678             and be sure there's no duplicates */
03679          while(e) {
03680             if (e->priority == tmp->priority) {
03681                /* Can't have something exactly the same.  Is this a
03682                   replacement?  If so, replace, otherwise, bonk. */
03683                if (replace) {
03684                   if (ep) {
03685                      /* We're in the peer list, insert ourselves */
03686                      ep->peer = tmp;
03687                      tmp->peer = e->peer;
03688                   } else if (el) {
03689                      /* We're the first extension. Take over e's functions */
03690                      el->next = tmp;
03691                      tmp->next = e->next;
03692                      tmp->peer = e->peer;
03693                   } else {
03694                      /* We're the very first extension.  */
03695                      con->root = tmp;
03696                      tmp->next = e->next;
03697                      tmp->peer = e->peer;
03698                   }
03699                   if (tmp->priority == PRIORITY_HINT)
03700                       ast_change_hint(e,tmp);
03701                   /* Destroy the old one */
03702                   e->datad(e->data);
03703                   free(e);
03704                   ast_mutex_unlock(&con->lock);
03705                   if (tmp->priority == PRIORITY_HINT)
03706                       ast_change_hint(e, tmp);
03707                   /* And immediately return success. */
03708                   LOG;
03709                   return 0;
03710                } else {
03711                   ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
03712                   tmp->datad(tmp->data);
03713                   free(tmp);
03714                   ast_mutex_unlock(&con->lock);
03715                   errno = EEXIST;
03716                   return -1;
03717                }
03718             } else if (e->priority > tmp->priority) {
03719                /* Slip ourselves in just before e */
03720                if (ep) {
03721                   /* Easy enough, we're just in the peer list */
03722                   ep->peer = tmp;
03723                   tmp->peer = e;
03724                } else if (el) {
03725                   /* We're the first extension in this peer list */
03726                   el->next = tmp;
03727                   tmp->next = e->next;
03728                   e->next = NULL;
03729                   tmp->peer = e;
03730                } else {
03731                   /* We're the very first extension altogether */
03732                   tmp->next = con->root;
03733                   /* Con->root must always exist or we couldn't get here */
03734                   tmp->peer = con->root->peer;
03735                   con->root = tmp;
03736                }
03737                ast_mutex_unlock(&con->lock);
03738                /* And immediately return success. */
03739                if (tmp->priority == PRIORITY_HINT)
03740                    ast_add_hint(tmp);
03741                
03742                LOG;
03743                return 0;
03744             }
03745             ep = e;
03746             e = e->peer;
03747          }
03748          /* If we make it here, then it's time for us to go at the very end.
03749             ep *must* be defined or we couldn't have gotten here. */
03750          ep->peer = tmp;
03751          ast_mutex_unlock(&con->lock);
03752          if (tmp->priority == PRIORITY_HINT)
03753              ast_add_hint(tmp);
03754          
03755          /* And immediately return success. */
03756          LOG;
03757          return 0;
03758             
03759       } else if (res > 0) {
03760          /* Insert ourselves just before 'e'.  We're the first extension of
03761             this kind */
03762          tmp->next = e;
03763          if (el) {
03764             /* We're in the list somewhere */
03765             el->next = tmp;
03766          } else {
03767             /* We're at the top of the list */
03768             con->root = tmp;
03769          }
03770          ast_mutex_unlock(&con->lock);
03771          if (tmp->priority == PRIORITY_HINT)
03772              ast_add_hint(tmp);
03773 
03774          /* And immediately return success. */
03775          LOG;
03776          return 0;
03777       }        
03778          
03779       el = e;
03780       e = e->next;
03781    }
03782    /* If we fall all the way through to here, then we need to be on the end. */
03783    if (el)
03784       el->next = tmp;
03785    else
03786       con->root = tmp;
03787    ast_mutex_unlock(&con->lock);
03788    if (tmp->priority == PRIORITY_HINT)
03789        ast_add_hint(tmp);
03790    LOG;
03791    return 0;   
03792 }

int ast_async_goto struct ast_channel chan,
char *  context,
char *  exten,
int  priority,
int  needlock
 

Definition at line 3496 of file pbx.c.

03497 {
03498    int res = 0;
03499    if (needlock)
03500       ast_mutex_lock(&chan->lock);
03501    if (chan->pbx) {
03502       /* This channel is currently in the PBX */
03503       if (context && strlen(context))
03504          strncpy(chan->context, context, sizeof(chan->context) - 1);
03505       if (exten && strlen(exten))
03506          strncpy(chan->exten, exten, sizeof(chan->context) - 1);
03507       if (priority)
03508          chan->priority = priority - 1;
03509       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
03510       if (needlock)
03511          ast_mutex_unlock(&chan->lock);
03512    } else {
03513       /* In order to do it when the channel doesn't really exist within
03514          the PBX, we have to make a new channel, masquerade, and start the PBX
03515          at the new location */
03516       struct ast_channel *tmpchan;
03517       struct ast_frame *f;
03518       tmpchan = ast_channel_alloc(0);
03519       if (tmpchan) {
03520          snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
03521          ast_setstate(tmpchan, chan->_state);
03522          /* Make formats okay */
03523          tmpchan->readformat = chan->readformat;
03524          tmpchan->writeformat = chan->writeformat;
03525          /* Setup proper location */
03526          if (context && strlen(context))
03527             strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1);
03528          else
03529             strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1);
03530          if (exten && strlen(exten))
03531             strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1);
03532          else
03533             strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1);
03534          if (priority)
03535             tmpchan->priority = priority;
03536          else
03537             tmpchan->priority = chan->priority;
03538          if (needlock)
03539             ast_mutex_unlock(&chan->lock);
03540          
03541          /* Masquerade into temp channel */
03542          ast_channel_masquerade(tmpchan, chan);
03543          
03544          /* Make the masquerade happen by reading a frame from the tmp channel */
03545          f = ast_read(tmpchan);
03546          if (f)
03547             ast_frfree(f);
03548          /* Start the PBX going on our stolen channel */
03549          if (ast_pbx_start(tmpchan)) {
03550             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
03551             ast_hangup(tmpchan);
03552             res = -1;
03553          }
03554       } else {
03555          res = -1;
03556          if (needlock)
03557             ast_mutex_unlock(&chan->lock);
03558       }
03559    }
03560    return res;
03561 }

int ast_async_goto_by_name char *  chan,
char *  context,
char *  exten,
int  priority
 

Definition at line 3563 of file pbx.c.

03564 {
03565    struct ast_channel *chan;
03566    chan = ast_channel_walk(NULL);
03567    while(chan) {
03568       if (!strcasecmp(channame, chan->name))
03569          break;
03570       chan = ast_channel_walk(chan);
03571    }
03572    if (chan)
03573       return ast_async_goto(chan, context, exten, priority, 1);
03574    return -1;
03575 }

int ast_canmatch_extension struct ast_channel c,
char *  context,
char *  exten,
int  priority,
char *  callerid
 

Looks for a valid matching extension.

Parameters:
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 If "exten" *could be* a valid extension in this context with or without some more digits, return non-zero. Basically, when this returns 0, no matter what you add to exten, it's not going to be a valid extension anymore

Definition at line 1643 of file pbx.c.

References HELPER_CANMATCH.

01644 {
01645    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH);
01646 }

int ast_context_add_ignorepat char *  context,
char *  ignorepat,
char *  registrar
 

Add an ignorepat.

Parameters:
context which context to add the ignorpattern to
ignorpat ignorepattern to set up for the extension
registrar registrar of the ignore pattern Adds an ignore pattern to a particular context. Returns 0 on success, -1 on failure

Definition at line 3391 of file pbx.c.

03392 {
03393    struct ast_context *c;
03394 
03395    if (ast_lock_contexts()) {
03396       errno = EBUSY;
03397       return -1;
03398    }
03399 
03400    c = ast_walk_contexts(NULL);
03401    while (c) {
03402       if (!strcmp(ast_get_context_name(c), con)) {
03403          int ret = ast_context_add_ignorepat2(c, value, registrar);
03404          ast_unlock_contexts();
03405          return ret;
03406       } 
03407       c = ast_walk_contexts(c);
03408    }
03409 
03410    ast_unlock_contexts();
03411    errno = ENOENT;
03412    return -1;
03413 }

int ast_context_add_ignorepat2 struct ast_context con,
char *  ignorepat,
char *  registrar
 

Definition at line 3415 of file pbx.c.

References ast_mutex_unlock, and ast_context::lock.

03416 {
03417    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
03418    ignorepat = malloc(sizeof(struct ast_ignorepat));
03419    if (!ignorepat) {
03420       ast_log(LOG_ERROR, "Out of memory\n");
03421       errno = ENOMEM;
03422       return -1;
03423    }
03424    memset(ignorepat, 0, sizeof(struct ast_ignorepat));
03425    strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
03426    ignorepat->next = NULL;
03427    ignorepat->registrar = registrar;
03428    ast_mutex_lock(&con->lock);
03429    ignorepatc = con->ignorepats;
03430    while(ignorepatc) {
03431       ignorepatl = ignorepatc;
03432       if (!strcasecmp(ignorepatc->pattern, value)) {
03433          /* Already there */
03434          ast_mutex_unlock(&con->lock);
03435          errno = EEXIST;
03436          return -1;
03437       }
03438       ignorepatc = ignorepatc->next;
03439    }
03440    if (ignorepatl) 
03441       ignorepatl->next = ignorepat;
03442    else
03443       con->ignorepats = ignorepat;
03444    ast_mutex_unlock(&con->lock);
03445    return 0;
03446    
03447 }

int ast_context_add_include char *  context,
char *  include,
char *  registrar
 

Add an include.

Parameters:
context context to add include to
include new include to add
registrar who's registering it Adds an include taking a char * string as the context parameter Returns 0 on success, -1 on error

Definition at line 2855 of file pbx.c.

02856 {
02857    struct ast_context *c;
02858 
02859    if (ast_lock_contexts()) {
02860       errno = EBUSY;
02861       return -1;
02862    }
02863 
02864    /* walk contexts ... */
02865    c = ast_walk_contexts(NULL);
02866    while (c) {
02867       /* ... search for the right one ... */
02868       if (!strcmp(ast_get_context_name(c), context)) {
02869          int ret = ast_context_add_include2(c, include, registrar);
02870          /* ... unlock contexts list and return */
02871          ast_unlock_contexts();
02872          return ret;
02873       }
02874       c = ast_walk_contexts(c);
02875    }
02876 
02877    /* we can't find the right context */
02878    ast_unlock_contexts();
02879    errno = ENOENT;
02880    return -1;
02881 }

int ast_context_add_include2 struct ast_context con,
char *  include,
char *  registrar
 

Add an include.

Parameters:
con context to add the include to
include include to add
registrar who registered the context Adds an include taking a struct ast_context as the first parameter Returns 0 on success, -1 on failure

Definition at line 3172 of file pbx.c.

03174 {
03175    struct ast_include *new_include;
03176    char *c;
03177    struct ast_include *i, *il = NULL; /* include, include_last */
03178 
03179    /* allocate new include structure ... */
03180    if (!(new_include = malloc(sizeof(struct ast_include)))) {
03181       ast_log(LOG_ERROR, "Out of memory\n");
03182       errno = ENOMEM;
03183       return -1;
03184    }
03185    
03186    /* ... fill in this structure ... */
03187    memset(new_include, 0, sizeof(struct ast_include));
03188    strncpy(new_include->name, value, sizeof(new_include->name)-1);
03189    strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
03190    c = new_include->rname;
03191    /* Strip off timing info */
03192    while(*c && (*c != '|')) c++; 
03193    /* Process if it's there */
03194    if (*c) {
03195       build_timing(new_include, c+1);
03196       *c = '\0';
03197    }
03198    new_include->next      = NULL;
03199    new_include->registrar = registrar;
03200 
03201    /* ... try to lock this context ... */
03202    if (ast_mutex_lock(&con->lock)) {
03203       free(new_include);
03204       errno = EBUSY;
03205       return -1;
03206    }
03207 
03208    /* ... go to last include and check if context is already included too... */
03209    i = con->includes;
03210    while (i) {
03211       if (!strcasecmp(i->name, new_include->name)) {
03212          free(new_include);
03213          ast_mutex_unlock(&con->lock);
03214          errno = EEXIST;
03215          return -1;
03216       }
03217       il = i;
03218       i = i->next;
03219    }
03220 
03221    /* ... include new context into context list, unlock, return */
03222    if (il)
03223       il->next = new_include;
03224    else
03225       con->includes = new_include;
03226    if (option_verbose > 2)
03227       ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 
03228    ast_mutex_unlock(&con->lock);
03229 
03230    return 0;
03231 }

int ast_context_add_switch char *  context,
char *  sw,
char *  data,
char *  registrar
 

Add a switch.

Parameters:
context context to which to add the switch
sw switch to add
data data to pass to switch
registrar whoever registered the switch This function registers a switch with the asterisk switch architecture It returns 0 on success, -1 on failure

Definition at line 3238 of file pbx.c.

03239 {
03240    struct ast_context *c;
03241 
03242    if (ast_lock_contexts()) {
03243       errno = EBUSY;
03244       return -1;
03245    }
03246 
03247    /* walk contexts ... */
03248    c = ast_walk_contexts(NULL);
03249    while (c) {
03250       /* ... search for the right one ... */
03251       if (!strcmp(ast_get_context_name(c), context)) {
03252          int ret = ast_context_add_switch2(c, sw, data, registrar);
03253          /* ... unlock contexts list and return */
03254          ast_unlock_contexts();
03255          return ret;
03256       }
03257       c = ast_walk_contexts(c);
03258    }
03259 
03260    /* we can't find the right context */
03261    ast_unlock_contexts();
03262    errno = ENOENT;
03263    return -1;
03264 }

int ast_context_add_switch2 struct ast_context con,
char *  sw,
char *  data,
char *  registrar
 

Adds a switch (first param is a ast_context).

See ast_context_add_switch()

Definition at line 3273 of file pbx.c.

03275 {
03276    struct ast_sw *new_sw;
03277    struct ast_sw *i, *il = NULL; /* sw, sw_last */
03278 
03279    /* allocate new sw structure ... */
03280    if (!(new_sw = malloc(sizeof(struct ast_sw)))) {
03281       ast_log(LOG_ERROR, "Out of memory\n");
03282       errno = ENOMEM;
03283       return -1;
03284    }
03285    
03286    /* ... fill in this structure ... */
03287    memset(new_sw, 0, sizeof(struct ast_sw));
03288    strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
03289    if (data)
03290       strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
03291    else
03292       strncpy(new_sw->data, "", sizeof(new_sw->data)-1);
03293    new_sw->next      = NULL;
03294    new_sw->registrar = registrar;
03295 
03296    /* ... try to lock this context ... */
03297    if (ast_mutex_lock(&con->lock)) {
03298       free(new_sw);
03299       errno = EBUSY;
03300       return -1;
03301    }
03302 
03303    /* ... go to last sw and check if context is already swd too... */
03304    i = con->alts;
03305    while (i) {
03306       if (!strcasecmp(i->name, new_sw->name)) {
03307          free(new_sw);
03308          ast_mutex_unlock(&con->lock);
03309          errno = EEXIST;
03310          return -1;
03311       }
03312       il = i;
03313       i = i->next;
03314    }
03315 
03316    /* ... sw new context into context list, unlock, return */
03317    if (il)
03318       il->next = new_sw;
03319    else
03320       con->alts = new_sw;
03321    if (option_verbose > 2)
03322       ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 
03323    ast_mutex_unlock(&con->lock);
03324 
03325    return 0;
03326 }

struct ast_context* ast_context_create struct ast_context **  extcontexts,
char *  name,
char *  registrar
 

Register a new context.

Parameters:
extcontexts pointer to the ast_context structure pointer
name name of the new context
registrar registrar of the context This will first search for a context with your name. If it exists already, it will not create a new one. If it does not exist, it will create a new one with the given name and registrar. It returns NULL on failure, and an ast_context structure on success

Definition at line 2778 of file pbx.c.

02779 {
02780    struct ast_context *tmp, **local_contexts;
02781    if (!extcontexts) {
02782       local_contexts = &contexts;
02783       ast_mutex_lock(&conlock);
02784    } else
02785       local_contexts = extcontexts;
02786 
02787    tmp = *local_contexts;
02788    while(tmp) {
02789       if (!strcasecmp(tmp->name, name)) {
02790          ast_mutex_unlock(&conlock);
02791          ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
02792          if (!extcontexts)
02793             ast_mutex_unlock(&conlock);
02794          return NULL;
02795       }
02796       tmp = tmp->next;
02797    }
02798    tmp = malloc(sizeof(struct ast_context));
02799    if (tmp) {
02800       memset(tmp, 0, sizeof(struct ast_context));
02801       ast_mutex_init(&tmp->lock);
02802       strncpy(tmp->name, name, sizeof(tmp->name)-1);
02803       tmp->root = NULL;
02804       tmp->registrar = registrar;
02805       tmp->next = *local_contexts;
02806       tmp->includes = NULL;
02807       tmp->ignorepats = NULL;
02808       *local_contexts = tmp;
02809       if (option_debug)
02810          ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
02811       else if (option_verbose > 2)
02812          ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
02813    } else
02814       ast_log(LOG_ERROR, "Out of memory\n");
02815    
02816    if (!extcontexts)
02817       ast_mutex_unlock(&conlock);
02818    return tmp;
02819 }

void ast_context_destroy struct ast_context con,
char *  registrar
 

Destroy a context (matches the specified context (or ANY context if NULL).

Parameters:
con context to destroy
registrar who registered it You can optionally leave out either parameter. It will find it based on either the ast_context or the registrar name. Returns nothing

Definition at line 4130 of file pbx.c.

04131 {
04132    __ast_context_destroy(con,registrar,1);
04133 }

struct ast_context* ast_context_find char *  name  ) 
 

Find a context.

Parameters:
name name of the context to find Will search for the context with the given name. Returns the ast_context on success, NULL on failure.

Definition at line 597 of file pbx.c.

References ast_mutex_lock, ast_mutex_unlock, and ast_context::next.

00598 {
00599    struct ast_context *tmp;
00600    ast_mutex_lock(&conlock);
00601    if (name) {
00602       tmp = contexts;
00603       while(tmp) {
00604          if (!strcasecmp(name, tmp->name))
00605             break;
00606          tmp = tmp->next;
00607       }
00608    } else
00609       tmp = contexts;
00610    ast_mutex_unlock(&conlock);
00611    return tmp;
00612 }

int ast_context_remove_extension char *  context,
char *  extension,
int  priority,
char *  registrar
 

Simply remove extension from context.

Parameters:
context context to remove extension from
extension which extension to remove
priority priority of extension to remove
registrar registrar of the extension This function removes an extension from a given context. Returns 0 on success, -1 on failure

Definition at line 2053 of file pbx.c.

References ast_context_remove_extension2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().

02054 {
02055    struct ast_context *c;
02056 
02057    if (ast_lock_contexts()) return -1;
02058 
02059    /* walk contexts ... */
02060    c = ast_walk_contexts(NULL);
02061    while (c) {
02062       /* ... search for the right one ... */
02063       if (!strcmp(ast_get_context_name(c), context)) {
02064          /* ... remove extension ... */
02065          int ret = ast_context_remove_extension2(c, extension, priority,
02066             registrar);
02067          /* ... unlock contexts list and return */
02068          ast_unlock_contexts();
02069          return ret;
02070       }
02071       c = ast_walk_contexts(c);
02072    }
02073 
02074    /* we can't find the right context */
02075    ast_unlock_contexts();
02076    return -1;
02077 }

int ast_context_remove_extension2 struct ast_context con,
char *  extension,
int  priority,
char *  registrar
 

Definition at line 2089 of file pbx.c.

References ast_mutex_lock, ast_mutex_unlock, free, ast_context::lock, ast_exten::next, ast_exten::peer, PRIORITY_HINT, and ast_context::root.

Referenced by ast_context_remove_extension().

02090 {
02091    struct ast_exten *exten, *prev_exten = NULL;
02092 
02093    if (ast_mutex_lock(&con->lock)) return -1;
02094 
02095    /* go through all extensions in context and search the right one ... */
02096    exten = con->root;
02097    while (exten) {
02098 
02099       /* look for right extension */
02100       if (!strcmp(exten->exten, extension) &&
02101          (!strcmp(exten->registrar, registrar) || !registrar)) {
02102          struct ast_exten *peer;
02103 
02104          /* should we free all peers in this extension? (priority == 0)? */
02105          if (priority == 0) {
02106             /* remove this extension from context list */
02107             if (prev_exten)
02108                prev_exten->next = exten->next;
02109             else
02110                con->root = exten->next;
02111 
02112             /* fire out all peers */
02113             peer = exten; 
02114             while (peer) {
02115                exten = peer->peer;
02116                
02117                if (!peer->priority==PRIORITY_HINT) 
02118                    ast_remove_hint(peer);
02119 
02120                peer->datad(peer->data);
02121                free(peer);
02122 
02123                peer = exten;
02124             }
02125 
02126             ast_mutex_unlock(&con->lock);
02127             return 0;
02128          } else {
02129             /* remove only extension with exten->priority == priority */
02130             struct ast_exten *previous_peer = NULL;
02131 
02132             peer = exten;
02133             while (peer) {
02134                /* is this our extension? */
02135                if (peer->priority == priority &&
02136                   (!strcmp(peer->registrar, registrar) || !registrar)) {
02137                   /* we are first priority extension? */
02138                   if (!previous_peer) {
02139                      /* exists previous extension here? */
02140                      if (prev_exten) {
02141                         /* yes, so we must change next pointer in
02142                          * previous connection to next peer
02143                          */
02144                         if (peer->peer) {
02145                            prev_exten->next = peer->peer;
02146                            peer->peer->next = exten->next;
02147                         } else
02148                            prev_exten->next = exten->next;
02149                      } else {
02150                         /* no previous extension, we are first
02151                          * extension, so change con->root ...
02152                          */
02153                         if (peer->peer)
02154                            con->root = peer->peer;
02155                         else
02156                            con->root = exten->next; 
02157                      }
02158                   } else {
02159                      /* we are not first priority in extension */
02160                      previous_peer->peer = peer->peer;
02161                   }
02162 
02163                   /* now, free whole priority extension */
02164                   if (peer->priority==PRIORITY_HINT)
02165                       ast_remove_hint(peer);
02166                   peer->datad(peer->data);
02167                   free(peer);
02168 
02169                   ast_mutex_unlock(&con->lock);
02170                   return 0;
02171                } else {
02172                   /* this is not right extension, skip to next peer */
02173                   previous_peer = peer;
02174                   peer = peer->peer;
02175                }
02176             }
02177 
02178             ast_mutex_unlock(&con->lock);
02179             return -1;
02180          }
02181       }
02182 
02183       prev_exten = exten;
02184       exten = exten->next;
02185    }
02186 
02187    /* we can't find right extension */
02188    ast_mutex_unlock(&con->lock);
02189    return -1;
02190 }

int ast_context_remove_ignorepat char *  context,
char *  ignorepat,
char *  registrar
 

Parameters:
context context from which to remove the pattern
ignorepat the pattern to remove
registrar the registrar of the ignore pattern This removes the given ignorepattern Returns 0 on success, -1 on failure

Definition at line 3332 of file pbx.c.

03333 {
03334    struct ast_context *c;
03335 
03336    if (ast_lock_contexts()) {
03337       errno = EBUSY;
03338       return -1;
03339    }
03340 
03341    c = ast_walk_contexts(NULL);
03342    while (c) {
03343       if (!strcmp(ast_get_context_name(c), context)) {
03344          int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
03345          ast_unlock_contexts();
03346          return ret;
03347       }
03348       c = ast_walk_contexts(c);
03349    }
03350 
03351    ast_unlock_contexts();
03352    errno = ENOENT;
03353    return -1;
03354 }

int ast_context_remove_ignorepat2 struct ast_context con,
char *  ignorepat,
char *  registrar
 

Definition at line 3356 of file pbx.c.

03357 {
03358    struct ast_ignorepat *ip, *ipl = NULL;
03359 
03360    if (ast_mutex_lock(&con->lock)) {
03361       errno = EBUSY;
03362       return -1;
03363    }
03364 
03365    ip = con->ignorepats;
03366    while (ip) {
03367       if (!strcmp(ip->pattern, ignorepat) &&
03368          (registrar == ip->registrar || !registrar)) {
03369          if (ipl) {
03370             ipl->next = ip->next;
03371             free(ip);
03372          } else {
03373             con->ignorepats = ip->next;
03374             free(ip);
03375          }
03376          ast_mutex_unlock(&con->lock);
03377          return 0;
03378       }
03379       ipl = ip; ip = ip->next;
03380    }
03381 
03382    ast_mutex_unlock(&con->lock);
03383    errno = EINVAL;
03384    return -1;
03385 }

int ast_context_remove_include char *  context,
char *  include,
char *  registrar
 

Removes an include.

See add_include

Definition at line 1909 of file pbx.c.

References ast_context_remove_include2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().

01910 {
01911    struct ast_context *c;
01912 
01913    if (ast_lock_contexts()) return -1;
01914 
01915    /* walk contexts and search for the right one ...*/
01916    c = ast_walk_contexts(NULL);
01917    while (c) {
01918       /* we found one ... */
01919       if (!strcmp(ast_get_context_name(c), context)) {
01920          int ret;
01921          /* remove include from this context ... */   
01922          ret = ast_context_remove_include2(c, include, registrar);
01923 
01924          ast_unlock_contexts();
01925 
01926          /* ... return results */
01927          return ret;
01928       }
01929       c = ast_walk_contexts(c);
01930    }
01931 
01932    /* we can't find the right one context */
01933    ast_unlock_contexts();
01934    return -1;
01935 }

int ast_context_remove_include2 struct ast_context con,
char *  include,
char *  registrar
 

Removes an include by an ast_context structure.

See add_include2

Definition at line 1945 of file pbx.c.

References ast_mutex_lock, ast_mutex_unlock, free, ast_context::includes, ast_context::lock, and ast_include::next.

Referenced by ast_context_remove_include().

01946 {
01947    struct ast_include *i, *pi = NULL;
01948 
01949    if (ast_mutex_lock(&con->lock)) return -1;
01950 
01951    /* walk includes */
01952    i = con->includes;
01953    while (i) {
01954       /* find our include */
01955       if (!strcmp(i->name, include) && 
01956          (!strcmp(i->registrar, registrar) || !registrar)) {
01957          /* remove from list */
01958          if (pi)
01959             pi->next = i->next;
01960          else
01961             con->includes = i->next;
01962          /* free include and return */
01963          free(i);
01964          ast_mutex_unlock(&con->lock);
01965          return 0;
01966       }
01967       pi = i;
01968       i = i->next;
01969    }
01970 
01971    /* we can't find the right include */
01972    ast_mutex_unlock(&con->lock);
01973    return -1;
01974 }

int ast_context_remove_switch char *  context,
char *  sw,
char *  data,
char *  registrar
 

Remove a switch.

Removes a switch with the given parameters Returns 0 on success, -1 on failure

Definition at line 1981 of file pbx.c.

References ast_context_remove_switch2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().

01982 {
01983    struct ast_context *c;
01984 
01985    if (ast_lock_contexts()) return -1;
01986 
01987    /* walk contexts and search for the right one ...*/
01988    c = ast_walk_contexts(NULL);
01989    while (c) {
01990       /* we found one ... */
01991       if (!strcmp(ast_get_context_name(c), context)) {
01992          int ret;
01993          /* remove switch from this context ... */ 
01994          ret = ast_context_remove_switch2(c, sw, data, registrar);
01995 
01996          ast_unlock_contexts();
01997 
01998          /* ... return results */
01999          return ret;
02000       }
02001       c = ast_walk_contexts(c);
02002    }
02003 
02004    /* we can't find the right one context */
02005    ast_unlock_contexts();
02006    return -1;
02007 }

int ast_context_remove_switch2 struct ast_context con,
char *  sw,
char *  data,
char *  registrar
 

Definition at line 2017 of file pbx.c.

References ast_context::alts, ast_mutex_lock, ast_mutex_unlock, free, ast_context::lock, and ast_sw::next.

Referenced by ast_context_remove_switch().

02018 {
02019    struct ast_sw *i, *pi = NULL;
02020 
02021    if (ast_mutex_lock(&con->lock)) return -1;
02022 
02023    /* walk switchs */
02024    i = con->alts;
02025    while (i) {
02026       /* find our switch */
02027       if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 
02028          (!strcmp(i->registrar, registrar) || !registrar)) {
02029          /* remove from list */
02030          if (pi)
02031             pi->next = i->next;
02032          else
02033             con->alts = i->next;
02034          /* free switch and return */
02035          free(i);
02036          ast_mutex_unlock(&con->lock);
02037          return 0;
02038       }
02039       pi = i;
02040       i = i->next;
02041    }
02042 
02043    /* we can't find the right switch */
02044    ast_mutex_unlock(&con->lock);
02045    return -1;
02046 }

int ast_context_verify_includes struct ast_context con  ) 
 

Verifies includes in an ast_contect structure.

Parameters:
con context in which to verify the includes Returns 0 if no problems found, -1 if there were any missing context

Definition at line 4731 of file pbx.c.

04732 {
04733    struct ast_include *inc;
04734    int res = 0;
04735 
04736    for (inc = ast_walk_context_includes(con, NULL); inc; inc = ast_walk_context_includes(con, inc))
04737       if (!ast_context_find(inc->rname)) {
04738          res = -1;
04739          ast_log(LOG_WARNING, "Context '%s' tries includes non-existant context '%s'\n",
04740                ast_get_context_name(con), inc->rname);
04741       }
04742    return res;
04743 }

int ast_device_state_changed const char *  fmt,
... 
 

Tells Asterisk the State for Device is changed.

Parameters:
fmt devicename like a dialstring with format parameters Asterisk polls the new extensionstates and calls the registered callbacks for the changed extensions Returns 0 on success, -1 on failure

Referenced by ast_channel_free(), and ast_setstate().

int ast_exec_extension struct ast_channel c,
char *  context,
char *  exten,
int  priority,
char *  callerid
 

Execute an extension.

Parameters:
c channel to execute upon
context which context extension is in
exten extension to execute
priority priority to execute within the given extension If it's not available, do whatever you should do for default extensions and halt the thread if necessary. This function does not return, except on error.

int ast_exists_extension struct ast_channel c,
char *  context,
char *  exten,
int  priority,
char *  callerid
 

If an extension exists, return non-zero.

Parameters:
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 If an extension within the given context(or callerid) with the given priority is found a non zero value will be returned. Otherwise, 0 is returned.

Definition at line 1638 of file pbx.c.

References HELPER_EXISTS.

Referenced by ast_pbx_run().

01639 {
01640    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
01641 }

int ast_extension_match char *  pattern,
char *  extension
 

Determine if a given extension matches a given pattern (in NXX format).

Parameters:
pattern pattern to match
extension extension to check against the pattern. Checks whether or not the given extension matches the given pattern. Returns 1 on match, 0 on failure

Definition at line 564 of file pbx.c.

References EXTENSION_MATCH_CORE.

00565 {
00566    int match;
00567    /* If they're the same return */
00568    if (!strcmp(pattern, data))
00569       return 1;
00570    EXTENSION_MATCH_CORE(data,pattern,match);
00571    /* Must be at the end of both */
00572    if (*data || (*pattern && (*pattern != '/')))
00573       match = 0;
00574    return match;
00575 }

int ast_extension_patmatch const char *  pattern,
const char *  data
 

int ast_extension_state struct ast_channel c,
char *  context,
char *  exten
 

Uses hint and devicestate callback to get the state of an extension.

Parameters:
c this is not important
context which context to look in
exten which extension to get state Returns extension state !! = AST_EXTENSION_???

Definition at line 1308 of file pbx.c.

01309 {
01310     struct ast_exten *e;
01311 
01312     e = ast_hint_extension(c, context, exten);    
01313     if (!e) 
01314    return -1;
01315 
01316     return ast_extension_state2(e);    
01317 }

int ast_extension_state_add char *  context,
char *  exten,
ast_state_cb_type  callback,
void *  data
 

Registers a state change callback.

Parameters:
context which context to look in
exten which extension to get state
callback callback to call if state changed
data to pass to callback The callback is called if the state for extension is changed Return -1 on failure, ID on success

Definition at line 1386 of file pbx.c.

References ast_mutex_lock, ast_mutex_unlock, ast_state_cb_type, ast_state_cb::data, hints, malloc, ast_hint::next, and statecbs.

Referenced by init_manager().

01388 {
01389     struct ast_hint *list;
01390     struct ast_state_cb *cblist;
01391     struct ast_exten *e;
01392 
01393     /* No context and extension add callback to statecbs list */
01394     if (!context && !exten) {
01395    ast_mutex_lock(&hintlock);
01396 
01397    cblist = statecbs;
01398    while (cblist) {
01399        if (cblist->callback == callback) {
01400       cblist->data = data;
01401       ast_mutex_unlock(&hintlock);
01402        }
01403        
01404        cblist = cblist->next;
01405    }
01406    
01407    /* Now inserts the callback */
01408    cblist = malloc(sizeof(struct ast_state_cb));
01409    if (!cblist) {
01410        ast_mutex_unlock(&hintlock);
01411        return -1;
01412    }
01413    memset(cblist, 0, sizeof(struct ast_state_cb));
01414    cblist->id = 0;
01415    cblist->callback = callback;
01416    cblist->data = data;
01417 
01418         cblist->next = statecbs;
01419    statecbs = cblist;
01420 
01421    ast_mutex_unlock(&hintlock);
01422    return 0;
01423     }
01424 
01425     if (!context || !exten)
01426    return -1;
01427 
01428     /* This callback type is for only one hint */
01429     e = ast_hint_extension(NULL, context, exten);    
01430     if (!e) {
01431         return -1;
01432     }
01433     
01434     ast_mutex_lock(&hintlock);
01435     list = hints;        
01436     
01437     while (list) {
01438    if (list->exten == e)
01439        break;      
01440    list = list->next;    
01441     }
01442 
01443     if (!list) {
01444    ast_mutex_unlock(&hintlock);
01445    return -1;
01446     }
01447 
01448     /* Now inserts the callback */
01449     cblist = malloc(sizeof(struct ast_state_cb));
01450     if (!cblist) {
01451    ast_mutex_unlock(&hintlock);
01452    return -1;
01453     }
01454     memset(cblist, 0, sizeof(struct ast_state_cb));
01455     cblist->id = stateid++;
01456     cblist->callback = callback;
01457     cblist->data = data;
01458 
01459     cblist->next = list->callbacks;
01460     list->callbacks = cblist;
01461 
01462     ast_mutex_unlock(&hintlock);
01463     return cblist->id;
01464 }

int ast_extension_state_del int  id,
ast_state_cb_type  callback
 

Deletes a registered state change callback by ID.

Parameters:
id of the callback to delete Removes the callback from list of callbacks Return 0 on success, -1 on failure

Definition at line 1466 of file pbx.c.

References ast_mutex_lock, ast_mutex_unlock, ast_state_cb_type, ast_hint::callbacks, free, hints, ast_state_cb::next, and statecbs.

01467 {
01468     struct ast_hint *list;
01469     struct ast_state_cb *cblist, *cbprev;
01470     
01471     if (!id && !callback)
01472    return -1;
01473             
01474     ast_mutex_lock(&hintlock);
01475 
01476     /* id is zero is a callback without extension */
01477     if (!id) {
01478    cbprev = NULL;
01479    cblist = statecbs;
01480    while (cblist) {
01481        if (cblist->callback == callback) {
01482       if (!cbprev)
01483           statecbs = cblist->next;
01484       else
01485           cbprev->next = cblist->next;
01486 
01487       free(cblist);
01488 
01489            ast_mutex_unlock(&hintlock);
01490       return 0;
01491        }
01492        cbprev = cblist;
01493        cblist = cblist->next;
01494    }
01495 
01496         ast_mutex_lock(&hintlock);
01497    return -1;
01498     }
01499 
01500     /* id greater zero is a callback with extension */
01501     list = hints;
01502     while (list) {
01503    cblist = list->callbacks;
01504    cbprev = NULL;
01505    while (cblist) {
01506        if (cblist->id==id) {
01507       if (!cbprev)
01508           list->callbacks = cblist->next;    
01509       else
01510           cbprev->next = cblist->next;
01511       
01512       free(cblist);
01513       
01514       ast_mutex_unlock(&hintlock);
01515       return 0;      
01516        }    
01517           cbprev = cblist;          
01518        cblist = cblist->next;
01519    }
01520    list = list->next;
01521     }
01522     
01523     ast_mutex_unlock(&hintlock);
01524     return -1;
01525 }

char* ast_get_context_name struct ast_context con  ) 
 

Definition at line 4602 of file pbx.c.

References ast_ignorepat::pattern.

Referenced by ast_context_remove_extension(), ast_context_remove_include(), ast_context_remove_switch(), and ast_ignore_pattern().

04603 {
04604    return con ? con->name : NULL;
04605 }

char* ast_get_context_registrar struct ast_context c  ) 
 

Definition at line 4630 of file pbx.c.

References ast_ignorepat::registrar.

04631 {
04632    return c ? c->registrar : NULL;
04633 }

char* ast_get_extension_app struct ast_exten e  ) 
 

Definition at line 4650 of file pbx.c.

References ast_sw::data.

Referenced by ast_device_state_changed(), and ast_get_hint().

04651 {
04652    return e ? e->app : NULL;
04653 }

void* ast_get_extension_app_data struct ast_exten e  ) 
 

Definition at line 4655 of file pbx.c.

References ast_sw::registrar.

04656 {
04657    return e ? e->data : NULL;
04658 }

char* ast_get_extension_name struct ast_exten exten  ) 
 

Definition at line 4607 of file pbx.c.

References ast_exten::priority.

04608 {
04609    return exten ? exten->exten : NULL;
04610 }

int ast_get_extension_priority struct ast_exten exten  ) 
 

Definition at line 4622 of file pbx.c.

04623 {
04624    return exten ? exten->priority : -1;
04625 }

char* ast_get_extension_registrar struct ast_exten e  ) 
 

Definition at line 4635 of file pbx.c.

References ast_exten::app.

04636 {
04637    return e ? e->registrar : NULL;
04638 }

int ast_get_hint char *  hint,
int  maxlen,
struct ast_channel c,
char *  context,
char *  exten
 

If an extension exists, return non-zero.

Parameters:
hint buffer for hint
maxlen size of hint buffer
c this is not important
context which context to look in
exten which extension to search for If an extension within the given context with the priority PRIORITY_HINT is found a non zero value will be returned. Otherwise, 0 is returned.

Definition at line 1627 of file pbx.c.

References ast_get_extension_app().

01628 {
01629    struct ast_exten *e;
01630    e = ast_hint_extension(c, context, exten);
01631    if (e) { 
01632        strncpy(hint, ast_get_extension_app(e), maxlen);
01633        return -1;
01634    }
01635    return 0;   
01636 }

char* ast_get_ignorepat_name struct ast_ignorepat ip  ) 
 

Definition at line 4617 of file pbx.c.

04618 {
04619    return ip ? ip->pattern : NULL;
04620 }

char* ast_get_ignorepat_registrar struct ast_ignorepat ip  ) 
 

Definition at line 4645 of file pbx.c.

References ast_sw::name.

04646 {
04647    return ip ? ip->registrar : NULL;
04648 }

char* ast_get_include_name struct ast_include include  ) 
 

Definition at line 4612 of file pbx.c.

References ast_context::registrar.

04613 {
04614    return inc ? inc->name : NULL;
04615 }

char* ast_get_include_registrar struct ast_include i  ) 
 

Definition at line 4640 of file pbx.c.

References ast_exten::data.

04641 {
04642    return i ? i->registrar : NULL;
04643 }

char* ast_get_switch_data struct ast_sw sw  ) 
 

Definition at line 4665 of file pbx.c.

04666 {
04667    return sw ? sw->data : NULL;
04668 }

char* ast_get_switch_name struct ast_sw sw  ) 
 

Definition at line 4660 of file pbx.c.

04661 {
04662    return sw ? sw->name : NULL;
04663 }

char* ast_get_switch_registrar struct ast_sw sw  ) 
 

Definition at line 4670 of file pbx.c.

References ast_exten::next, and ast_context::root.

04671 {
04672    return sw ? sw->registrar : NULL;
04673 }

int ast_ignore_pattern char *  context,
char *  pattern
 

Checks to see if a number should be ignored.

Parameters:
context context to search within
extension to check whether it should be ignored or not Check if a number should be ignored with respect to dialtone cancellation. Returns 0 if the pattern should not be ignored, or non-zero if the pattern should be ignored

Definition at line 3449 of file pbx.c.

References ast_add_extension2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().

03450 {
03451    struct ast_context *con;
03452    struct ast_ignorepat *pat;
03453    con = ast_context_find(context);
03454    if (con) {
03455       pat = con->ignorepats;
03456       while (pat) {
03457          if (ast_extension_match(pat->pattern, pattern))
03458             return 1;
03459          pat = pat->next;
03460       }
03461    } 
03462    return 0;
03463 }

int ast_lock_context struct ast_context con  ) 
 

Locks a given context.

Parameters:
con context to lock Locks the context. Returns 0 on success, -1 on failure

Definition at line 4589 of file pbx.c.

04590 {
04591    return ast_mutex_lock(&con->lock);
04592 }

int ast_lock_contexts void   ) 
 

Locks the contexts.

Locks the context list Returns 0 on success, -1 on error

Definition at line 4576 of file pbx.c.

Referenced by ast_context_remove_extension(), ast_context_remove_include(), ast_context_remove_switch(), and ast_ignore_pattern().

04577 {
04578    return ast_mutex_lock(&conlock);
04579 }

int ast_matchmore_extension struct ast_channel c,
char *  context,
char *  exten,
int  priority,
char *  callerid
 

Looks to see if adding anything to this extension might match something. (exists ^ canmatch).

Parameters:
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 If "exten" *could match* a valid extension in this context with some more digits, return non-zero. Does NOT return non-zero if this is an exact-match only. Basically, when this returns 0, no matter what you add to exten, it's not going to be a valid extension anymore

Definition at line 1648 of file pbx.c.

References HELPER_MATCHMORE.

Referenced by ast_pbx_run().

01649 {
01650    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE);
01651 }

void ast_merge_contexts_and_delete struct ast_context **  extcontexts,
char *  registrar
 

Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.

Parameters:
extcontexts pointer to the ast_context structure pointer
registar 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 2823 of file pbx.c.

02823                                                                                       {
02824    struct ast_context *tmp, *lasttmp = NULL;
02825    tmp = *extcontexts;
02826    ast_mutex_lock(&conlock);
02827    if (registrar) {
02828       __ast_context_destroy(NULL,registrar,0);
02829       while (tmp) {
02830          lasttmp = tmp;
02831          tmp = tmp->next;
02832       }
02833    } else {
02834       while (tmp) {
02835          __ast_context_destroy(tmp,tmp->registrar,0);
02836          lasttmp = tmp;
02837          tmp = tmp->next;
02838       }
02839    }
02840    if (lasttmp) {
02841       lasttmp->next = contexts;
02842       contexts = *extcontexts;
02843       *extcontexts = NULL;
02844    } else 
02845       ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
02846    ast_mutex_unlock(&conlock);
02847    return;  
02848 }

int ast_pbx_outgoing_app char *  type,
int  format,
void *  data,
int  timeout,
char *  app,
char *  appdata,
int *  reason,
int  sync,
char *  callerid,
char *  variable,
char *  account
 

Definition at line 3973 of file pbx.c.

03974 {
03975    struct ast_channel *chan;
03976    struct async_stat *as;
03977    struct app_tmp *tmp;
03978    char *var, *vartmp;
03979    int res = -1;
03980    pthread_attr_t attr;
03981    
03982    if (!app || !strlen(app))
03983       return -1;
03984    if (sync) {
03985       chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
03986       if (chan) {
03987          pbx_builtin_setaccount(chan, account);
03988          if (variable) {
03989             vartmp = ast_strdupa(variable);
03990             for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp)) {
03991                pbx_builtin_setvar( chan, var );
03992             }
03993          }
03994          if (chan->_state == AST_STATE_UP) {
03995             res = 0;
03996             if (option_verbose > 3)
03997                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
03998             tmp = malloc(sizeof(struct app_tmp));
03999             if (tmp) {
04000                memset(tmp, 0, sizeof(struct app_tmp));
04001                strncpy(tmp->app, app, sizeof(tmp->app) - 1);
04002                strncpy(tmp->data, appdata, sizeof(tmp->data) - 1);
04003                tmp->chan = chan;
04004                if (sync > 1) {
04005                   ast_pbx_run_app(tmp);
04006                } else {
04007                   pthread_attr_init(&attr);
04008                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04009                   if (pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
04010                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
04011                      free(tmp);
04012                      ast_hangup(chan);
04013                      res = -1;
04014                   }
04015                }
04016             } else {
04017                ast_log(LOG_ERROR, "Out of memory :(\n");
04018                res = -1;
04019             }
04020          } else {
04021             if (option_verbose > 3)
04022                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
04023             ast_hangup(chan);
04024          }
04025       }
04026    } else {
04027       as = malloc(sizeof(struct async_stat));
04028       if (!as)
04029          return -1;
04030       memset(as, 0, sizeof(struct async_stat));
04031       chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
04032       if (!chan) {
04033          free(as);
04034          return -1;
04035       }
04036       pbx_builtin_setaccount(chan, account);
04037       as->chan = chan;
04038       strncpy(as->app, app, sizeof(as->app) - 1);
04039       if (appdata)
04040          strncpy(as->appdata,  appdata, sizeof(as->appdata) - 1);
04041       as->timeout = timeout;
04042       if (pthread_create(&as->p, NULL, async_wait, as)) {
04043          ast_log(LOG_WARNING, "Failed to start async wait\n");
04044          free(as);
04045          ast_hangup(chan);
04046          return -1;
04047       }
04048       res = 0;
04049    }
04050    return res;
04051 }

int ast_pbx_outgoing_exten char *  type,
int  format,
void *  data,
int  timeout,
char *  context,
char *  exten,
int  priority,
int *  reason,
int  sync,
char *  callerid,
char *  variable,
char *  account
 

Definition at line 3862 of file pbx.c.

References option_verbose.

03863 {
03864    struct ast_channel *chan;
03865    struct async_stat *as;
03866    int res = -1;
03867    char *var, *tmp;
03868    struct outgoing_helper oh;
03869    pthread_attr_t attr;
03870       
03871    if (sync) {
03872       LOAD_OH(oh);
03873       chan = __ast_request_and_dial(type, format, data, timeout, reason, callerid, &oh);
03874       if (chan) {
03875          pbx_builtin_setaccount(chan, account);
03876          if (chan->_state == AST_STATE_UP) {
03877                res = 0;
03878             if (option_verbose > 3)
03879                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
03880 
03881             if (sync > 1) {
03882                if (ast_pbx_run(chan)) {
03883                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
03884                   ast_hangup(chan);
03885                   res = -1;
03886                }
03887             } else {
03888                if (ast_pbx_start(chan)) {
03889                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
03890                   ast_hangup(chan);
03891                   res = -1;
03892                } 
03893             }
03894          } else {
03895             if (option_verbose > 3)
03896                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
03897             ast_hangup(chan);
03898          }
03899       } else {
03900          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
03901          /* check if "failed" exists */
03902          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
03903             chan = ast_channel_alloc(0);
03904             if (chan) {
03905                strncpy(chan->name, "OutgoingSpoolFailed", sizeof(chan->name) - 1);
03906                if (context && strlen(context))
03907                   strncpy(chan->context, context, sizeof(chan->context) - 1);
03908                strncpy(chan->exten, "failed", sizeof(chan->exten) - 1);
03909                chan->priority = 1;
03910                if (variable) {
03911                   tmp = ast_strdupa(variable);
03912                   for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp)) {
03913                      pbx_builtin_setvar( chan, var );
03914                   }
03915                }
03916                ast_pbx_run(chan);   
03917             } else
03918                ast_log(LOG_WARNING, "Can't allocate the channel structure, skipping execution of extension 'failed'\n");
03919          }
03920       }
03921    } else {
03922       as = malloc(sizeof(struct async_stat));
03923       if (!as)
03924          return -1;
03925       memset(as, 0, sizeof(struct async_stat));
03926       chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
03927       if (!chan) {
03928          free(as);
03929          return -1;
03930       }
03931       pbx_builtin_setaccount(chan, account);
03932       as->chan = chan;
03933       strncpy(as->context, context, sizeof(as->context) - 1);
03934       strncpy(as->exten,  exten, sizeof(as->exten) - 1);
03935       as->priority = priority;
03936       as->timeout = timeout;
03937       pthread_attr_init(&attr);
03938       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
03939       if (pthread_create(&as->p, &attr, async_wait, as)) {
03940          ast_log(LOG_WARNING, "Failed to start async wait\n");
03941          free(as);
03942          ast_hangup(chan);
03943          return -1;
03944       }
03945       res = 0;
03946    }
03947    return res;
03948 }

int ast_pbx_run struct ast_channel c  ) 
 

Execute the PBX in the current thread.

Parameters:
c channel to run the pbx on This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality.

Definition at line 1658 of file pbx.c.

References ast_channel::_softhangup, ast_channel::amaflags, ast_cdr_alloc(), ast_cdr_init(), ast_cdr_start(), ast_cdr_update(), ast_exists_extension(), ast_hangup(), ast_log(), ast_matchmore_extension(), AST_PBX_KEEPALIVE, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_verbose(), ast_waitfordigit(), ast_channel::callerid, ast_channel::cdr, ast_channel::context, ast_pbx::dtimeout, EVENT_FLAG_CALL, ast_channel::exten, free, LOG_DEBUG, LOG_ERROR, LOG_WARNING, malloc, manager_event(), ast_channel::name, option_debug, option_verbose, ast_channel::pbx, pbx_builtin_setvar_helper(), ast_channel::priority, ast_pbx::rtimeout, ast_channel::uniqueid, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, and ast_channel::whentohangup.

01659 {
01660    int firstpass = 1;
01661    char digit;
01662    char exten[256];
01663    int pos;
01664    int waittime;
01665    int res=0;
01666 
01667    /* A little initial setup here */
01668    if (c->pbx)
01669       ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
01670    c->pbx = malloc(sizeof(struct ast_pbx));
01671    if (!c->pbx) {
01672       ast_log(LOG_ERROR, "Out of memory\n");
01673       return -1;
01674    }
01675    if (c->amaflags) {
01676       if (c->cdr) {
01677          ast_log(LOG_WARNING, "%s already has a call record??\n", c->name);
01678       } else {
01679          c->cdr = ast_cdr_alloc();
01680          if (!c->cdr) {
01681             ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
01682             free(c->pbx);
01683             return -1;
01684          }
01685          ast_cdr_init(c->cdr, c);
01686       }
01687    }
01688    memset(c->pbx, 0, sizeof(struct ast_pbx));
01689    /* Set reasonable defaults */
01690    c->pbx->rtimeout = 10;
01691    c->pbx->dtimeout = 5;
01692 
01693    /* Start by trying whatever the channel is set to */
01694    if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01695       /* JK02: If not successfull fall back to 's' */
01696       strncpy(c->exten, "s", sizeof(c->exten)-1);
01697       if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01698          /* JK02: And finally back to default if everything else failed */
01699          strncpy(c->context, "default", sizeof(c->context)-1);
01700       }
01701       c->priority = 1;
01702    }
01703    if (c->cdr)
01704       ast_cdr_start(c->cdr);
01705    for(;;) {
01706       pos = 0;
01707       digit = 0;
01708       while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01709          memset(exten, 0, sizeof(exten));
01710          manager_event(EVENT_FLAG_CALL, "Newexten", 
01711             "Channel: %s\r\n"
01712             "Context: %s\r\n"
01713             "Extension: %s\r\n"
01714             "Priority: %d\r\n"
01715             "Uniqueid: %s\r\n",
01716             c->name, c->context, c->exten, c->priority, c->uniqueid);
01717          if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
01718             /* Something bad happened, or a hangup has been requested. */
01719             if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
01720                (res == '*') || (res == '#')) {
01721                ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
01722                memset(exten, 0, sizeof(exten));
01723                pos = 0;
01724                exten[pos++] = digit = res;
01725                break;
01726             }
01727             switch(res) {
01728             case AST_PBX_KEEPALIVE:
01729                if (option_debug)
01730                   ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
01731                else if (option_verbose > 1)
01732                   ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
01733                goto out;
01734                break;
01735             default:
01736                if (option_debug)
01737                   ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01738                else if (option_verbose > 1)
01739                   ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01740                if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
01741                   c->_softhangup =0;
01742                   break;
01743                }
01744                /* atimeout */
01745                if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
01746                   break;
01747                }
01748 
01749                if (c->cdr) {
01750                   ast_cdr_update(c);
01751                }
01752                goto out;
01753             }
01754          }
01755          if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->callerid))) {
01756             strncpy(c->exten,"T",sizeof(c->exten) - 1);
01757             /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
01758             c->whentohangup = 0;
01759             c->priority = 0;
01760             c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
01761          } else if (c->_softhangup) {
01762             ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
01763                c->exten, c->priority);
01764             goto out;
01765          }
01766          firstpass = 0;
01767          c->priority++;
01768       }
01769       if (!ast_exists_extension(c, c->context, c->exten, 1, c->callerid)) {
01770          /* It's not a valid extension anymore */
01771          if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
01772             if (option_verbose > 2)
01773                ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
01774             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
01775             strncpy(c->exten, "i", sizeof(c->exten)-1);
01776             c->priority = 1;
01777          } else {
01778             ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
01779                c->name, c->exten, c->context);
01780             goto out;
01781          }
01782       } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
01783          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
01784          c->_softhangup = 0;
01785       } else {
01786          /* Done, wait for an extension */
01787          if (digit)
01788             waittime = c->pbx->dtimeout;
01789          else
01790             waittime = c->pbx->rtimeout;
01791          while (ast_matchmore_extension(c, c->context, exten, 1, c->callerid)) {
01792             /* As long as we're willing to wait, and as long as it's not defined, 
01793                keep reading digits until we can't possibly get a right answer anymore.  */
01794             digit = ast_waitfordigit(c, waittime * 1000);
01795             if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
01796                c->_softhangup = 0;
01797             } else {
01798                if (!digit)
01799                   /* No entry */
01800                   break;
01801                if (digit < 0)
01802                   /* Error, maybe a  hangup */
01803                   goto out;
01804                exten[pos++] = digit;
01805                waittime = c->pbx->dtimeout;
01806             }
01807          }
01808          if (ast_exists_extension(c, c->context, exten, 1, c->callerid)) {
01809             /* Prepare the next cycle */
01810             strncpy(c->exten, exten, sizeof(c->exten)-1);
01811             c->priority = 1;
01812          } else {
01813             /* No such extension */
01814             if (strlen(exten)) {
01815                /* An invalid extension */
01816                if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
01817                   if (option_verbose > 2)
01818                      ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
01819                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
01820                   strncpy(c->exten, "i", sizeof(c->exten)-1);
01821                   c->priority = 1;
01822                } else {
01823                   ast_log(LOG_WARNING, "Invalid extension, but no rule 'i' in context '%s'\n", c->context);
01824                   goto out;
01825                }
01826             } else {
01827                /* A simple timeout */
01828                if (ast_exists_extension(c, c->context, "t", 1, c->callerid)) {
01829                   if (option_verbose > 2)
01830                      ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
01831                   strncpy(c->exten, "t", sizeof(c->exten)-1);
01832                   c->priority = 1;
01833                } else {
01834                   ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
01835                   goto out;
01836                }
01837             }  
01838          }
01839          if (c->cdr) {
01840              if (option_verbose > 2)
01841             ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);   
01842              ast_cdr_update(c);
01843           }
01844       }
01845    }
01846    if (firstpass) 
01847       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
01848 out:
01849    if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->callerid)) {
01850       strcpy(c->exten, "h");
01851       c->priority = 1;
01852       while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01853          if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
01854             /* Something bad happened, or a hangup has been requested. */
01855             if (option_debug)
01856                ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01857             else if (option_verbose > 1)
01858                ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01859             break;
01860          }
01861          c->priority++;
01862       }
01863    }
01864 
01865    pbx_destroy(c->pbx);
01866    c->pbx = NULL;
01867    if (res != AST_PBX_KEEPALIVE)
01868       ast_hangup(c);
01869    return 0;
01870 }

int ast_pbx_start struct ast_channel c  ) 
 

Create a new thread and start the PBX (or whatever).

Parameters:
c channel to start the pbx on Starts a pbx thread on a given channel It returns -1 on failure, and 0 on success

Definition at line 1885 of file pbx.c.

References ast_log(), and LOG_WARNING.

01886 {
01887    pthread_t t;
01888    pthread_attr_t attr;
01889    if (!c) {
01890       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
01891       return -1;
01892    }
01893       
01894    /* Start a new thread, and get something handling this channel. */
01895    pthread_attr_init(&attr);
01896    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01897    if (pthread_create(&t, &attr, pbx_thread, c)) {
01898       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
01899       return -1;
01900    }
01901    return 0;
01902 }

int ast_register_application char *  app,
int(*  execute)(struct ast_channel *, void *),
char *  synopsis,
char *  description
 

Add an application. The function 'execute' should return non-zero if the line needs to be hung up.

Parameters:
app Short name of the application
execute a function callback to execute the application
synopsis a short description of the application
description long description of the application Include a one-line synopsis (e.g. 'hangs up a channel') and a more lengthy, multiline description with more detail, including under what conditions the application will return 0 or -1. This registers an application with asterisks internal application list. Please note: The individual applications themselves are responsible for registering and unregistering CLI commands. It returns 0 on success, -1 on failure.

Definition at line 2193 of file pbx.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), COLOR_BRCYAN, description(), LOG_ERROR, LOG_WARNING, malloc, ast_app::next, option_verbose, term_color(), and VERBOSE_PREFIX_2.

02194 {
02195    struct ast_app *tmp, *prev, *cur;
02196    char tmps[80];
02197    if (ast_mutex_lock(&applock)) {
02198       ast_log(LOG_ERROR, "Unable to lock application list\n");
02199       return -1;
02200    }
02201    tmp = apps;
02202    while(tmp) {
02203       if (!strcasecmp(app, tmp->name)) {
02204          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
02205          ast_mutex_unlock(&applock);
02206          return -1;
02207       }
02208       tmp = tmp->next;
02209    }
02210    tmp = malloc(sizeof(struct ast_app));
02211    if (tmp) {
02212       memset(tmp, 0, sizeof(struct ast_app));
02213       strncpy(tmp->name, app, sizeof(tmp->name)-1);
02214       tmp->execute = execute;
02215       tmp->synopsis = synopsis;
02216       tmp->description = description;
02217       /* Store in alphabetical order */
02218       cur = apps;
02219       prev = NULL;
02220       while(cur) {
02221          if (strcasecmp(tmp->name, cur->name) < 0)
02222             break;
02223          prev = cur;
02224          cur = cur->next;
02225       }
02226       if (prev) {
02227          tmp->next = prev->next;
02228          prev->next = tmp;
02229       } else {
02230          tmp->next = apps;
02231          apps = tmp;
02232       }
02233    } else {
02234       ast_log(LOG_ERROR, "Out of memory\n");
02235       ast_mutex_unlock(&applock);
02236       return -1;
02237    }
02238    if (option_verbose > 1)
02239       ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
02240    ast_mutex_unlock(&applock);
02241    return 0;
02242 }

int ast_register_switch struct ast_switch sw  ) 
 

Register an alternative switch.

Parameters:
sw switch to register This function registers a populated ast_switch structure with the asterisk switching architecture. It returns 0 on success, and other than 0 on failure

Definition at line 2244 of file pbx.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_ERROR, LOG_WARNING, ast_switch::name, ast_switch::next, and switches.

02245 {
02246    struct ast_switch *tmp, *prev=NULL;
02247    if (ast_mutex_lock(&switchlock)) {
02248       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02249       return -1;
02250    }
02251    tmp = switches;
02252    while(tmp) {
02253       if (!strcasecmp(tmp->name, sw->name))
02254          break;
02255       prev = tmp;
02256       tmp = tmp->next;
02257    }
02258    if (tmp) {  
02259       ast_mutex_unlock(&switchlock);
02260       ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
02261       return -1;
02262    }
02263    sw->next = NULL;
02264    if (prev) 
02265       prev->next = sw;
02266    else
02267       switches = sw;
02268    ast_mutex_unlock(&switchlock);
02269    return 0;
02270 }

int ast_spawn_extension struct ast_channel c,
char *  context,
char *  exten,
int  priority,
char *  callerid
 

Launch a new extension (i.e. new stack).

Parameters:
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 This adds a new extension to the asterisk extension list. It returns 0 on success, -1 on failure.

Definition at line 1653 of file pbx.c.

References HELPER_SPAWN.

Referenced by ast_pbx_run().

01654 {
01655    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN);
01656 }

int ast_unlock_context struct ast_context con  ) 
 

Unlocks the given context.

Parameters:
con context to unlock Unlocks the given context Returns 0 on success, -1 on failure

Definition at line 4594 of file pbx.c.

04595 {
04596    return ast_mutex_unlock(&con->lock);
04597 }

int ast_unlock_contexts void   ) 
 

Unlocks contexts.

Returns 0 on success, -1 on failure

Definition at line 4581 of file pbx.c.

Referenced by ast_context_remove_extension(), ast_context_remove_include(), ast_context_remove_switch(), and ast_ignore_pattern().

04582 {
04583    return ast_mutex_unlock(&conlock);
04584 }

int ast_unregister_application char *  app  ) 
 

Remove an application.

Parameters:
app name of the application (does not have to be the same string as the one that was registered) This unregisters an application from asterisk's internal registration mechanisms. It returns 0 on success, and -1 on failure.

Definition at line 2753 of file pbx.c.

02753                                           {
02754    struct ast_app *tmp, *tmpl = NULL;
02755    if (ast_mutex_lock(&applock)) {
02756       ast_log(LOG_ERROR, "Unable to lock application list\n");
02757       return -1;
02758    }
02759    tmp = apps;
02760    while(tmp) {
02761       if (!strcasecmp(app, tmp->name)) {
02762          if (tmpl)
02763             tmpl->next = tmp->next;
02764          else
02765             apps = tmp->next;
02766          if (option_verbose > 1)
02767             ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
02768          ast_mutex_unlock(&applock);
02769          return 0;
02770       }
02771       tmpl = tmp;
02772       tmp = tmp->next;
02773    }
02774    ast_mutex_unlock(&applock);
02775    return -1;
02776 }

void ast_unregister_switch struct ast_switch sw  ) 
 

Unregister an alternative switch.

Parameters:
sw switch to unregister Unregisters a switch from asterisk. Returns nothing

Definition at line 2272 of file pbx.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_ERROR, ast_switch::next, and switches.

02273 {
02274    struct ast_switch *tmp, *prev=NULL;
02275    if (ast_mutex_lock(&switchlock)) {
02276       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02277       return;
02278    }
02279    tmp = switches;
02280    while(tmp) {
02281       if (tmp == sw) {
02282          if (prev)
02283             prev->next = tmp->next;
02284          else
02285             switches = tmp->next;
02286          tmp->next = NULL;
02287          break;         
02288       }
02289       prev = tmp;
02290       tmp = tmp->next;
02291    }
02292    ast_mutex_unlock(&switchlock);
02293 }

struct ast_exten* ast_walk_context_extensions struct ast_context con,
struct ast_exten priority
 

Definition at line 4686 of file pbx.c.

04688 {
04689    if (!exten)
04690       return con ? con->root : NULL;
04691    else
04692       return exten->next;
04693 }

struct ast_ignorepat* ast_walk_context_ignorepats struct ast_context con,
struct ast_ignorepat ip
 

Definition at line 4722 of file pbx.c.

04724 {
04725    if (!ip)
04726       return con ? con->ignorepats : NULL;
04727    else
04728       return ip->next;
04729 }

struct ast_include* ast_walk_context_includes struct ast_context con,
struct ast_include inc
 

Definition at line 4713 of file pbx.c.

04715 {
04716    if (!inc)
04717       return con ? con->includes : NULL;
04718    else
04719       return inc->next;
04720 }

struct ast_sw* ast_walk_context_switches struct ast_context con,
struct ast_sw sw
 

Definition at line 4695 of file pbx.c.

04697 {
04698    if (!sw)
04699       return con ? con->alts : NULL;
04700    else
04701       return sw->next;
04702 }

struct ast_context* ast_walk_contexts struct ast_context con  ) 
 

Definition at line 4678 of file pbx.c.

References ast_context::alts, and ast_sw::next.

Referenced by ast_context_remove_extension(), ast_context_remove_include(), ast_context_remove_switch(), and ast_ignore_pattern().

04679 {
04680    if (!con)
04681       return contexts;
04682    else
04683       return con->next;
04684 }

struct ast_exten* ast_walk_extension_priorities struct ast_exten exten,
struct ast_exten priority
 

Definition at line 4704 of file pbx.c.

04706 {
04707    if (!priority)
04708       return exten;
04709    else
04710       return priority->peer;
04711 }

void pbx_builtin_clear_globals void   ) 
 

Definition at line 4474 of file pbx.c.

04475 {
04476    struct ast_var_t *vardata;
04477    while (!AST_LIST_EMPTY(&globals)) {
04478       vardata = AST_LIST_FIRST(&globals);
04479       AST_LIST_REMOVE_HEAD(&globals, entries);
04480       ast_var_delete(vardata);
04481    }
04482 }

char* pbx_builtin_getvar_helper struct ast_channel chan,
char *  name
 

int pbx_builtin_setvar struct ast_channel chan,
void *  data
 

Referenced by __ast_request_and_dial().

void pbx_builtin_setvar_helper struct ast_channel chan,
char *  name,
char *  value
 

Referenced by ast_pbx_run().

int pbx_exec struct ast_channel c,
struct ast_app app,
void *  data,
int  newstack
 

executes an application

Parameters:
c channel to execute on
app which app to execute
data the data passed into the app
newstack stack pointer This application executes an application on a given channel. It saves the stack and executes the given appliation passing in the given data. It returns 0 on success, and -1 on failure

Definition at line 362 of file pbx.c.

References ast_channel::app, ast_channel::appl, ast_cdr_setapp(), AST_CHANNEL_MAX_STACK, ast_log(), ast_channel::cdr, ast_channel::data, ast_app::execute, ast_channel::jmp, LOG_WARNING, ast_app::name, and ast_channel::stack.

00366 {
00367    /* This function is special.  It saves the stack so that no matter
00368       how many times it is called, it returns to the same place */
00369    int res;
00370    int stack = c->stack;
00371    int (*execute)(struct ast_channel *chan, void *data) = app->execute; 
00372    if (newstack && stack > AST_CHANNEL_MAX_STACK - 2) {
00373       /* Don't allow us to go over the max number of stacks we
00374          permit saving. */
00375       ast_log(LOG_WARNING, "Stack overflow, cannot create another stack\n");
00376       return -1;
00377    }
00378    if (newstack && (res = setjmp(c->jmp[++c->stack]))) {
00379       /* Okay, here's where it gets weird.  If newstack is non-zero, 
00380          then we increase the stack increment, but setjmp is not going
00381          to return until longjmp is called -- when the application
00382          exec'd is finished running. */
00383       if (res == 1)
00384          res = 0;
00385       if (c->stack != stack + 1) 
00386          ast_log(LOG_WARNING, "Stack returned to an unexpected place!\n");
00387       else if (c->app[c->stack])
00388          ast_log(LOG_WARNING, "Application may have forgotten to free its memory\n");
00389       c->stack = stack;
00390       return res;
00391    } else {
00392       if (c->cdr)
00393          ast_cdr_setapp(c->cdr, app->name, data);
00394       c->appl = app->name;
00395       c->data = data;      
00396       res = execute(c, data);
00397       c->appl = NULL;
00398       c->data = NULL;      
00399       /* Any application that returns, we longjmp back, just in case. */
00400       if (c->stack != stack + 1)
00401          ast_log(LOG_WARNING, "Stack is not at expected value\n");
00402       longjmp(c->jmp[stack+1], res);
00403       /* Never returns */
00404    }
00405 }

struct ast_app* pbx_findapp char *  app  ) 
 

Look up an application.

Parameters:
app name of the app This function searches for the ast_app structure within the apps that are registered for the one with the name you passed in. Returns the ast_app structure that matches on success, or NULL on failure

Definition at line 417 of file pbx.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_WARNING, and ast_app::next.

00418 {
00419    struct ast_app *tmp;
00420    if (ast_mutex_lock(&applock)) {
00421       ast_log(LOG_WARNING, "Unable to obtain application lock\n");
00422       return NULL;
00423    }
00424    tmp = apps;
00425    while(tmp) {
00426       if (!strcasecmp(tmp->name, app))
00427          break;
00428       tmp = tmp->next;
00429    }
00430    ast_mutex_unlock(&applock);
00431    return tmp;
00432 }

void pbx_substitute_variables_helper struct ast_channel c,
const char *  cp1,
char *  cp2,
int  count
 

Definition at line 943 of file pbx.c.

References ast_expr(), ast_log(), free, LOG_DEBUG, and LOG_NOTICE.

00944 {
00945    char *cp4;
00946    const char *tmp, *whereweare;
00947    int length;
00948    char workspace[256];
00949    char ltmp[256], var[256];
00950    char *nextvar, *nextexp;
00951    char *vars, *vare;
00952    int pos, brackets, needsub, len;
00953 
00954    /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
00955       zero-filled */
00956    whereweare=tmp=cp1;
00957    while(strlen(whereweare) && count) {
00958       /* Assume we're copying the whole remaining string */
00959       pos = strlen(whereweare);
00960 
00961       /* Look for a variable */
00962       nextvar = strstr(whereweare, "${");
00963       
00964       nextexp = strstr(whereweare, "$[");
00965       
00966       if (nextvar && nextexp) {
00967          if (nextvar < nextexp)
00968             nextexp = NULL;
00969          else
00970             nextvar = NULL;
00971       }
00972       
00973       /* If there is one, we only go that far */
00974       if (nextvar)
00975          pos = nextvar - whereweare;
00976       else if (nextexp)
00977          pos = nextexp - whereweare;
00978       
00979       /* Can't copy more than 'count' bytes */
00980       if (pos > count)
00981          pos = count;
00982       
00983       /* Copy that many bytes */
00984       memcpy(cp2, whereweare, pos);
00985       
00986       count -= pos;
00987       cp2 += pos;
00988       whereweare += pos;
00989       
00990       if (nextvar) {
00991          /* We have a variable.  Find the start and end, and determine
00992             if we are going to have to recursively call ourselves on the
00993             contents */
00994          vars = vare = nextvar + 2;
00995          brackets = 1;
00996          needsub = 0;
00997          
00998          /* Find the end of it */
00999          while(brackets && *vare) {
01000             if ((vare[0] == '$') && (vare[1] == '{')) {
01001                needsub++;
01002                brackets++;
01003             } else if (vare[0] == '}') {
01004                brackets--;
01005             } else if ((vare[0] == '$') && (vare[1] == '['))
01006                needsub++;
01007             vare++;
01008          }
01009          if (brackets)
01010             ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
01011          len = vare - vars - 1;
01012          
01013          /* Skip totally over variable name */
01014          whereweare += ( len + 3);
01015          
01016          /* Store variable name (and truncate) */
01017          memset(var, 0, sizeof(var));
01018          strncpy(var, vars, sizeof(var) - 1);
01019          var[len] = '\0';
01020          
01021          /* Substitute if necessary */
01022          if (needsub) {
01023             memset(ltmp, 0, sizeof(ltmp));
01024             pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
01025             vars = ltmp;
01026          } else {
01027             vars = var;
01028          }
01029          
01030          /* Retrieve variable value */
01031          strcpy(workspace, "");
01032          pbx_substitute_variables_temp(c,vars,&cp4, workspace, sizeof(workspace));
01033          if (cp4) {
01034             length = strlen(cp4);
01035             if (length > count)
01036                length = count;
01037             memcpy(cp2, cp4, length);
01038             count -= length;
01039             cp2 += length;
01040          }
01041          
01042       } else if (nextexp) {
01043          /* We have an expression.  Find the start and end, and determine
01044             if we are going to have to recursively call ourselves on the
01045             contents */
01046          vars = vare = nextexp + 2;
01047          brackets = 1;
01048          needsub = 0;
01049          
01050          /* Find the end of it */
01051          while(brackets && *vare) {
01052             if ((vare[0] == '$') && (vare[1] == '[')) {
01053                needsub++;
01054                brackets++;
01055             } else if (vare[0] == ']') {
01056                brackets--;
01057             } else if ((vare[0] == '$') && (vare[1] == '{'))
01058                needsub++;
01059             vare++;
01060          }
01061          if (brackets)
01062             ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
01063          len = vare - vars - 1;
01064          
01065          /* Skip totally over variable name */
01066          whereweare += ( len + 3);
01067          
01068          /* Store variable name (and truncate) */
01069          memset(var, 0, sizeof(var));
01070          strncpy(var, vars, sizeof(var) - 1);
01071          var[len] = '\0';
01072          
01073          /* Substitute if necessary */
01074          if (needsub) {
01075             memset(ltmp, 0, sizeof(ltmp));
01076             pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
01077             vars = ltmp;
01078          } else {
01079             vars = var;
01080          }
01081 
01082          /* Evaluate expression */        
01083          cp4 = ast_expr(vars);
01084          
01085          ast_log(LOG_DEBUG, "Expression is '%s'\n", cp4);
01086          
01087          if (cp4) {
01088             length = strlen(cp4);
01089             if (length > count)
01090                length = count;
01091             memcpy(cp2, cp4, length);
01092             count -= length;
01093             cp2 += length;
01094             free(cp4);
01095          }
01096          
01097       } else
01098          break;
01099    }
01100 }


Generated on Fri Feb 27 12:19:52 2004 for Asterisk by doxygen 1.3.5