pbx.h File Reference

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

Include dependency graph for pbx.h:

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

Go to the source code of this file.

Data Structures

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

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.
struct 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
struct 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).
struct 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 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 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)
int ast_get_extension_matchcid (struct ast_exten *e)
char * ast_get_extension_cidmatch (struct ast_exten *e)
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)
struct ast_contextast_walk_contexts (struct ast_context *con)
struct ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority)
struct ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
struct ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
struct ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
struct 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.

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


Typedef Documentation

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

Definition at line 52 of file pbx.h.


Function Documentation

int ast_add_extension ( char *  context,
int  replace,
char *  extension,
int  priority,
char *  callerid,
char *  application,
void *  data,
void(*)(void *)  datad,
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 3667 of file pbx.c.

03669 {
03670    struct ast_context *c;
03671 
03672    if (ast_lock_contexts()) {
03673       errno = EBUSY;
03674       return -1;
03675    }
03676 
03677    c = ast_walk_contexts(NULL);
03678    while (c) {
03679       if (!strcmp(context, ast_get_context_name(c))) {
03680          int ret = ast_add_extension2(c, replace, extension, priority, callerid,
03681             application, data, datad, registrar);
03682          ast_unlock_contexts();
03683          return ret;
03684       }
03685       c = ast_walk_contexts(c);
03686    }
03687 
03688    ast_unlock_contexts();
03689    errno = ENOENT;
03690    return -1;
03691 }

int ast_add_extension2 ( struct ast_context con,
int  replace,
char *  extension,
int  priority,
char *  callerid,
char *  application,
void *  data,
void(*)(void *)  datad,
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 3800 of file pbx.c.

03804 {
03805 
03806 #define LOG do {  if (option_debug) {\
03807       if (tmp->matchcid) { \
03808          ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
03809       } else { \
03810          ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
03811       } \
03812    } else if (option_verbose > 2) { \
03813       if (tmp->matchcid) { \
03814          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
03815       } else {  \
03816          ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
03817       } \
03818    } } while(0)
03819 
03820    /*
03821     * This is a fairly complex routine.  Different extensions are kept
03822     * in order by the extension number.  Then, extensions of different
03823     * priorities (same extension) are kept in a list, according to the
03824     * peer pointer.
03825     */
03826    struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
03827    int res;
03828 
03829    /* Be optimistic:  Build the extension structure first */
03830    tmp = malloc(sizeof(struct ast_exten));
03831    if (tmp) {
03832       memset(tmp, 0, sizeof(struct ast_exten));
03833       ext_strncpy(tmp->exten, extension, sizeof(tmp->exten));
03834       tmp->priority = priority;
03835       if (callerid) {
03836          ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch));
03837          tmp->matchcid = 1;
03838       } else {
03839          tmp->cidmatch[0] = '\0';
03840          tmp->matchcid = 0;
03841       }
03842       strncpy(tmp->app, application, sizeof(tmp->app)-1);
03843       tmp->parent = con;
03844       tmp->data = data;
03845       tmp->datad = datad;
03846       tmp->registrar = registrar;
03847       tmp->peer = NULL;
03848       tmp->next =  NULL;
03849    } else {
03850       ast_log(LOG_ERROR, "Out of memory\n");
03851       errno = ENOMEM;
03852       return -1;
03853    }
03854    if (ast_mutex_lock(&con->lock)) {
03855       free(tmp);
03856       /* And properly destroy the data */
03857       datad(data);
03858       ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
03859       errno = EBUSY;
03860       return -1;
03861    }
03862    e = con->root;
03863    while(e) {
03864       /* Make sure patterns are always last! */
03865       if ((e->exten[0] != '_') && (extension[0] == '_'))
03866          res = -1;
03867       else if ((e->exten[0] == '_') && (extension[0] != '_'))
03868          res = 1;
03869       else
03870          res= strcmp(e->exten, extension);
03871       if (!res) {
03872          if (!e->matchcid && !tmp->matchcid)
03873             res = 0;
03874          else if (tmp->matchcid && !e->matchcid)
03875             res = 1;
03876          else if (e->matchcid && !tmp->matchcid)
03877             res = -1;
03878          else
03879             res = strcasecmp(e->cidmatch, tmp->cidmatch);
03880       }
03881       if (res == 0) {
03882          /* We have an exact match, now we find where we are
03883             and be sure there's no duplicates */
03884          while(e) {
03885             if (e->priority == tmp->priority) {
03886                /* Can't have something exactly the same.  Is this a
03887                   replacement?  If so, replace, otherwise, bonk. */
03888                if (replace) {
03889                   if (ep) {
03890                      /* We're in the peer list, insert ourselves */
03891                      ep->peer = tmp;
03892                      tmp->peer = e->peer;
03893                   } else if (el) {
03894                      /* We're the first extension. Take over e's functions */
03895                      el->next = tmp;
03896                      tmp->next = e->next;
03897                      tmp->peer = e->peer;
03898                   } else {
03899                      /* We're the very first extension.  */
03900                      con->root = tmp;
03901                      tmp->next = e->next;
03902                      tmp->peer = e->peer;
03903                   }
03904                   if (tmp->priority == PRIORITY_HINT)
03905                       ast_change_hint(e,tmp);
03906                   /* Destroy the old one */
03907                   e->datad(e->data);
03908                   free(e);
03909                   ast_mutex_unlock(&con->lock);
03910                   if (tmp->priority == PRIORITY_HINT)
03911                       ast_change_hint(e, tmp);
03912                   /* And immediately return success. */
03913                   LOG;
03914                   return 0;
03915                } else {
03916                   ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
03917                   tmp->datad(tmp->data);
03918                   free(tmp);
03919                   ast_mutex_unlock(&con->lock);
03920                   errno = EEXIST;
03921                   return -1;
03922                }
03923             } else if (e->priority > tmp->priority) {
03924                /* Slip ourselves in just before e */
03925                if (ep) {
03926                   /* Easy enough, we're just in the peer list */
03927                   ep->peer = tmp;
03928                   tmp->peer = e;
03929                } else if (el) {
03930                   /* We're the first extension in this peer list */
03931                   el->next = tmp;
03932                   tmp->next = e->next;
03933                   e->next = NULL;
03934                   tmp->peer = e;
03935                } else {
03936                   /* We're the very first extension altogether */
03937                   tmp->next = con->root->next;
03938                   /* Con->root must always exist or we couldn't get here */
03939                   tmp->peer = con->root;
03940                   con->root = tmp;
03941                }
03942                ast_mutex_unlock(&con->lock);
03943                /* And immediately return success. */
03944                if (tmp->priority == PRIORITY_HINT)
03945                    ast_add_hint(tmp);
03946                
03947                LOG;
03948                return 0;
03949             }
03950             ep = e;
03951             e = e->peer;
03952          }
03953          /* If we make it here, then it's time for us to go at the very end.
03954             ep *must* be defined or we couldn't have gotten here. */
03955          ep->peer = tmp;
03956          ast_mutex_unlock(&con->lock);
03957          if (tmp->priority == PRIORITY_HINT)
03958             ast_add_hint(tmp);
03959          
03960          /* And immediately return success. */
03961          LOG;
03962          return 0;
03963             
03964       } else if (res > 0) {
03965          /* Insert ourselves just before 'e'.  We're the first extension of
03966             this kind */
03967          tmp->next = e;
03968          if (el) {
03969             /* We're in the list somewhere */
03970             el->next = tmp;
03971          } else {
03972             /* We're at the top of the list */
03973             con->root = tmp;
03974          }
03975          ast_mutex_unlock(&con->lock);
03976          if (tmp->priority == PRIORITY_HINT)
03977             ast_add_hint(tmp);
03978 
03979          /* And immediately return success. */
03980          LOG;
03981          return 0;
03982       }        
03983          
03984       el = e;
03985       e = e->next;
03986    }
03987    /* If we fall all the way through to here, then we need to be on the end. */
03988    if (el)
03989       el->next = tmp;
03990    else
03991       con->root = tmp;
03992    ast_mutex_unlock(&con->lock);
03993    if (tmp->priority == PRIORITY_HINT)
03994       ast_add_hint(tmp);
03995    LOG;
03996    return 0;   
03997 }

int ast_async_goto ( struct ast_channel chan,
char *  context,
char *  exten,
int  priority 
)

Definition at line 3693 of file pbx.c.

03694 {
03695    int res = 0;
03696    ast_mutex_lock(&chan->lock);
03697 
03698    if (chan->pbx) {
03699       /* This channel is currently in the PBX */
03700       if (context && !ast_strlen_zero(context))
03701          strncpy(chan->context, context, sizeof(chan->context) - 1);
03702       if (exten && !ast_strlen_zero(exten))
03703          strncpy(chan->exten, exten, sizeof(chan->context) - 1);
03704       if (priority)
03705          chan->priority = priority - 1;
03706       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
03707    } else {
03708       /* In order to do it when the channel doesn't really exist within
03709          the PBX, we have to make a new channel, masquerade, and start the PBX
03710          at the new location */
03711       struct ast_channel *tmpchan;
03712       tmpchan = ast_channel_alloc(0);
03713       if (tmpchan) {
03714          snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
03715          ast_setstate(tmpchan, chan->_state);
03716          /* Make formats okay */
03717          tmpchan->readformat = chan->readformat;
03718          tmpchan->writeformat = chan->writeformat;
03719          /* Setup proper location */
03720          if (context && !ast_strlen_zero(context))
03721             strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1);
03722          else
03723             strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1);
03724          if (exten && !ast_strlen_zero(exten))
03725             strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1);
03726          else
03727             strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1);
03728          if (priority)
03729             tmpchan->priority = priority;
03730          else
03731             tmpchan->priority = chan->priority;
03732          
03733          /* Masquerade into temp channel */
03734          ast_channel_masquerade(tmpchan, chan);
03735       
03736          /* Grab the locks and get going */
03737          ast_mutex_lock(&tmpchan->lock);
03738          ast_do_masquerade(tmpchan);
03739          ast_mutex_unlock(&tmpchan->lock);
03740          /* Start the PBX going on our stolen channel */
03741          if (ast_pbx_start(tmpchan)) {
03742             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
03743             ast_hangup(tmpchan);
03744             res = -1;
03745          }
03746       } else {
03747          res = -1;
03748       }
03749    }
03750    ast_mutex_unlock(&chan->lock);
03751    return res;
03752 }

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

Definition at line 3754 of file pbx.c.

03755 {
03756    struct ast_channel *chan;
03757    int res = -1;
03758 
03759    chan = ast_channel_walk_locked(NULL);
03760    while(chan) {
03761       if (!strcasecmp(channame, chan->name))
03762          break;
03763       ast_mutex_unlock(&chan->lock);
03764       chan = ast_channel_walk_locked(chan);
03765    }
03766    
03767    if (chan) {
03768       res = ast_async_goto(chan, context, exten, priority);
03769       ast_mutex_unlock(&chan->lock);
03770    }
03771    return res;
03772 }

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 1761 of file pbx.c.

01762 {
01763    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH);
01764 }

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 3586 of file pbx.c.

03587 {
03588    struct ast_context *c;
03589 
03590    if (ast_lock_contexts()) {
03591       errno = EBUSY;
03592       return -1;
03593    }
03594 
03595    c = ast_walk_contexts(NULL);
03596    while (c) {
03597       if (!strcmp(ast_get_context_name(c), con)) {
03598          int ret = ast_context_add_ignorepat2(c, value, registrar);
03599          ast_unlock_contexts();
03600          return ret;
03601       } 
03602       c = ast_walk_contexts(c);
03603    }
03604 
03605    ast_unlock_contexts();
03606    errno = ENOENT;
03607    return -1;
03608 }

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

Definition at line 3610 of file pbx.c.

03611 {
03612    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
03613 
03614    ignorepat = malloc(sizeof(struct ast_ignorepat));
03615    if (!ignorepat) {
03616       ast_log(LOG_ERROR, "Out of memory\n");
03617       errno = ENOMEM;
03618       return -1;
03619    }
03620    memset(ignorepat, 0, sizeof(struct ast_ignorepat));
03621    strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
03622    ignorepat->next = NULL;
03623    ignorepat->registrar = registrar;
03624    ast_mutex_lock(&con->lock);
03625    ignorepatc = con->ignorepats;
03626    while(ignorepatc) {
03627       ignorepatl = ignorepatc;
03628       if (!strcasecmp(ignorepatc->pattern, value)) {
03629          /* Already there */
03630          ast_mutex_unlock(&con->lock);
03631          errno = EEXIST;
03632          return -1;
03633       }
03634       ignorepatc = ignorepatc->next;
03635    }
03636    if (ignorepatl) 
03637       ignorepatl->next = ignorepat;
03638    else
03639       con->ignorepats = ignorepat;
03640    ast_mutex_unlock(&con->lock);
03641    return 0;
03642    
03643 }

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 3047 of file pbx.c.

03048 {
03049    struct ast_context *c;
03050 
03051    if (ast_lock_contexts()) {
03052       errno = EBUSY;
03053       return -1;
03054    }
03055 
03056    /* walk contexts ... */
03057    c = ast_walk_contexts(NULL);
03058    while (c) {
03059       /* ... search for the right one ... */
03060       if (!strcmp(ast_get_context_name(c), context)) {
03061          int ret = ast_context_add_include2(c, include, registrar);
03062          /* ... unlock contexts list and return */
03063          ast_unlock_contexts();
03064          return ret;
03065       }
03066       c = ast_walk_contexts(c);
03067    }
03068 
03069    /* we can't find the right context */
03070    ast_unlock_contexts();
03071    errno = ENOENT;
03072    return -1;
03073 }

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 3367 of file pbx.c.

03369 {
03370    struct ast_include *new_include;
03371    char *c;
03372    struct ast_include *i, *il = NULL; /* include, include_last */
03373 
03374    /* allocate new include structure ... */
03375    if (!(new_include = malloc(sizeof(struct ast_include)))) {
03376       ast_log(LOG_ERROR, "Out of memory\n");
03377       errno = ENOMEM;
03378       return -1;
03379    }
03380    
03381    /* ... fill in this structure ... */
03382    memset(new_include, 0, sizeof(struct ast_include));
03383    strncpy(new_include->name, value, sizeof(new_include->name)-1);
03384    strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
03385    c = new_include->rname;
03386    /* Strip off timing info */
03387    while(*c && (*c != '|')) c++; 
03388    /* Process if it's there */
03389    if (*c) {
03390       build_timing(new_include, c+1);
03391       *c = '\0';
03392    }
03393    new_include->next      = NULL;
03394    new_include->registrar = registrar;
03395 
03396    /* ... try to lock this context ... */
03397    if (ast_mutex_lock(&con->lock)) {
03398       free(new_include);
03399       errno = EBUSY;
03400       return -1;
03401    }
03402 
03403    /* ... go to last include and check if context is already included too... */
03404    i = con->includes;
03405    while (i) {
03406       if (!strcasecmp(i->name, new_include->name)) {
03407          free(new_include);
03408          ast_mutex_unlock(&con->lock);
03409          errno = EEXIST;
03410          return -1;
03411       }
03412       il = i;
03413       i = i->next;
03414    }
03415 
03416    /* ... include new context into context list, unlock, return */
03417    if (il)
03418       il->next = new_include;
03419    else
03420       con->includes = new_include;
03421    if (option_verbose > 2)
03422       ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 
03423    ast_mutex_unlock(&con->lock);
03424 
03425    return 0;
03426 }

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 3433 of file pbx.c.

03434 {
03435    struct ast_context *c;
03436 
03437    if (ast_lock_contexts()) {
03438       errno = EBUSY;
03439       return -1;
03440    }
03441 
03442    /* walk contexts ... */
03443    c = ast_walk_contexts(NULL);
03444    while (c) {
03445       /* ... search for the right one ... */
03446       if (!strcmp(ast_get_context_name(c), context)) {
03447          int ret = ast_context_add_switch2(c, sw, data, registrar);
03448          /* ... unlock contexts list and return */
03449          ast_unlock_contexts();
03450          return ret;
03451       }
03452       c = ast_walk_contexts(c);
03453    }
03454 
03455    /* we can't find the right context */
03456    ast_unlock_contexts();
03457    errno = ENOENT;
03458    return -1;
03459 }

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 3468 of file pbx.c.

03470 {
03471    struct ast_sw *new_sw;
03472    struct ast_sw *i, *il = NULL; /* sw, sw_last */
03473 
03474    /* allocate new sw structure ... */
03475    if (!(new_sw = malloc(sizeof(struct ast_sw)))) {
03476       ast_log(LOG_ERROR, "Out of memory\n");
03477       errno = ENOMEM;
03478       return -1;
03479    }
03480    
03481    /* ... fill in this structure ... */
03482    memset(new_sw, 0, sizeof(struct ast_sw));
03483    strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
03484    if (data)
03485       strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
03486    else
03487       strncpy(new_sw->data, "", sizeof(new_sw->data)-1);
03488    new_sw->next      = NULL;
03489    new_sw->registrar = registrar;
03490 
03491    /* ... try to lock this context ... */
03492    if (ast_mutex_lock(&con->lock)) {
03493       free(new_sw);
03494       errno = EBUSY;
03495       return -1;
03496    }
03497 
03498    /* ... go to last sw and check if context is already swd too... */
03499    i = con->alts;
03500    while (i) {
03501       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
03502          free(new_sw);
03503          ast_mutex_unlock(&con->lock);
03504          errno = EEXIST;
03505          return -1;
03506       }
03507       il = i;
03508       i = i->next;
03509    }
03510 
03511    /* ... sw new context into context list, unlock, return */
03512    if (il)
03513       il->next = new_sw;
03514    else
03515       con->alts = new_sw;
03516    if (option_verbose > 2)
03517       ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 
03518    ast_mutex_unlock(&con->lock);
03519 
03520    return 0;
03521 }

struct ast_context* ast_context_create ( struct ast_context **  extcontexts,
char *  name,
char *  registrar 
) [read]

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 2970 of file pbx.c.

02971 {
02972    struct ast_context *tmp, **local_contexts;
02973    if (!extcontexts) {
02974       local_contexts = &contexts;
02975       ast_mutex_lock(&conlock);
02976    } else
02977       local_contexts = extcontexts;
02978 
02979    tmp = *local_contexts;
02980    while(tmp) {
02981       if (!strcasecmp(tmp->name, name)) {
02982          ast_mutex_unlock(&conlock);
02983          ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
02984          if (!extcontexts)
02985             ast_mutex_unlock(&conlock);
02986          return NULL;
02987       }
02988       tmp = tmp->next;
02989    }
02990    tmp = malloc(sizeof(struct ast_context));
02991    if (tmp) {
02992       memset(tmp, 0, sizeof(struct ast_context));
02993       ast_mutex_init(&tmp->lock);
02994       strncpy(tmp->name, name, sizeof(tmp->name)-1);
02995       tmp->root = NULL;
02996       tmp->registrar = registrar;
02997       tmp->next = *local_contexts;
02998       tmp->includes = NULL;
02999       tmp->ignorepats = NULL;
03000       *local_contexts = tmp;
03001       if (option_debug)
03002          ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
03003       else if (option_verbose > 2)
03004          ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
03005    } else
03006       ast_log(LOG_ERROR, "Out of memory\n");
03007    
03008    if (!extcontexts)
03009       ast_mutex_unlock(&conlock);
03010    return tmp;
03011 }

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 4356 of file pbx.c.

04357 {
04358    __ast_context_destroy(con,registrar);
04359 }

struct ast_context* ast_context_find ( char *  name  )  [read]

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 678 of file pbx.c.

00679 {
00680    struct ast_context *tmp;
00681    ast_mutex_lock(&conlock);
00682    if (name) {
00683       tmp = contexts;
00684       while(tmp) {
00685          if (!strcasecmp(name, tmp->name))
00686             break;
00687          tmp = tmp->next;
00688       }
00689    } else
00690       tmp = contexts;
00691    ast_mutex_unlock(&conlock);
00692    return tmp;
00693 }

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 2169 of file pbx.c.

02170 {
02171    struct ast_context *c;
02172 
02173    if (ast_lock_contexts()) return -1;
02174 
02175    /* walk contexts ... */
02176    c = ast_walk_contexts(NULL);
02177    while (c) {
02178       /* ... search for the right one ... */
02179       if (!strcmp(ast_get_context_name(c), context)) {
02180          /* ... remove extension ... */
02181          int ret = ast_context_remove_extension2(c, extension, priority,
02182             registrar);
02183          /* ... unlock contexts list and return */
02184          ast_unlock_contexts();
02185          return ret;
02186       }
02187       c = ast_walk_contexts(c);
02188    }
02189 
02190    /* we can't find the right context */
02191    ast_unlock_contexts();
02192    return -1;
02193 }

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

Definition at line 2205 of file pbx.c.

02206 {
02207    struct ast_exten *exten, *prev_exten = NULL;
02208 
02209    if (ast_mutex_lock(&con->lock)) return -1;
02210 
02211    /* go through all extensions in context and search the right one ... */
02212    exten = con->root;
02213    while (exten) {
02214 
02215       /* look for right extension */
02216       if (!strcmp(exten->exten, extension) &&
02217          (!registrar || !strcmp(exten->registrar, registrar))) {
02218          struct ast_exten *peer;
02219 
02220          /* should we free all peers in this extension? (priority == 0)? */
02221          if (priority == 0) {
02222             /* remove this extension from context list */
02223             if (prev_exten)
02224                prev_exten->next = exten->next;
02225             else
02226                con->root = exten->next;
02227 
02228             /* fire out all peers */
02229             peer = exten; 
02230             while (peer) {
02231                exten = peer->peer;
02232                
02233                if (!peer->priority==PRIORITY_HINT) 
02234                    ast_remove_hint(peer);
02235 
02236                peer->datad(peer->data);
02237                free(peer);
02238 
02239                peer = exten;
02240             }
02241 
02242             ast_mutex_unlock(&con->lock);
02243             return 0;
02244          } else {
02245             /* remove only extension with exten->priority == priority */
02246             struct ast_exten *previous_peer = NULL;
02247 
02248             peer = exten;
02249             while (peer) {
02250                /* is this our extension? */
02251                if (peer->priority == priority &&
02252                   (!registrar || !strcmp(peer->registrar, registrar) )) {
02253                   /* we are first priority extension? */
02254                   if (!previous_peer) {
02255                      /* exists previous extension here? */
02256                      if (prev_exten) {
02257                         /* yes, so we must change next pointer in
02258                          * previous connection to next peer
02259                          */
02260                         if (peer->peer) {
02261                            prev_exten->next = peer->peer;
02262                            peer->peer->next = exten->next;
02263                         } else
02264                            prev_exten->next = exten->next;
02265                      } else {
02266                         /* no previous extension, we are first
02267                          * extension, so change con->root ...
02268                          */
02269                         if (peer->peer)
02270                            con->root = peer->peer;
02271                         else
02272                            con->root = exten->next; 
02273                      }
02274                   } else {
02275                      /* we are not first priority in extension */
02276                      previous_peer->peer = peer->peer;
02277                   }
02278 
02279                   /* now, free whole priority extension */
02280                   if (peer->priority==PRIORITY_HINT)
02281                       ast_remove_hint(peer);
02282                   peer->datad(peer->data);
02283                   free(peer);
02284 
02285                   ast_mutex_unlock(&con->lock);
02286                   return 0;
02287                } else {
02288                   /* this is not right extension, skip to next peer */
02289                   previous_peer = peer;
02290                   peer = peer->peer;
02291                }
02292             }
02293 
02294             ast_mutex_unlock(&con->lock);
02295             return -1;
02296          }
02297       }
02298 
02299       prev_exten = exten;
02300       exten = exten->next;
02301    }
02302 
02303    /* we can't find right extension */
02304    ast_mutex_unlock(&con->lock);
02305    return -1;
02306 }

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 3527 of file pbx.c.

03528 {
03529    struct ast_context *c;
03530 
03531    if (ast_lock_contexts()) {
03532       errno = EBUSY;
03533       return -1;
03534    }
03535 
03536    c = ast_walk_contexts(NULL);
03537    while (c) {
03538       if (!strcmp(ast_get_context_name(c), context)) {
03539          int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
03540          ast_unlock_contexts();
03541          return ret;
03542       }
03543       c = ast_walk_contexts(c);
03544    }
03545 
03546    ast_unlock_contexts();
03547    errno = ENOENT;
03548    return -1;
03549 }

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

Definition at line 3551 of file pbx.c.

03552 {
03553    struct ast_ignorepat *ip, *ipl = NULL;
03554 
03555    if (ast_mutex_lock(&con->lock)) {
03556       errno = EBUSY;
03557       return -1;
03558    }
03559 
03560    ip = con->ignorepats;
03561    while (ip) {
03562       if (!strcmp(ip->pattern, ignorepat) &&
03563          (!registrar || (registrar == ip->registrar))) {
03564          if (ipl) {
03565             ipl->next = ip->next;
03566             free(ip);
03567          } else {
03568             con->ignorepats = ip->next;
03569             free(ip);
03570          }
03571          ast_mutex_unlock(&con->lock);
03572          return 0;
03573       }
03574       ipl = ip; ip = ip->next;
03575    }
03576 
03577    ast_mutex_unlock(&con->lock);
03578    errno = EINVAL;
03579    return -1;
03580 }

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

Removes an include.

See add_include

Definition at line 2025 of file pbx.c.

02026 {
02027    struct ast_context *c;
02028 
02029    if (ast_lock_contexts()) return -1;
02030 
02031    /* walk contexts and search for the right one ...*/
02032    c = ast_walk_contexts(NULL);
02033    while (c) {
02034       /* we found one ... */
02035       if (!strcmp(ast_get_context_name(c), context)) {
02036          int ret;
02037          /* remove include from this context ... */   
02038          ret = ast_context_remove_include2(c, include, registrar);
02039 
02040          ast_unlock_contexts();
02041 
02042          /* ... return results */
02043          return ret;
02044       }
02045       c = ast_walk_contexts(c);
02046    }
02047 
02048    /* we can't find the right one context */
02049    ast_unlock_contexts();
02050    return -1;
02051 }

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 2061 of file pbx.c.

02062 {
02063    struct ast_include *i, *pi = NULL;
02064 
02065    if (ast_mutex_lock(&con->lock)) return -1;
02066 
02067    /* walk includes */
02068    i = con->includes;
02069    while (i) {
02070       /* find our include */
02071       if (!strcmp(i->name, include) && 
02072          (!registrar || !strcmp(i->registrar, registrar))) {
02073          /* remove from list */
02074          if (pi)
02075             pi->next = i->next;
02076          else
02077             con->includes = i->next;
02078          /* free include and return */
02079          free(i);
02080          ast_mutex_unlock(&con->lock);
02081          return 0;
02082       }
02083       pi = i;
02084       i = i->next;
02085    }
02086 
02087    /* we can't find the right include */
02088    ast_mutex_unlock(&con->lock);
02089    return -1;
02090 }

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 2097 of file pbx.c.

02098 {
02099    struct ast_context *c;
02100 
02101    if (ast_lock_contexts()) return -1;
02102 
02103    /* walk contexts and search for the right one ...*/
02104    c = ast_walk_contexts(NULL);
02105    while (c) {
02106       /* we found one ... */
02107       if (!strcmp(ast_get_context_name(c), context)) {
02108          int ret;
02109          /* remove switch from this context ... */ 
02110          ret = ast_context_remove_switch2(c, sw, data, registrar);
02111 
02112          ast_unlock_contexts();
02113 
02114          /* ... return results */
02115          return ret;
02116       }
02117       c = ast_walk_contexts(c);
02118    }
02119 
02120    /* we can't find the right one context */
02121    ast_unlock_contexts();
02122    return -1;
02123 }

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

Definition at line 2133 of file pbx.c.

02134 {
02135    struct ast_sw *i, *pi = NULL;
02136 
02137    if (ast_mutex_lock(&con->lock)) return -1;
02138 
02139    /* walk switchs */
02140    i = con->alts;
02141    while (i) {
02142       /* find our switch */
02143       if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 
02144          (!registrar || !strcmp(i->registrar, registrar))) {
02145          /* remove from list */
02146          if (pi)
02147             pi->next = i->next;
02148          else
02149             con->alts = i->next;
02150          /* free switch and return */
02151          free(i);
02152          ast_mutex_unlock(&con->lock);
02153          return 0;
02154       }
02155       pi = i;
02156       i = i->next;
02157    }
02158 
02159    /* we can't find the right switch */
02160    ast_mutex_unlock(&con->lock);
02161    return -1;
02162 }

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 5083 of file pbx.c.

05084 {
05085    struct ast_include *inc;
05086    int res = 0;
05087 
05088    for (inc = ast_walk_context_includes(con, NULL); inc; inc = ast_walk_context_includes(con, inc))
05089       if (!ast_context_find(inc->rname)) {
05090          res = -1;
05091          ast_log(LOG_WARNING, "Context '%s' tries includes nonexistent context '%s'\n",
05092                ast_get_context_name(con), inc->rname);
05093       }
05094    return res;
05095 }

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

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 1756 of file pbx.c.

01757 {
01758    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
01759 }

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 645 of file pbx.c.

00646 {
00647    int match;
00648    /* If they're the same return */
00649    if (!strcmp(pattern, data))
00650       return 1;
00651    EXTENSION_MATCH_CORE(data,pattern,match);
00652    /* Must be at the end of both */
00653    if (*data || (*pattern && (*pattern != '/')))
00654       match = 0;
00655    return match;
00656 }

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 1429 of file pbx.c.

01430 {
01431    struct ast_exten *e;
01432 
01433    e = ast_hint_extension(c, context, exten);    
01434    if (!e) 
01435       return -1;
01436 
01437    return ast_extension_state2(e);    
01438 }

int 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 1505 of file pbx.c.

01507 {
01508    struct ast_hint *list;
01509    struct ast_state_cb *cblist;
01510    struct ast_exten *e;
01511 
01512    /* No context and extension add callback to statecbs list */
01513    if (!context && !exten) {
01514       ast_mutex_lock(&hintlock);
01515 
01516       cblist = statecbs;
01517       while (cblist) {
01518          if (cblist->callback == callback) {
01519             cblist->data = data;
01520             ast_mutex_unlock(&hintlock);
01521             return 0;
01522          }
01523          cblist = cblist->next;
01524       }
01525    
01526       /* Now insert the callback */
01527       cblist = malloc(sizeof(struct ast_state_cb));
01528       if (!cblist) {
01529          ast_mutex_unlock(&hintlock);
01530          return -1;
01531       }
01532       memset(cblist, 0, sizeof(struct ast_state_cb));
01533       cblist->id = 0;
01534       cblist->callback = callback;
01535       cblist->data = data;
01536    
01537             cblist->next = statecbs;
01538       statecbs = cblist;
01539 
01540       ast_mutex_unlock(&hintlock);
01541       return 0;
01542       }
01543 
01544    if (!context || !exten)
01545       return -1;
01546 
01547    /* This callback type is for only one hint */
01548    e = ast_hint_extension(NULL, context, exten);    
01549    if (!e) {
01550       return -1;
01551    }
01552     
01553    ast_mutex_lock(&hintlock);
01554    list = hints;        
01555     
01556    while (list) {
01557       if (list->exten == e)
01558          break;       
01559       list = list->next;    
01560    }
01561 
01562    if (!list) {
01563       ast_mutex_unlock(&hintlock);
01564       return -1;
01565    }
01566 
01567    /* Now inserts the callback */
01568    cblist = malloc(sizeof(struct ast_state_cb));
01569    if (!cblist) {
01570       ast_mutex_unlock(&hintlock);
01571       return -1;
01572    }
01573    memset(cblist, 0, sizeof(struct ast_state_cb));
01574    cblist->id = stateid++;
01575    cblist->callback = callback;
01576    cblist->data = data;
01577 
01578    cblist->next = list->callbacks;
01579    list->callbacks = cblist;
01580 
01581    ast_mutex_unlock(&hintlock);
01582    return cblist->id;
01583 }

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 1585 of file pbx.c.

01586 {
01587    struct ast_hint *list;
01588    struct ast_state_cb *cblist, *cbprev;
01589     
01590    if (!id && !callback)
01591       return -1;
01592             
01593    ast_mutex_lock(&hintlock);
01594 
01595    /* id is zero is a callback without extension */
01596    if (!id) {
01597       cbprev = NULL;
01598       cblist = statecbs;
01599       while (cblist) {
01600          if (cblist->callback == callback) {
01601             if (!cbprev)
01602                   statecbs = cblist->next;
01603             else
01604                   cbprev->next = cblist->next;
01605 
01606             free(cblist);
01607 
01608                ast_mutex_unlock(&hintlock);
01609             return 0;
01610             }
01611             cbprev = cblist;
01612             cblist = cblist->next;
01613       }
01614 
01615          ast_mutex_lock(&hintlock);
01616       return -1;
01617    }
01618 
01619    /* id greater than zero is a callback with extension */
01620    list = hints;
01621    while (list) {
01622       cblist = list->callbacks;
01623       cbprev = NULL;
01624       while (cblist) {
01625             if (cblist->id==id) {
01626             if (!cbprev)
01627                   list->callbacks = cblist->next;     
01628             else
01629                   cbprev->next = cblist->next;
01630       
01631             free(cblist);
01632       
01633             ast_mutex_unlock(&hintlock);
01634             return 0;      
01635             }     
01636                cbprev = cblist;           
01637             cblist = cblist->next;
01638       }
01639       list = list->next;
01640    }
01641     
01642    ast_mutex_unlock(&hintlock);
01643    return -1;
01644 }

char* ast_get_context_name ( struct ast_context con  ) 

Definition at line 4944 of file pbx.c.

04945 {
04946    return con ? con->name : NULL;
04947 }

char* ast_get_context_registrar ( struct ast_context c  ) 

Definition at line 4972 of file pbx.c.

04973 {
04974    return c ? c->registrar : NULL;
04975 }

char* ast_get_extension_app ( struct ast_exten e  ) 

Definition at line 5002 of file pbx.c.

05003 {
05004    return e ? e->app : NULL;
05005 }

void* ast_get_extension_app_data ( struct ast_exten e  ) 

Definition at line 5007 of file pbx.c.

05008 {
05009    return e ? e->data : NULL;
05010 }

char* ast_get_extension_cidmatch ( struct ast_exten e  ) 

Definition at line 4997 of file pbx.c.

04998 {
04999    return e ? e->cidmatch : NULL;
05000 }

int ast_get_extension_matchcid ( struct ast_exten e  ) 

Definition at line 4992 of file pbx.c.

04993 {
04994    return e ? e->matchcid : 0;
04995 }

char* ast_get_extension_name ( struct ast_exten exten  ) 

Definition at line 4949 of file pbx.c.

04950 {
04951    return exten ? exten->exten : NULL;
04952 }

int ast_get_extension_priority ( struct ast_exten exten  ) 

Definition at line 4964 of file pbx.c.

04965 {
04966    return exten ? exten->priority : -1;
04967 }

char* ast_get_extension_registrar ( struct ast_exten e  ) 

Definition at line 4977 of file pbx.c.

04978 {
04979    return e ? e->registrar : NULL;
04980 }

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 1745 of file pbx.c.

01746 {
01747    struct ast_exten *e;
01748    e = ast_hint_extension(c, context, exten);
01749    if (e) { 
01750        strncpy(hint, ast_get_extension_app(e), hintsize - 1);
01751        return -1;
01752    }
01753    return 0;   
01754 }

char* ast_get_ignorepat_name ( struct ast_ignorepat ip  ) 

Definition at line 4959 of file pbx.c.

04960 {
04961    return ip ? ip->pattern : NULL;
04962 }

char* ast_get_ignorepat_registrar ( struct ast_ignorepat ip  ) 

Definition at line 4987 of file pbx.c.

04988 {
04989    return ip ? ip->registrar : NULL;
04990 }

char* ast_get_include_name ( struct ast_include include  ) 

Definition at line 4954 of file pbx.c.

04955 {
04956    return inc ? inc->name : NULL;
04957 }

char* ast_get_include_registrar ( struct ast_include i  ) 

Definition at line 4982 of file pbx.c.

04983 {
04984    return i ? i->registrar : NULL;
04985 }

char* ast_get_switch_data ( struct ast_sw sw  ) 

Definition at line 5017 of file pbx.c.

05018 {
05019    return sw ? sw->data : NULL;
05020 }

char* ast_get_switch_name ( struct ast_sw sw  ) 

Definition at line 5012 of file pbx.c.

05013 {
05014    return sw ? sw->name : NULL;
05015 }

char* ast_get_switch_registrar ( struct ast_sw sw  ) 

Definition at line 5022 of file pbx.c.

05023 {
05024    return sw ? sw->registrar : NULL;
05025 }

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 3645 of file pbx.c.

03646 {
03647    struct ast_context *con;
03648    struct ast_ignorepat *pat;
03649 
03650    con = ast_context_find(context);
03651    if (con) {
03652       pat = con->ignorepats;
03653       while (pat) {
03654          if (ast_extension_match(pat->pattern, pattern))
03655             return 1;
03656          pat = pat->next;
03657       }
03658    } 
03659    return 0;
03660 }

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 4931 of file pbx.c.

04932 {
04933    return ast_mutex_lock(&con->lock);
04934 }

int ast_lock_contexts ( void   ) 

Locks the contexts.

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

Definition at line 4918 of file pbx.c.

04919 {
04920    return ast_mutex_lock(&conlock);
04921 }

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 1766 of file pbx.c.

01767 {
01768    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE);
01769 }

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 3015 of file pbx.c.

03015                                                                                       {
03016    struct ast_context *tmp, *lasttmp = NULL;
03017    tmp = *extcontexts;
03018    ast_mutex_lock(&conlock);
03019    if (registrar) {
03020       __ast_context_destroy(NULL,registrar);
03021       while (tmp) {
03022          lasttmp = tmp;
03023          tmp = tmp->next;
03024       }
03025    } else {
03026       while (tmp) {
03027          __ast_context_destroy(tmp,tmp->registrar);
03028          lasttmp = tmp;
03029          tmp = tmp->next;
03030       }
03031    }
03032    if (lasttmp) {
03033       lasttmp->next = contexts;
03034       contexts = *extcontexts;
03035       *extcontexts = NULL;
03036    } else 
03037       ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
03038    ast_mutex_unlock(&conlock);
03039    return;  
03040 }

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 4185 of file pbx.c.

04186 {
04187    struct ast_channel *chan;
04188    struct async_stat *as;
04189    struct app_tmp *tmp;
04190    char *var, *vartmp;
04191    int res = -1;
04192    pthread_attr_t attr;
04193    
04194    if (!app || ast_strlen_zero(app))
04195       return -1;
04196    if (sync) {
04197       chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
04198       if (chan) {
04199          pbx_builtin_setaccount(chan, account);
04200          if (variable) {
04201             vartmp = ast_strdupa(variable);
04202             for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp)) {
04203                pbx_builtin_setvar( chan, var );
04204             }
04205          }
04206          if (chan->_state == AST_STATE_UP) {
04207             res = 0;
04208             if (option_verbose > 3)
04209                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
04210             tmp = malloc(sizeof(struct app_tmp));
04211             if (tmp) {
04212                memset(tmp, 0, sizeof(struct app_tmp));
04213                strncpy(tmp->app, app, sizeof(tmp->app) - 1);
04214                strncpy(tmp->data, appdata, sizeof(tmp->data) - 1);
04215                tmp->chan = chan;
04216                if (sync > 1) {
04217                   ast_pbx_run_app(tmp);
04218                } else {
04219                   pthread_attr_init(&attr);
04220                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04221                   if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
04222                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
04223                      free(tmp);
04224                      ast_hangup(chan);
04225                      res = -1;
04226                   }
04227                }
04228             } else {
04229                ast_log(LOG_ERROR, "Out of memory :(\n");
04230                res = -1;
04231             }
04232          } else {
04233             if (option_verbose > 3)
04234                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
04235             ast_hangup(chan);
04236          }
04237       }
04238    } else {
04239       as = malloc(sizeof(struct async_stat));
04240       if (!as)
04241          return -1;
04242       memset(as, 0, sizeof(struct async_stat));
04243       chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
04244       if (!chan) {
04245          free(as);
04246          return -1;
04247       }
04248       pbx_builtin_setaccount(chan, account);
04249       as->chan = chan;
04250       strncpy(as->app, app, sizeof(as->app) - 1);
04251       if (appdata)
04252          strncpy(as->appdata,  appdata, sizeof(as->appdata) - 1);
04253       as->timeout = timeout;
04254       if (variable) {
04255          vartmp = ast_strdupa(variable);
04256          for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp))
04257             pbx_builtin_setvar( chan, var );
04258       }
04259       /* Start a new thread, and get something handling this channel. */
04260       pthread_attr_init(&attr);
04261       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04262       if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
04263          ast_log(LOG_WARNING, "Failed to start async wait\n");
04264          free(as);
04265          ast_hangup(chan);
04266          return -1;
04267       }
04268       res = 0;
04269    }
04270    return res;
04271 }

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 4067 of file pbx.c.

04068 {
04069    struct ast_channel *chan;
04070    struct async_stat *as;
04071    int res = -1;
04072    char *var, *tmp;
04073    struct outgoing_helper oh;
04074    pthread_attr_t attr;
04075       
04076    if (sync) {
04077       LOAD_OH(oh);
04078       chan = __ast_request_and_dial(type, format, data, timeout, reason, callerid, &oh);
04079       if (chan) {
04080          pbx_builtin_setaccount(chan, account);
04081          if (chan->_state == AST_STATE_UP) {
04082                res = 0;
04083             if (option_verbose > 3)
04084                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
04085 
04086             if (sync > 1) {
04087                if (ast_pbx_run(chan)) {
04088                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
04089                   ast_hangup(chan);
04090                   res = -1;
04091                }
04092             } else {
04093                if (ast_pbx_start(chan)) {
04094                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
04095                   ast_hangup(chan);
04096                   res = -1;
04097                } 
04098             }
04099          } else {
04100             if (option_verbose > 3)
04101                ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
04102             ast_hangup(chan);
04103          }
04104       }
04105 
04106       if(res < 0) { /* the call failed for some reason */
04107          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
04108          /* check if "failed" exists */
04109          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
04110             chan = ast_channel_alloc(0);
04111             if (chan) {
04112                strncpy(chan->name, "OutgoingSpoolFailed", sizeof(chan->name) - 1);
04113                if (context && !ast_strlen_zero(context))
04114                   strncpy(chan->context, context, sizeof(chan->context) - 1);
04115                strncpy(chan->exten, "failed", sizeof(chan->exten) - 1);
04116                chan->priority = 1;
04117                if (variable) {
04118                   tmp = ast_strdupa(variable);
04119                   for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp)) {
04120                      pbx_builtin_setvar( chan, var );
04121                   }
04122                }
04123                ast_pbx_run(chan);   
04124             } else
04125                ast_log(LOG_WARNING, "Can't allocate the channel structure, skipping execution of extension 'failed'\n");
04126          }
04127       }
04128    } else {
04129       as = malloc(sizeof(struct async_stat));
04130       if (!as)
04131          return -1;
04132       memset(as, 0, sizeof(struct async_stat));
04133       chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
04134       if (!chan) {
04135          free(as);
04136          return -1;
04137       }
04138       pbx_builtin_setaccount(chan, account);
04139       as->chan = chan;
04140       strncpy(as->context, context, sizeof(as->context) - 1);
04141       strncpy(as->exten,  exten, sizeof(as->exten) - 1);
04142       as->priority = priority;
04143       as->timeout = timeout;
04144       if (variable) {
04145          tmp = ast_strdupa(variable);
04146          for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp))
04147             pbx_builtin_setvar( chan, var );
04148       }
04149       pthread_attr_init(&attr);
04150       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04151       if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
04152          ast_log(LOG_WARNING, "Failed to start async wait\n");
04153          free(as);
04154          ast_hangup(chan);
04155          return -1;
04156       }
04157       res = 0;
04158    }
04159    return res;
04160 }

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 1776 of file pbx.c.

01777 {
01778    int firstpass = 1;
01779    int digit;
01780    char exten[256];
01781    int pos;
01782    int waittime;
01783    int res=0;
01784 
01785    /* A little initial setup here */
01786    if (c->pbx)
01787       ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
01788    c->pbx = malloc(sizeof(struct ast_pbx));
01789    if (!c->pbx) {
01790       ast_log(LOG_ERROR, "Out of memory\n");
01791       return -1;
01792    }
01793    if (c->amaflags) {
01794       if (c->cdr) {
01795          ast_log(LOG_WARNING, "%s already has a call record??\n", c->name);
01796       } else {
01797          c->cdr = ast_cdr_alloc();
01798          if (!c->cdr) {
01799             ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
01800             free(c->pbx);
01801             return -1;
01802          }
01803          ast_cdr_init(c->cdr, c);
01804       }
01805    }
01806    memset(c->pbx, 0, sizeof(struct ast_pbx));
01807    /* Set reasonable defaults */
01808    c->pbx->rtimeout = 10;
01809    c->pbx->dtimeout = 5;
01810 
01811    /* Start by trying whatever the channel is set to */
01812    if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01813       /* JK02: If not successfull fall back to 's' */
01814       if (option_verbose > 1)
01815          ast_verbose( VERBOSE_PREFIX_2 "Starting %s at %s,%s,%d failed so falling back to exten 's'\n", c->name, c->context, c->exten, c->priority);
01816       strncpy(c->exten, "s", sizeof(c->exten)-1);
01817       if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01818          /* JK02: And finally back to default if everything else failed */
01819          if (option_verbose > 1)
01820             ast_verbose( VERBOSE_PREFIX_2 "Starting %s at %s,%s,%d still failed so falling back to context 'default'\n", c->name, c->context, c->exten, c->priority);
01821          strncpy(c->context, "default", sizeof(c->context)-1);
01822       }
01823       c->priority = 1;
01824    }
01825    if (c->cdr)
01826       ast_cdr_start(c->cdr);
01827    for(;;) {
01828       pos = 0;
01829       digit = 0;
01830       while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01831          memset(exten, 0, sizeof(exten));
01832          if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
01833             /* Something bad happened, or a hangup has been requested. */
01834             if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
01835                (res == '*') || (res == '#')) {
01836                ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
01837                memset(exten, 0, sizeof(exten));
01838                pos = 0;
01839                exten[pos++] = digit = res;
01840                break;
01841             }
01842             switch(res) {
01843             case AST_PBX_KEEPALIVE:
01844                if (option_debug)
01845                   ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
01846                else if (option_verbose > 1)
01847                   ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
01848                goto out;
01849                break;
01850             default:
01851                if (option_debug)
01852                   ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01853                else if (option_verbose > 1)
01854                   ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01855                if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
01856                   c->_softhangup =0;
01857                   break;
01858                }
01859                /* atimeout */
01860                if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
01861                   break;
01862                }
01863 
01864                if (c->cdr) {
01865                   ast_cdr_update(c);
01866                }
01867                goto out;
01868             }
01869          }
01870          if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->callerid))) {
01871             strncpy(c->exten,"T",sizeof(c->exten) - 1);
01872             /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
01873             c->whentohangup = 0;
01874             c->priority = 0;
01875             c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
01876          } else if (c->_softhangup) {
01877             ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
01878                c->exten, c->priority);
01879             goto out;
01880          }
01881          firstpass = 0;
01882          c->priority++;
01883       }
01884       if (!ast_exists_extension(c, c->context, c->exten, 1, c->callerid)) {
01885          /* It's not a valid extension anymore */
01886          if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
01887             if (option_verbose > 2)
01888                ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
01889             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
01890             strncpy(c->exten, "i", sizeof(c->exten)-1);
01891             c->priority = 1;
01892          } else {
01893             ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
01894                c->name, c->exten, c->context);
01895             goto out;
01896          }
01897       } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
01898          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
01899          c->_softhangup = 0;
01900       } else {
01901          /* Done, wait for an extension */
01902          if (digit)
01903             waittime = c->pbx->dtimeout;
01904          else
01905             waittime = c->pbx->rtimeout;
01906          while (ast_matchmore_extension(c, c->context, exten, 1, c->callerid)) {
01907             /* As long as we're willing to wait, and as long as it's not defined, 
01908                keep reading digits until we can't possibly get a right answer anymore.  */
01909             digit = ast_waitfordigit(c, waittime * 1000);
01910             if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
01911                c->_softhangup = 0;
01912             } else {
01913                if (!digit)
01914                   /* No entry */
01915                   break;
01916                if (digit < 0)
01917                   /* Error, maybe a  hangup */
01918                   goto out;
01919                exten[pos++] = digit;
01920                waittime = c->pbx->dtimeout;
01921             }
01922          }
01923          if (ast_exists_extension(c, c->context, exten, 1, c->callerid)) {
01924             /* Prepare the next cycle */
01925             strncpy(c->exten, exten, sizeof(c->exten)-1);
01926             c->priority = 1;
01927          } else {
01928             /* No such extension */
01929             if (!ast_strlen_zero(exten)) {
01930                /* An invalid extension */
01931                if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
01932                   if (option_verbose > 2)
01933                      ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
01934                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
01935                   strncpy(c->exten, "i", sizeof(c->exten)-1);
01936                   c->priority = 1;
01937                } else {
01938                   ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", exten, c->context);
01939                   goto out;
01940                }
01941             } else {
01942                /* A simple timeout */
01943                if (ast_exists_extension(c, c->context, "t", 1, c->callerid)) {
01944                   if (option_verbose > 2)
01945                      ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
01946                   strncpy(c->exten, "t", sizeof(c->exten)-1);
01947                   c->priority = 1;
01948                } else {
01949                   ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
01950                   goto out;
01951                }
01952             }  
01953          }
01954          if (c->cdr) {
01955             if (option_verbose > 2)
01956                ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);   
01957             ast_cdr_update(c);
01958           }
01959       }
01960    }
01961    if (firstpass) 
01962       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
01963 out:
01964    if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->callerid)) {
01965       c->exten[0] = 'h';
01966       c->exten[1] = '\0';
01967       c->priority = 1;
01968       while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01969          if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
01970             /* Something bad happened, or a hangup has been requested. */
01971             if (option_debug)
01972                ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01973             else if (option_verbose > 1)
01974                ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01975             break;
01976          }
01977          c->priority++;
01978       }
01979    }
01980 
01981    pbx_destroy(c->pbx);
01982    c->pbx = NULL;
01983    if (res != AST_PBX_KEEPALIVE)
01984       ast_hangup(c);
01985    return 0;
01986 }

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 2001 of file pbx.c.

02002 {
02003    pthread_t t;
02004    pthread_attr_t attr;
02005    if (!c) {
02006       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
02007       return -1;
02008    }
02009       
02010    /* Start a new thread, and get something handling this channel. */
02011    pthread_attr_init(&attr);
02012    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02013    if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
02014       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
02015       return -1;
02016    }
02017    return 0;
02018 }

int ast_register_application ( char *  app,
int(*)(struct ast_channel *, void *)  execute,
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 2309 of file pbx.c.

02310 {
02311    struct ast_app *tmp, *prev, *cur;
02312    char tmps[80];
02313    if (ast_mutex_lock(&applock)) {
02314       ast_log(LOG_ERROR, "Unable to lock application list\n");
02315       return -1;
02316    }
02317    tmp = apps;
02318    while(tmp) {
02319       if (!strcasecmp(app, tmp->name)) {
02320          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
02321          ast_mutex_unlock(&applock);
02322          return -1;
02323       }
02324       tmp = tmp->next;
02325    }
02326    tmp = malloc(sizeof(struct ast_app));
02327    if (tmp) {
02328       memset(tmp, 0, sizeof(struct ast_app));
02329       strncpy(tmp->name, app, sizeof(tmp->name)-1);
02330       tmp->execute = execute;
02331       tmp->synopsis = synopsis;
02332       tmp->description = description;
02333       /* Store in alphabetical order */
02334       cur = apps;
02335       prev = NULL;
02336       while(cur) {
02337          if (strcasecmp(tmp->name, cur->name) < 0)
02338             break;
02339          prev = cur;
02340          cur = cur->next;
02341       }
02342       if (prev) {
02343          tmp->next = prev->next;
02344          prev->next = tmp;
02345       } else {
02346          tmp->next = apps;
02347          apps = tmp;
02348       }
02349    } else {
02350       ast_log(LOG_ERROR, "Out of memory\n");
02351       ast_mutex_unlock(&applock);
02352       return -1;
02353    }
02354    if (option_verbose > 1)
02355       ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
02356    ast_mutex_unlock(&applock);
02357    return 0;
02358 }

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 2360 of file pbx.c.

02361 {
02362    struct ast_switch *tmp, *prev=NULL;
02363    if (ast_mutex_lock(&switchlock)) {
02364       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02365       return -1;
02366    }
02367    tmp = switches;
02368    while(tmp) {
02369       if (!strcasecmp(tmp->name, sw->name))
02370          break;
02371       prev = tmp;
02372       tmp = tmp->next;
02373    }
02374    if (tmp) {  
02375       ast_mutex_unlock(&switchlock);
02376       ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
02377       return -1;
02378    }
02379    sw->next = NULL;
02380    if (prev) 
02381       prev->next = sw;
02382    else
02383       switches = sw;
02384    ast_mutex_unlock(&switchlock);
02385    return 0;
02386 }

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 1771 of file pbx.c.

01772 {
01773    return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN);
01774 }

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 4936 of file pbx.c.

04937 {
04938    return ast_mutex_unlock(&con->lock);
04939 }

int ast_unlock_contexts ( void   ) 

Unlocks contexts.

Returns 0 on success, -1 on failure

Definition at line 4923 of file pbx.c.

04924 {
04925    return ast_mutex_unlock(&conlock);
04926 }

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 2944 of file pbx.c.

02944                                           {
02945    struct ast_app *tmp, *tmpl = NULL;
02946    if (ast_mutex_lock(&applock)) {
02947       ast_log(LOG_ERROR, "Unable to lock application list\n");
02948       return -1;
02949    }
02950    tmp = apps;
02951    while(tmp) {
02952       if (!strcasecmp(app, tmp->name)) {
02953          if (tmpl)
02954             tmpl->next = tmp->next;
02955          else
02956             apps = tmp->next;
02957          if (option_verbose > 1)
02958             ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
02959          free(tmp);
02960          ast_mutex_unlock(&applock);
02961          return 0;
02962       }
02963       tmpl = tmp;
02964       tmp = tmp->next;
02965    }
02966    ast_mutex_unlock(&applock);
02967    return -1;
02968 }

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 2388 of file pbx.c.

02389 {
02390    struct ast_switch *tmp, *prev=NULL;
02391    if (ast_mutex_lock(&switchlock)) {
02392       ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02393       return;
02394    }
02395    tmp = switches;
02396    while(tmp) {
02397       if (tmp == sw) {
02398          if (prev)
02399             prev->next = tmp->next;
02400          else
02401             switches = tmp->next;
02402          tmp->next = NULL;
02403          break;         
02404       }
02405       prev = tmp;
02406       tmp = tmp->next;
02407    }
02408    ast_mutex_unlock(&switchlock);
02409 }

struct ast_exten* ast_walk_context_extensions ( struct ast_context con,
struct ast_exten priority 
) [read]

Definition at line 5038 of file pbx.c.

05040 {
05041    if (!exten)
05042       return con ? con->root : NULL;
05043    else
05044       return exten->next;
05045 }

struct ast_ignorepat* ast_walk_context_ignorepats ( struct ast_context con,
struct ast_ignorepat ip 
) [read]

Definition at line 5074 of file pbx.c.

05076 {
05077    if (!ip)
05078       return con ? con->ignorepats : NULL;
05079    else
05080       return ip->next;
05081 }

struct ast_include* ast_walk_context_includes ( struct ast_context con,
struct ast_include inc 
) [read]

Definition at line 5065 of file pbx.c.

05067 {
05068    if (!inc)
05069       return con ? con->includes : NULL;
05070    else
05071       return inc->next;
05072 }

struct ast_sw* ast_walk_context_switches ( struct ast_context con,
struct ast_sw sw 
) [read]

Definition at line 5047 of file pbx.c.

05049 {
05050    if (!sw)
05051       return con ? con->alts : NULL;
05052    else
05053       return sw->next;
05054 }

struct ast_context* ast_walk_contexts ( struct ast_context con  )  [read]

Definition at line 5030 of file pbx.c.

05031 {
05032    if (!con)
05033       return contexts;
05034    else
05035       return con->next;
05036 }

struct ast_exten* ast_walk_extension_priorities ( struct ast_exten exten,
struct ast_exten priority 
) [read]

Definition at line 5056 of file pbx.c.

05058 {
05059    if (!priority)
05060       return exten;
05061    else
05062       return priority->peer;
05063 }

void pbx_builtin_clear_globals ( void   ) 

Definition at line 4791 of file pbx.c.

04792 {
04793    struct ast_var_t *vardata;
04794    while (!AST_LIST_EMPTY(&globals)) {
04795       vardata = AST_LIST_FIRST(&globals);
04796       AST_LIST_REMOVE_HEAD(&globals, entries);
04797       ast_var_delete(vardata);
04798    }
04799 }

char* pbx_builtin_getvar_helper ( struct ast_channel chan,
char *  name 
)

int pbx_builtin_setvar ( struct ast_channel chan,
void *  data 
)

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

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 427 of file pbx.c.

00431 {
00432    /* This function is special.  It saves the stack so that no matter
00433       how many times it is called, it returns to the same place */
00434    int res;
00435    
00436    char *saved_c_appl;
00437    char *saved_c_data;
00438    
00439    int stack = c->stack;
00440    int (*execute)(struct ast_channel *chan, void *data) = app->execute; 
00441 
00442    if (newstack && stack > AST_CHANNEL_MAX_STACK - 2) {
00443       /* Don't allow us to go over the max number of stacks we
00444          permit saving. */
00445       ast_log(LOG_WARNING, "Stack overflow, cannot create another stack\n");
00446       return -1;
00447    }
00448    if (newstack && (res = setjmp(c->jmp[++c->stack]))) {
00449       /* Okay, here's where it gets weird.  If newstack is non-zero, 
00450          then we increase the stack increment, but setjmp is not going
00451          to return until longjmp is called -- when the application
00452          exec'd is finished running. */
00453       if (res == 1)
00454          res = 0;
00455       if (c->stack != stack + 1) 
00456          ast_log(LOG_WARNING, "Stack returned to an unexpected place!\n");
00457       else if (c->app[c->stack])
00458          ast_log(LOG_WARNING, "Application may have forgotten to free its memory\n");
00459       c->stack = stack;
00460       return res;
00461    } else {
00462       if (c->cdr)
00463          ast_cdr_setapp(c->cdr, app->name, data);
00464 
00465       /* save channel values */
00466       saved_c_appl= c->appl;
00467       saved_c_data= c->data;
00468 
00469       c->appl = app->name;
00470       c->data = data;      
00471       res = execute(c, data);
00472       /* restore channel values */
00473       c->appl= saved_c_appl;
00474       c->data= saved_c_data;
00475 
00476       /* Any application that returns, we longjmp back, just in case. */
00477       if (c->stack != stack + 1)
00478          ast_log(LOG_WARNING, "Stack is not at expected value\n");
00479       longjmp(c->jmp[stack+1], res);
00480       /* Never returns */
00481    }
00482 }

struct ast_app* pbx_findapp ( char *  app  )  [read]

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 494 of file pbx.c.

00495 {
00496    struct ast_app *tmp;
00497 
00498    if (ast_mutex_lock(&applock)) {
00499       ast_log(LOG_WARNING, "Unable to obtain application lock\n");
00500       return NULL;
00501    }
00502    tmp = apps;
00503    while(tmp) {
00504       if (!strcasecmp(tmp->name, app))
00505          break;
00506       tmp = tmp->next;
00507    }
00508    ast_mutex_unlock(&applock);
00509    return tmp;
00510 }

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

Definition at line 1046 of file pbx.c.

01047 {
01048    char *cp4;
01049    const char *tmp, *whereweare;
01050    int length;
01051    char workspace[4096];
01052    char ltmp[4096], var[4096];
01053    char *nextvar, *nextexp;
01054    char *vars, *vare;
01055    int pos, brackets, needsub, len;
01056    
01057    /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
01058       zero-filled */
01059    whereweare=tmp=cp1;
01060    while(!ast_strlen_zero(whereweare) && count) {
01061       /* Assume we're copying the whole remaining string */
01062       pos = strlen(whereweare);
01063 
01064       /* Look for a variable */
01065       nextvar = strstr(whereweare, "${");
01066       
01067       /* Look for an expression */
01068       nextexp = strstr(whereweare, "$[");
01069       
01070       /* Pick the first one only */
01071       if (nextvar && nextexp) {
01072          if (nextvar < nextexp)
01073             nextexp = NULL;
01074          else
01075             nextvar = NULL;
01076       }
01077       
01078       /* If there is one, we only go that far */
01079       if (nextvar)
01080          pos = nextvar - whereweare;
01081       else if (nextexp)
01082          pos = nextexp - whereweare;
01083       
01084       /* Can't copy more than 'count' bytes */
01085       if (pos > count)
01086          pos = count;
01087       
01088       /* Copy that many bytes */
01089       memcpy(cp2, whereweare, pos);
01090       
01091       count -= pos;
01092       cp2 += pos;
01093       whereweare += pos;
01094       
01095       if (nextvar) {
01096          /* We have a variable.  Find the start and end, and determine
01097             if we are going to have to recursively call ourselves on the
01098             contents */
01099          vars = vare = nextvar + 2;
01100          brackets = 1;
01101          needsub = 0;
01102          
01103          /* Find the end of it */
01104          while(brackets && *vare) {
01105             if ((vare[0] == '$') && (vare[1] == '{')) {
01106                needsub++;
01107                brackets++;
01108             } else if (vare[0] == '}') {
01109                brackets--;
01110             } else if ((vare[0] == '$') && (vare[1] == '['))
01111                needsub++;
01112             vare++;
01113          }
01114          if (brackets)
01115             ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
01116          len = vare - vars - 1;
01117          
01118          /* Skip totally over variable name */
01119          whereweare += ( len + 3);
01120          
01121          /* Store variable name (and truncate) */
01122          memset(var, 0, sizeof(var));
01123          strncpy(var, vars, sizeof(var) - 1);
01124          var[len] = '\0';
01125          
01126          /* Substitute if necessary */
01127          if (needsub) {
01128             memset(ltmp, 0, sizeof(ltmp));
01129             pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
01130             vars = ltmp;
01131          } else {
01132             vars = var;
01133          }
01134          
01135          /* Retrieve variable value */
01136          workspace[0] = '\0';
01137          pbx_substitute_variables_temp(c,vars,&cp4, workspace, sizeof(workspace));
01138          if (cp4) {
01139             length = strlen(cp4);
01140             if (length > count)
01141                length = count;
01142             memcpy(cp2, cp4, length);
01143             count -= length;
01144             cp2 += length;
01145          }
01146          
01147       } else if (nextexp) {
01148          /* We have an expression.  Find the start and end, and determine
01149             if we are going to have to recursively call ourselves on the
01150             contents */
01151          vars = vare = nextexp + 2;
01152          brackets = 1;
01153          needsub = 0;
01154          
01155          /* Find the end of it */
01156          while(brackets && *vare) {
01157             if ((vare[0] == '$') && (vare[1] == '[')) {
01158                needsub++;
01159                brackets++;
01160                vare++;
01161             } else if (vare[0] == '[') {
01162                brackets++;
01163             } else if (vare[0] == ']') {
01164                brackets--;
01165             } else if ((vare[0] == '$') && (vare[1] == '{')) {
01166                needsub++;
01167                vare++;
01168             }
01169             vare++;
01170          }
01171          if (brackets)
01172             ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
01173          len = vare - vars - 1;
01174          
01175          /* Skip totally over variable name */
01176          whereweare += ( len + 3);
01177          
01178          /* Store variable name (and truncate) */
01179          memset(var, 0, sizeof(var));
01180          strncpy(var, vars, sizeof(var) - 1);
01181          var[len] = '\0';
01182          
01183          /* Substitute if necessary */
01184          if (needsub) {
01185             memset(ltmp, 0, sizeof(ltmp));
01186             pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
01187             vars = ltmp;
01188          } else {
01189             vars = var;
01190          }
01191 
01192          /* Evaluate expression */        
01193          cp4 = ast_expr(vars);
01194          
01195          ast_log(LOG_DEBUG, "Expression is '%s'\n", cp4);
01196          
01197          if (cp4) {
01198             length = strlen(cp4);
01199             if (length > count)
01200                length = count;
01201             memcpy(cp2, cp4, length);
01202             count -= length;
01203             cp2 += length;
01204             free(cp4);
01205          }
01206          
01207       } else
01208          break;
01209    }
01210 }


Generated on Wed Oct 28 17:01:00 2009 for Asterisk by  doxygen 1.5.6