#include <asterisk/lock.h>#include <asterisk/cli.h>#include <asterisk/pbx.h>#include <asterisk/channel.h>#include <asterisk/options.h>#include <asterisk/logger.h>#include <asterisk/file.h>#include <asterisk/callerid.h>#include <asterisk/cdr.h>#include <asterisk/config.h>#include <asterisk/term.h>#include <asterisk/manager.h>#include <asterisk/ast_expr.h>#include <asterisk/channel_pvt.h>#include <asterisk/linkedlists.h>#include <asterisk/say.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <setjmp.h>#include <ctype.h>#include <errno.h>#include <time.h>#include <sys/time.h>#include "asterisk.h"Go to the source code of this file.
Data Structures | |
| struct | ast_exten |
| struct | ast_include |
| struct | ast_sw |
| struct | ast_ignorepat |
| struct | ast_context |
| struct | ast_app |
| struct | ast_state_cb |
| struct | ast_hint |
| struct | pbx_builtin |
| struct | async_stat |
| struct | app_tmp |
Defines | |
| #define | AST_PBX_MAX_STACK 64 |
| #define | HELPER_EXISTS 0 |
| #define | HELPER_SPAWN 1 |
| #define | HELPER_EXEC 2 |
| #define | HELPER_CANMATCH 3 |
| #define | HELPER_MATCHMORE 4 |
| #define | EXTENSION_MATCH_CORE(data, pattern, match) |
| #define | STATUS_NO_CONTEXT 1 |
| #define | STATUS_NO_EXTENSION 2 |
| #define | STATUS_NO_PRIORITY 3 |
| #define | STATUS_SUCCESS 4 |
| #define | FIND_NEXT |
| #define | LOG |
Functions | |
| int | pbx_builtin_setvar (struct ast_channel *, void *) |
| void | pbx_builtin_setvar_helper (struct ast_channel *chan, char *name, char *value) |
| char * | pbx_builtin_getvar_helper (struct ast_channel *chan, char *name) |
| int | pbx_exec (struct ast_channel *c, struct ast_app *app, void *data, int newstack) |
| executes an application | |
| ast_app * | pbx_findapp (char *app) |
| Look up an application. | |
| int | ast_extension_match (char *pattern, char *data) |
| Determine if a given extension matches a given pattern (in NXX format). | |
| ast_context * | ast_context_find (char *name) |
| Find a context. | |
| void | pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count) |
| 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,...) |
| 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_spawn_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid) |
| Launch a new extension (i.e. new stack). | |
| int | ast_pbx_run (struct ast_channel *c) |
| Execute the PBX in the current thread. | |
| int | ast_pbx_start (struct ast_channel *c) |
| Create a new thread and start the PBX (or whatever). | |
| 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_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_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_register_switch (struct ast_switch *sw) |
| Register an alternative switch. | |
| void | ast_unregister_switch (struct ast_switch *sw) |
| Unregister an alternative switch. | |
| int | ast_unregister_application (char *app) |
| Remove an application. | |
| ast_context * | ast_context_create (struct ast_context **extcontexts, char *name, char *registrar) |
| Register a new context. | |
| void | __ast_context_destroy (struct ast_context *con, char *registrar, int lock) |
| 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. | |
| int | ast_context_add_include (char *context, char *include, char *registrar) |
| Add an include. | |
| int | ast_context_add_include2 (struct ast_context *con, char *value, char *registrar) |
| Add an include. | |
| 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 *value, char *data, char *registrar) |
| Adds a switch (first param is a ast_context). | |
| 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_context_add_ignorepat (char *con, char *value, char *registrar) |
| Add an ignorepat. | |
| int | ast_context_add_ignorepat2 (struct ast_context *con, char *value, char *registrar) |
| int | ast_ignore_pattern (char *context, char *pattern) |
| Checks to see if a number should be ignored. | |
| 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_async_goto (struct ast_channel *chan, char *context, char *exten, int priority, int needlock) |
| int | ast_async_goto_by_name (char *channame, char *context, char *exten, int priority) |
| 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_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) |
| void | ast_context_destroy (struct ast_context *con, char *registrar) |
| Destroy a context (matches the specified context (or ANY context if NULL). | |
| void | pbx_builtin_clear_globals (void) |
| int | load_pbx (void) |
| int | ast_lock_contexts () |
| Locks the contexts. | |
| int | ast_unlock_contexts () |
| 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. | |
| 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 *inc) |
| char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
| int | ast_get_extension_priority (struct ast_exten *exten) |
| 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_extension_app (struct ast_exten *e) |
| void * | ast_get_extension_app_data (struct ast_exten *e) |
| char * | ast_get_switch_name (struct ast_sw *sw) |
| char * | ast_get_switch_data (struct ast_sw *sw) |
| char * | ast_get_switch_registrar (struct ast_sw *sw) |
| ast_context * | ast_walk_contexts (struct ast_context *con) |
| ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten) |
| ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
| ast_exten * | ast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority) |
| ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
| ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
| int | ast_context_verify_includes (struct ast_context *con) |
| Verifies includes in an ast_contect structure. | |
Variables | |
| ast_switch * | switches = NULL |
| ast_hint * | hints = NULL |
| ast_state_cb * | statecbs = NULL |
|
|
|
|
|
Definition at line 494 of file pbx.c. Referenced by ast_extension_match(). |
|
|
Value: do { \ c = info; \ while(*c && (*c != '|')) c++; \ if (*c) { *c = '\0'; c++; } else c = NULL; \ } while(0) |
|
|
Definition at line 414 of file pbx.c. Referenced by ast_canmatch_extension(). |
|
|
|
|
|
Definition at line 411 of file pbx.c. Referenced by ast_exists_extension(). |
|
|
Definition at line 415 of file pbx.c. Referenced by ast_matchmore_extension(). |
|
|
Definition at line 412 of file pbx.c. Referenced by ast_spawn_extension(). |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||
|
Definition at line 4066 of file pbx.c.
04067 {
04068 struct ast_context *tmp, *tmpl=NULL;
04069 struct ast_include *tmpi, *tmpil= NULL;
04070 struct ast_sw *sw, *swl= NULL;
04071 struct ast_exten *e, *el, *en;
04072 struct ast_ignorepat *ipi, *ipl = NULL;
04073 if (lock)
04074 ast_mutex_lock(&conlock);
04075 tmp = contexts;
04076 while(tmp) {
04077 if (((tmp->name && con && con->name && !strcasecmp(tmp->name, con->name)) || !con) &&
04078 (!registrar || !strcasecmp(registrar, tmp->registrar))) {
04079 /* Okay, let's lock the structure to be sure nobody else
04080 is searching through it. */
04081 if (ast_mutex_lock(&tmp->lock)) {
04082 ast_log(LOG_WARNING, "Unable to lock context lock\n");
04083 return;
04084 }
04085 if (tmpl)
04086 tmpl->next = tmp->next;
04087 else
04088 contexts = tmp->next;
04089 /* Okay, now we're safe to let it go -- in a sense, we were
04090 ready to let it go as soon as we locked it. */
04091 ast_mutex_unlock(&tmp->lock);
04092 for (tmpi = tmp->includes; tmpi; ) {
04093 /* Free includes */
04094 tmpil = tmpi;
04095 tmpi = tmpi->next;
04096 free(tmpil);
04097 }
04098 for (ipi = tmp->ignorepats; ipi; ) {
04099 /* Free ignorepats */
04100 ipl = ipi;
04101 ipi = ipi->next;
04102 free(ipl);
04103 }
04104 for (sw = tmp->alts; sw; ) {
04105 /* Free switches */
04106 swl = sw;
04107 sw = sw->next;
04108 free(swl);
04109 swl = sw;
04110 }
04111 for (e = tmp->root; e;) {
04112 for (en = e->peer; en;) {
04113 el = en;
04114 en = en->peer;
04115 destroy_exten(el);
04116 }
04117 el = e;
04118 e = e->next;
04119 destroy_exten(el);
04120 }
04121 free(tmp);
04122 if (!con) {
04123 /* Might need to get another one -- restart */
04124 tmp = contexts;
04125 tmpl = NULL;
04126 tmpil = NULL;
04127 continue;
04128 }
04129 if (lock)
04130 ast_mutex_unlock(&conlock);
04131 return;
04132 }
04133 tmpl = tmp;
04134 tmp = tmp->next;
04135 }
04136 if (lock)
04137 ast_mutex_unlock(&conlock);
04138 }
|
|
||||||||||||||||||||||||||||||||||||||||
|
Definition at line 3472 of file pbx.c.
03474 {
03475 struct ast_context *c;
03476
03477 if (ast_lock_contexts()) {
03478 errno = EBUSY;
03479 return -1;
03480 }
03481
03482 c = ast_walk_contexts(NULL);
03483 while (c) {
03484 if (!strcmp(context, ast_get_context_name(c))) {
03485 int ret = ast_add_extension2(c, replace, extension, priority, callerid,
03486 application, data, datad, registrar);
03487 ast_unlock_contexts();
03488 return ret;
03489 }
03490 c = ast_walk_contexts(c);
03491 }
03492
03493 ast_unlock_contexts();
03494 errno = ENOENT;
03495 return -1;
03496 }
|
|
||||||||||||||||||||||||||||||||||||||||
|
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 3605 of file pbx.c. Referenced by ast_ignore_pattern().
03609 {
03610
03611 #define LOG do { if (option_debug) {\
03612 if (tmp->matchcid) { \
03613 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
03614 } else { \
03615 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
03616 } \
03617 } else if (option_verbose > 2) { \
03618 if (tmp->matchcid) { \
03619 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
03620 } else { \
03621 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
03622 } \
03623 } } while(0)
03624
03625 /*
03626 * This is a fairly complex routine. Different extensions are kept
03627 * in order by the extension number. Then, extensions of different
03628 * priorities (same extension) are kept in a list, according to the
03629 * peer pointer.
03630 */
03631 struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
03632 int res;
03633 /* Be optimistic: Build the extension structure first */
03634 tmp = malloc(sizeof(struct ast_exten));
03635 if (tmp) {
03636 memset(tmp, 0, sizeof(struct ast_exten));
03637 ext_strncpy(tmp->exten, extension, sizeof(tmp->exten));
03638 tmp->priority = priority;
03639 if (callerid) {
03640 ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch));
03641 tmp->matchcid = 1;
03642 } else {
03643 strcpy(tmp->cidmatch, "");
03644 tmp->matchcid = 0;
03645 }
03646 strncpy(tmp->app, application, sizeof(tmp->app)-1);
03647 tmp->parent = con;
03648 tmp->data = data;
03649 tmp->datad = datad;
03650 tmp->registrar = registrar;
03651 tmp->peer = NULL;
03652 tmp->next = NULL;
03653 } else {
03654 ast_log(LOG_ERROR, "Out of memory\n");
03655 errno = ENOMEM;
03656 return -1;
03657 }
03658 if (ast_mutex_lock(&con->lock)) {
03659 free(tmp);
03660 /* And properly destroy the data */
03661 datad(data);
03662 ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
03663 errno = EBUSY;
03664 return -1;
03665 }
03666 e = con->root;
03667 while(e) {
03668 res= strcasecmp(e->exten, extension);
03669 if (!res) {
03670 if (!e->matchcid && !tmp->matchcid)
03671 res = 0;
03672 else if (tmp->matchcid && !e->matchcid)
03673 res = 1;
03674 else if (e->matchcid && !tmp->matchcid)
03675 res = -1;
03676 else
03677 res = strcasecmp(e->cidmatch, tmp->cidmatch);
03678 }
03679 if (res == 0) {
03680 /* We have an exact match, now we find where we are
03681 and be sure there's no duplicates */
03682 while(e) {
03683 if (e->priority == tmp->priority) {
03684 /* Can't have something exactly the same. Is this a
03685 replacement? If so, replace, otherwise, bonk. */
03686 if (replace) {
03687 if (ep) {
03688 /* We're in the peer list, insert ourselves */
03689 ep->peer = tmp;
03690 tmp->peer = e->peer;
03691 } else if (el) {
03692 /* We're the first extension. Take over e's functions */
03693 el->next = tmp;
03694 tmp->next = e->next;
03695 tmp->peer = e->peer;
03696 } else {
03697 /* We're the very first extension. */
03698 con->root = tmp;
03699 tmp->next = e->next;
03700 tmp->peer = e->peer;
03701 }
03702 if (tmp->priority == PRIORITY_HINT)
03703 ast_change_hint(e,tmp);
03704 /* Destroy the old one */
03705 e->datad(e->data);
03706 free(e);
03707 ast_mutex_unlock(&con->lock);
03708 if (tmp->priority == PRIORITY_HINT)
03709 ast_change_hint(e, tmp);
03710 /* And immediately return success. */
03711 LOG;
03712 return 0;
03713 } else {
03714 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
03715 tmp->datad(tmp->data);
03716 free(tmp);
03717 ast_mutex_unlock(&con->lock);
03718 errno = EEXIST;
03719 return -1;
03720 }
03721 } else if (e->priority > tmp->priority) {
03722 /* Slip ourselves in just before e */
03723 if (ep) {
03724 /* Easy enough, we're just in the peer list */
03725 ep->peer = tmp;
03726 tmp->peer = e;
03727 } else if (el) {
03728 /* We're the first extension in this peer list */
03729 el->next = tmp;
03730 tmp->next = e->next;
03731 e->next = NULL;
03732 tmp->peer = e;
03733 } else {
03734 /* We're the very first extension altogether */
03735 tmp->next = con->root->next;
03736 /* Con->root must always exist or we couldn't get here */
03737 tmp->peer = con->root;
03738 con->root = tmp;
03739 }
03740 ast_mutex_unlock(&con->lock);
03741 /* And immediately return success. */
03742 if (tmp->priority == PRIORITY_HINT)
03743 ast_add_hint(tmp);
03744
03745 LOG;
03746 return 0;
03747 }
03748 ep = e;
03749 e = e->peer;
03750 }
03751 /* If we make it here, then it's time for us to go at the very end.
03752 ep *must* be defined or we couldn't have gotten here. */
03753 ep->peer = tmp;
03754 ast_mutex_unlock(&con->lock);
03755 if (tmp->priority == PRIORITY_HINT)
03756 ast_add_hint(tmp);
03757
03758 /* And immediately return success. */
03759 LOG;
03760 return 0;
03761
03762 } else if (res > 0) {
03763 /* Insert ourselves just before 'e'. We're the first extension of
03764 this kind */
03765 tmp->next = e;
03766 if (el) {
03767 /* We're in the list somewhere */
03768 el->next = tmp;
03769 } else {
03770 /* We're at the top of the list */
03771 con->root = tmp;
03772 }
03773 ast_mutex_unlock(&con->lock);
03774 if (tmp->priority == PRIORITY_HINT)
03775 ast_add_hint(tmp);
03776
03777 /* And immediately return success. */
03778 LOG;
03779 return 0;
03780 }
03781
03782 el = e;
03783 e = e->next;
03784 }
03785 /* If we fall all the way through to here, then we need to be on the end. */
03786 if (el)
03787 el->next = tmp;
03788 else
03789 con->root = tmp;
03790 ast_mutex_unlock(&con->lock);
03791 if (tmp->priority == PRIORITY_HINT)
03792 ast_add_hint(tmp);
03793 LOG;
03794 return 0;
03795 }
|
|
||||||||||||||||||||||||
|
Definition at line 3498 of file pbx.c.
03499 {
03500 int res = 0;
03501 if (needlock)
03502 ast_mutex_lock(&chan->lock);
03503 if (chan->pbx) {
03504 /* This channel is currently in the PBX */
03505 if (context && strlen(context))
03506 strncpy(chan->context, context, sizeof(chan->context) - 1);
03507 if (exten && strlen(exten))
03508 strncpy(chan->exten, exten, sizeof(chan->context) - 1);
03509 if (priority)
03510 chan->priority = priority - 1;
03511 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
03512 if (needlock)
03513 ast_mutex_unlock(&chan->lock);
03514 } else {
03515 /* In order to do it when the channel doesn't really exist within
03516 the PBX, we have to make a new channel, masquerade, and start the PBX
03517 at the new location */
03518 struct ast_channel *tmpchan;
03519 struct ast_frame *f;
03520 tmpchan = ast_channel_alloc(0);
03521 if (tmpchan) {
03522 snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
03523 ast_setstate(tmpchan, chan->_state);
03524 /* Make formats okay */
03525 tmpchan->readformat = chan->readformat;
03526 tmpchan->writeformat = chan->writeformat;
03527 /* Setup proper location */
03528 if (context && strlen(context))
03529 strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1);
03530 else
03531 strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1);
03532 if (exten && strlen(exten))
03533 strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1);
03534 else
03535 strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1);
03536 if (priority)
03537 tmpchan->priority = priority;
03538 else
03539 tmpchan->priority = chan->priority;
03540
03541 /* Masquerade into temp channel */
03542 ast_channel_masquerade(tmpchan, chan);
03543
03544 if (needlock)
03545 ast_mutex_unlock(&chan->lock);
03546
03547 /* Make the masquerade happen by reading a frame from the tmp channel */
03548 f = ast_read(tmpchan);
03549 if (f)
03550 ast_frfree(f);
03551 /* Start the PBX going on our stolen channel */
03552 if (ast_pbx_start(tmpchan)) {
03553 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
03554 ast_hangup(tmpchan);
03555 res = -1;
03556 }
03557 } else {
03558 res = -1;
03559 if (needlock)
03560 ast_mutex_unlock(&chan->lock);
03561 }
03562 }
03563 return res;
03564 }
|
|
||||||||||||||||||||
|
Definition at line 3566 of file pbx.c.
03567 {
03568 struct ast_channel *chan;
03569 chan = ast_channel_walk(NULL);
03570 while(chan) {
03571 if (!strcasecmp(channame, chan->name))
03572 break;
03573 chan = ast_channel_walk(chan);
03574 }
03575 if (chan)
03576 return ast_async_goto(chan, context, exten, priority, 1);
03577 return -1;
03578 }
|
|
||||||||||||||||||||||||
|
Looks for a valid matching extension.
Definition at line 1645 of file pbx.c. References HELPER_CANMATCH.
01646 {
01647 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH);
01648 }
|
|
||||||||||||||||
|
Add an ignorepat.
Definition at line 3393 of file pbx.c.
03394 {
03395 struct ast_context *c;
03396
03397 if (ast_lock_contexts()) {
03398 errno = EBUSY;
03399 return -1;
03400 }
03401
03402 c = ast_walk_contexts(NULL);
03403 while (c) {
03404 if (!strcmp(ast_get_context_name(c), con)) {
03405 int ret = ast_context_add_ignorepat2(c, value, registrar);
03406 ast_unlock_contexts();
03407 return ret;
03408 }
03409 c = ast_walk_contexts(c);
03410 }
03411
03412 ast_unlock_contexts();
03413 errno = ENOENT;
03414 return -1;
03415 }
|
|
||||||||||||||||
|
Definition at line 3417 of file pbx.c. References ast_mutex_unlock, and ast_context::lock.
03418 {
03419 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
03420 ignorepat = malloc(sizeof(struct ast_ignorepat));
03421 if (!ignorepat) {
03422 ast_log(LOG_ERROR, "Out of memory\n");
03423 errno = ENOMEM;
03424 return -1;
03425 }
03426 memset(ignorepat, 0, sizeof(struct ast_ignorepat));
03427 strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
03428 ignorepat->next = NULL;
03429 ignorepat->registrar = registrar;
03430 ast_mutex_lock(&con->lock);
03431 ignorepatc = con->ignorepats;
03432 while(ignorepatc) {
03433 ignorepatl = ignorepatc;
03434 if (!strcasecmp(ignorepatc->pattern, value)) {
03435 /* Already there */
03436 ast_mutex_unlock(&con->lock);
03437 errno = EEXIST;
03438 return -1;
03439 }
03440 ignorepatc = ignorepatc->next;
03441 }
03442 if (ignorepatl)
03443 ignorepatl->next = ignorepat;
03444 else
03445 con->ignorepats = ignorepat;
03446 ast_mutex_unlock(&con->lock);
03447 return 0;
03448
03449 }
|
|
||||||||||||||||
|
Add an include.
Definition at line 2857 of file pbx.c.
02858 {
02859 struct ast_context *c;
02860
02861 if (ast_lock_contexts()) {
02862 errno = EBUSY;
02863 return -1;
02864 }
02865
02866 /* walk contexts ... */
02867 c = ast_walk_contexts(NULL);
02868 while (c) {
02869 /* ... search for the right one ... */
02870 if (!strcmp(ast_get_context_name(c), context)) {
02871 int ret = ast_context_add_include2(c, include, registrar);
02872 /* ... unlock contexts list and return */
02873 ast_unlock_contexts();
02874 return ret;
02875 }
02876 c = ast_walk_contexts(c);
02877 }
02878
02879 /* we can't find the right context */
02880 ast_unlock_contexts();
02881 errno = ENOENT;
02882 return -1;
02883 }
|
|
||||||||||||||||
|
Add an include.
Definition at line 3174 of file pbx.c.
03176 {
03177 struct ast_include *new_include;
03178 char *c;
03179 struct ast_include *i, *il = NULL; /* include, include_last */
03180
03181 /* allocate new include structure ... */
03182 if (!(new_include = malloc(sizeof(struct ast_include)))) {
03183 ast_log(LOG_ERROR, "Out of memory\n");
03184 errno = ENOMEM;
03185 return -1;
03186 }
03187
03188 /* ... fill in this structure ... */
03189 memset(new_include, 0, sizeof(struct ast_include));
03190 strncpy(new_include->name, value, sizeof(new_include->name)-1);
03191 strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
03192 c = new_include->rname;
03193 /* Strip off timing info */
03194 while(*c && (*c != '|')) c++;
03195 /* Process if it's there */
03196 if (*c) {
03197 build_timing(new_include, c+1);
03198 *c = '\0';
03199 }
03200 new_include->next = NULL;
03201 new_include->registrar = registrar;
03202
03203 /* ... try to lock this context ... */
03204 if (ast_mutex_lock(&con->lock)) {
03205 free(new_include);
03206 errno = EBUSY;
03207 return -1;
03208 }
03209
03210 /* ... go to last include and check if context is already included too... */
03211 i = con->includes;
03212 while (i) {
03213 if (!strcasecmp(i->name, new_include->name)) {
03214 free(new_include);
03215 ast_mutex_unlock(&con->lock);
03216 errno = EEXIST;
03217 return -1;
03218 }
03219 il = i;
03220 i = i->next;
03221 }
03222
03223 /* ... include new context into context list, unlock, return */
03224 if (il)
03225 il->next = new_include;
03226 else
03227 con->includes = new_include;
03228 if (option_verbose > 2)
03229 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
03230 ast_mutex_unlock(&con->lock);
03231
03232 return 0;
03233 }
|
|
||||||||||||||||||||
|
Add a switch.
Definition at line 3240 of file pbx.c.
03241 {
03242 struct ast_context *c;
03243
03244 if (ast_lock_contexts()) {
03245 errno = EBUSY;
03246 return -1;
03247 }
03248
03249 /* walk contexts ... */
03250 c = ast_walk_contexts(NULL);
03251 while (c) {
03252 /* ... search for the right one ... */
03253 if (!strcmp(ast_get_context_name(c), context)) {
03254 int ret = ast_context_add_switch2(c, sw, data, registrar);
03255 /* ... unlock contexts list and return */
03256 ast_unlock_contexts();
03257 return ret;
03258 }
03259 c = ast_walk_contexts(c);
03260 }
03261
03262 /* we can't find the right context */
03263 ast_unlock_contexts();
03264 errno = ENOENT;
03265 return -1;
03266 }
|
|
||||||||||||||||||||
|
Adds a switch (first param is a ast_context). Definition at line 3275 of file pbx.c.
03277 {
03278 struct ast_sw *new_sw;
03279 struct ast_sw *i, *il = NULL; /* sw, sw_last */
03280
03281 /* allocate new sw structure ... */
03282 if (!(new_sw = malloc(sizeof(struct ast_sw)))) {
03283 ast_log(LOG_ERROR, "Out of memory\n");
03284 errno = ENOMEM;
03285 return -1;
03286 }
03287
03288 /* ... fill in this structure ... */
03289 memset(new_sw, 0, sizeof(struct ast_sw));
03290 strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
03291 if (data)
03292 strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
03293 else
03294 strncpy(new_sw->data, "", sizeof(new_sw->data)-1);
03295 new_sw->next = NULL;
03296 new_sw->registrar = registrar;
03297
03298 /* ... try to lock this context ... */
03299 if (ast_mutex_lock(&con->lock)) {
03300 free(new_sw);
03301 errno = EBUSY;
03302 return -1;
03303 }
03304
03305 /* ... go to last sw and check if context is already swd too... */
03306 i = con->alts;
03307 while (i) {
03308 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
03309 free(new_sw);
03310 ast_mutex_unlock(&con->lock);
03311 errno = EEXIST;
03312 return -1;
03313 }
03314 il = i;
03315 i = i->next;
03316 }
03317
03318 /* ... sw new context into context list, unlock, return */
03319 if (il)
03320 il->next = new_sw;
03321 else
03322 con->alts = new_sw;
03323 if (option_verbose > 2)
03324 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
03325 ast_mutex_unlock(&con->lock);
03326
03327 return 0;
03328 }
|
|
||||||||||||||||
|
Register a new context.
Definition at line 2780 of file pbx.c.
02781 {
02782 struct ast_context *tmp, **local_contexts;
02783 if (!extcontexts) {
02784 local_contexts = &contexts;
02785 ast_mutex_lock(&conlock);
02786 } else
02787 local_contexts = extcontexts;
02788
02789 tmp = *local_contexts;
02790 while(tmp) {
02791 if (!strcasecmp(tmp->name, name)) {
02792 ast_mutex_unlock(&conlock);
02793 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
02794 if (!extcontexts)
02795 ast_mutex_unlock(&conlock);
02796 return NULL;
02797 }
02798 tmp = tmp->next;
02799 }
02800 tmp = malloc(sizeof(struct ast_context));
02801 if (tmp) {
02802 memset(tmp, 0, sizeof(struct ast_context));
02803 ast_mutex_init(&tmp->lock);
02804 strncpy(tmp->name, name, sizeof(tmp->name)-1);
02805 tmp->root = NULL;
02806 tmp->registrar = registrar;
02807 tmp->next = *local_contexts;
02808 tmp->includes = NULL;
02809 tmp->ignorepats = NULL;
02810 *local_contexts = tmp;
02811 if (option_debug)
02812 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
02813 else if (option_verbose > 2)
02814 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
02815 } else
02816 ast_log(LOG_ERROR, "Out of memory\n");
02817
02818 if (!extcontexts)
02819 ast_mutex_unlock(&conlock);
02820 return tmp;
02821 }
|
|
||||||||||||
|
Destroy a context (matches the specified context (or ANY context if NULL).
Definition at line 4140 of file pbx.c.
04141 {
04142 __ast_context_destroy(con,registrar,1);
04143 }
|
|
|
Find a context.
Definition at line 597 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, and ast_context::next.
00598 {
00599 struct ast_context *tmp;
00600 ast_mutex_lock(&conlock);
00601 if (name) {
00602 tmp = contexts;
00603 while(tmp) {
00604 if (!strcasecmp(name, tmp->name))
00605 break;
00606 tmp = tmp->next;
00607 }
00608 } else
00609 tmp = contexts;
00610 ast_mutex_unlock(&conlock);
00611 return tmp;
00612 }
|
|
||||||||||||||||||||
|
Simply remove extension from context.
Definition at line 2055 of file pbx.c. References ast_context_remove_extension2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
02056 {
02057 struct ast_context *c;
02058
02059 if (ast_lock_contexts()) return -1;
02060
02061 /* walk contexts ... */
02062 c = ast_walk_contexts(NULL);
02063 while (c) {
02064 /* ... search for the right one ... */
02065 if (!strcmp(ast_get_context_name(c), context)) {
02066 /* ... remove extension ... */
02067 int ret = ast_context_remove_extension2(c, extension, priority,
02068 registrar);
02069 /* ... unlock contexts list and return */
02070 ast_unlock_contexts();
02071 return ret;
02072 }
02073 c = ast_walk_contexts(c);
02074 }
02075
02076 /* we can't find the right context */
02077 ast_unlock_contexts();
02078 return -1;
02079 }
|
|
||||||||||||||||||||
|
Definition at line 2091 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, free, ast_context::lock, ast_exten::next, ast_exten::peer, PRIORITY_HINT, and ast_context::root. Referenced by ast_context_remove_extension().
02092 {
02093 struct ast_exten *exten, *prev_exten = NULL;
02094
02095 if (ast_mutex_lock(&con->lock)) return -1;
02096
02097 /* go through all extensions in context and search the right one ... */
02098 exten = con->root;
02099 while (exten) {
02100
02101 /* look for right extension */
02102 if (!strcmp(exten->exten, extension) &&
02103 (!strcmp(exten->registrar, registrar) || !registrar)) {
02104 struct ast_exten *peer;
02105
02106 /* should we free all peers in this extension? (priority == 0)? */
02107 if (priority == 0) {
02108 /* remove this extension from context list */
02109 if (prev_exten)
02110 prev_exten->next = exten->next;
02111 else
02112 con->root = exten->next;
02113
02114 /* fire out all peers */
02115 peer = exten;
02116 while (peer) {
02117 exten = peer->peer;
02118
02119 if (!peer->priority==PRIORITY_HINT)
02120 ast_remove_hint(peer);
02121
02122 peer->datad(peer->data);
02123 free(peer);
02124
02125 peer = exten;
02126 }
02127
02128 ast_mutex_unlock(&con->lock);
02129 return 0;
02130 } else {
02131 /* remove only extension with exten->priority == priority */
02132 struct ast_exten *previous_peer = NULL;
02133
02134 peer = exten;
02135 while (peer) {
02136 /* is this our extension? */
02137 if (peer->priority == priority &&
02138 (!strcmp(peer->registrar, registrar) || !registrar)) {
02139 /* we are first priority extension? */
02140 if (!previous_peer) {
02141 /* exists previous extension here? */
02142 if (prev_exten) {
02143 /* yes, so we must change next pointer in
02144 * previous connection to next peer
02145 */
02146 if (peer->peer) {
02147 prev_exten->next = peer->peer;
02148 peer->peer->next = exten->next;
02149 } else
02150 prev_exten->next = exten->next;
02151 } else {
02152 /* no previous extension, we are first
02153 * extension, so change con->root ...
02154 */
02155 if (peer->peer)
02156 con->root = peer->peer;
02157 else
02158 con->root = exten->next;
02159 }
02160 } else {
02161 /* we are not first priority in extension */
02162 previous_peer->peer = peer->peer;
02163 }
02164
02165 /* now, free whole priority extension */
02166 if (peer->priority==PRIORITY_HINT)
02167 ast_remove_hint(peer);
02168 peer->datad(peer->data);
02169 free(peer);
02170
02171 ast_mutex_unlock(&con->lock);
02172 return 0;
02173 } else {
02174 /* this is not right extension, skip to next peer */
02175 previous_peer = peer;
02176 peer = peer->peer;
02177 }
02178 }
02179
02180 ast_mutex_unlock(&con->lock);
02181 return -1;
02182 }
02183 }
02184
02185 prev_exten = exten;
02186 exten = exten->next;
02187 }
02188
02189 /* we can't find right extension */
02190 ast_mutex_unlock(&con->lock);
02191 return -1;
02192 }
|
|
||||||||||||||||
|
Definition at line 3334 of file pbx.c.
03335 {
03336 struct ast_context *c;
03337
03338 if (ast_lock_contexts()) {
03339 errno = EBUSY;
03340 return -1;
03341 }
03342
03343 c = ast_walk_contexts(NULL);
03344 while (c) {
03345 if (!strcmp(ast_get_context_name(c), context)) {
03346 int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
03347 ast_unlock_contexts();
03348 return ret;
03349 }
03350 c = ast_walk_contexts(c);
03351 }
03352
03353 ast_unlock_contexts();
03354 errno = ENOENT;
03355 return -1;
03356 }
|
|
||||||||||||||||
|
Definition at line 3358 of file pbx.c.
03359 {
03360 struct ast_ignorepat *ip, *ipl = NULL;
03361
03362 if (ast_mutex_lock(&con->lock)) {
03363 errno = EBUSY;
03364 return -1;
03365 }
03366
03367 ip = con->ignorepats;
03368 while (ip) {
03369 if (!strcmp(ip->pattern, ignorepat) &&
03370 (registrar == ip->registrar || !registrar)) {
03371 if (ipl) {
03372 ipl->next = ip->next;
03373 free(ip);
03374 } else {
03375 con->ignorepats = ip->next;
03376 free(ip);
03377 }
03378 ast_mutex_unlock(&con->lock);
03379 return 0;
03380 }
03381 ipl = ip; ip = ip->next;
03382 }
03383
03384 ast_mutex_unlock(&con->lock);
03385 errno = EINVAL;
03386 return -1;
03387 }
|
|
||||||||||||||||
|
Removes an include. See add_include Definition at line 1911 of file pbx.c. References ast_context_remove_include2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
01912 {
01913 struct ast_context *c;
01914
01915 if (ast_lock_contexts()) return -1;
01916
01917 /* walk contexts and search for the right one ...*/
01918 c = ast_walk_contexts(NULL);
01919 while (c) {
01920 /* we found one ... */
01921 if (!strcmp(ast_get_context_name(c), context)) {
01922 int ret;
01923 /* remove include from this context ... */
01924 ret = ast_context_remove_include2(c, include, registrar);
01925
01926 ast_unlock_contexts();
01927
01928 /* ... return results */
01929 return ret;
01930 }
01931 c = ast_walk_contexts(c);
01932 }
01933
01934 /* we can't find the right one context */
01935 ast_unlock_contexts();
01936 return -1;
01937 }
|
|
||||||||||||||||
|
Removes an include by an ast_context structure. See add_include2 Definition at line 1947 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, free, ast_context::includes, ast_context::lock, and ast_include::next. Referenced by ast_context_remove_include().
01948 {
01949 struct ast_include *i, *pi = NULL;
01950
01951 if (ast_mutex_lock(&con->lock)) return -1;
01952
01953 /* walk includes */
01954 i = con->includes;
01955 while (i) {
01956 /* find our include */
01957 if (!strcmp(i->name, include) &&
01958 (!strcmp(i->registrar, registrar) || !registrar)) {
01959 /* remove from list */
01960 if (pi)
01961 pi->next = i->next;
01962 else
01963 con->includes = i->next;
01964 /* free include and return */
01965 free(i);
01966 ast_mutex_unlock(&con->lock);
01967 return 0;
01968 }
01969 pi = i;
01970 i = i->next;
01971 }
01972
01973 /* we can't find the right include */
01974 ast_mutex_unlock(&con->lock);
01975 return -1;
01976 }
|
|
||||||||||||||||||||
|
Remove a switch. Removes a switch with the given parameters Returns 0 on success, -1 on failure Definition at line 1983 of file pbx.c. References ast_context_remove_switch2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
01984 {
01985 struct ast_context *c;
01986
01987 if (ast_lock_contexts()) return -1;
01988
01989 /* walk contexts and search for the right one ...*/
01990 c = ast_walk_contexts(NULL);
01991 while (c) {
01992 /* we found one ... */
01993 if (!strcmp(ast_get_context_name(c), context)) {
01994 int ret;
01995 /* remove switch from this context ... */
01996 ret = ast_context_remove_switch2(c, sw, data, registrar);
01997
01998 ast_unlock_contexts();
01999
02000 /* ... return results */
02001 return ret;
02002 }
02003 c = ast_walk_contexts(c);
02004 }
02005
02006 /* we can't find the right one context */
02007 ast_unlock_contexts();
02008 return -1;
02009 }
|
|
||||||||||||||||||||
|
Definition at line 2019 of file pbx.c. References ast_context::alts, ast_mutex_lock, ast_mutex_unlock, free, ast_context::lock, and ast_sw::next. Referenced by ast_context_remove_switch().
02020 {
02021 struct ast_sw *i, *pi = NULL;
02022
02023 if (ast_mutex_lock(&con->lock)) return -1;
02024
02025 /* walk switchs */
02026 i = con->alts;
02027 while (i) {
02028 /* find our switch */
02029 if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
02030 (!strcmp(i->registrar, registrar) || !registrar)) {
02031 /* remove from list */
02032 if (pi)
02033 pi->next = i->next;
02034 else
02035 con->alts = i->next;
02036 /* free switch and return */
02037 free(i);
02038 ast_mutex_unlock(&con->lock);
02039 return 0;
02040 }
02041 pi = i;
02042 i = i->next;
02043 }
02044
02045 /* we can't find the right switch */
02046 ast_mutex_unlock(&con->lock);
02047 return -1;
02048 }
|
|
|
Verifies includes in an ast_contect structure.
Definition at line 4741 of file pbx.c.
04742 {
04743 struct ast_include *inc;
04744 int res = 0;
04745
04746 for (inc = ast_walk_context_includes(con, NULL); inc; inc = ast_walk_context_includes(con, inc))
04747 if (!ast_context_find(inc->rname)) {
04748 res = -1;
04749 ast_log(LOG_WARNING, "Context '%s' tries includes non-existant context '%s'\n",
04750 ast_get_context_name(con), inc->rname);
04751 }
04752 return res;
04753 }
|
|
||||||||||||
|
Definition at line 1321 of file pbx.c. References ast_get_extension_app(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_state_cb::callback, hints, and statecbs.
01322 {
01323 struct ast_hint *list;
01324 struct ast_state_cb *cblist;
01325 char hint[AST_MAX_EXTENSION];
01326 char device[AST_MAX_EXTENSION];
01327 char *cur, *rest;
01328 int state;
01329
01330 va_list ap;
01331
01332 va_start(ap, fmt);
01333 vsnprintf(device, sizeof(device)-1, fmt, ap);
01334 va_end(ap);
01335
01336 rest = strchr(device, '-');
01337 if (rest) {
01338 *rest = 0;
01339 }
01340
01341 ast_mutex_lock(&hintlock);
01342
01343 list = hints;
01344
01345 while (list) {
01346
01347 strcpy(hint, ast_get_extension_app(list->exten));
01348 cur = hint;
01349 do {
01350 rest = strchr(cur, '&');
01351 if (rest) {
01352 *rest = 0;
01353 rest++;
01354 }
01355
01356 if (!strcmp(cur, device)) {
01357 // Found extension execute callbacks
01358 state = ast_extension_state2(list->exten);
01359 if ((state != -1) && (state != list->laststate)) {
01360 // For general callbacks
01361 cblist = statecbs;
01362 while (cblist) {
01363 cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
01364 cblist = cblist->next;
01365 }
01366
01367 // For extension callbacks
01368 cblist = list->callbacks;
01369 while (cblist) {
01370 cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
01371 cblist = cblist->next;
01372 }
01373
01374 list->laststate = state;
01375 }
01376 break;
01377 }
01378 cur = rest;
01379 } while (cur);
01380
01381 list = list->next;
01382 }
01383
01384 ast_mutex_unlock(&hintlock);
01385 return 1;
01386 }
|
|
||||||||||||||||||||||||
|
If an extension exists, return non-zero.
Definition at line 1640 of file pbx.c. References HELPER_EXISTS. Referenced by ast_pbx_run().
01641 {
01642 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
01643 }
|
|
||||||||||||
|
Determine if a given extension matches a given pattern (in NXX format).
Definition at line 564 of file pbx.c. References EXTENSION_MATCH_CORE.
00565 {
00566 int match;
00567 /* If they're the same return */
00568 if (!strcmp(pattern, data))
00569 return 1;
00570 EXTENSION_MATCH_CORE(data,pattern,match);
00571 /* Must be at the end of both */
00572 if (*data || (*pattern && (*pattern != '/')))
00573 match = 0;
00574 return match;
00575 }
|
|
||||||||||||||||
|
Uses hint and devicestate callback to get the state of an extension.
Definition at line 1310 of file pbx.c.
01311 {
01312 struct ast_exten *e;
01313
01314 e = ast_hint_extension(c, context, exten);
01315 if (!e)
01316 return -1;
01317
01318 return ast_extension_state2(e);
01319 }
|
|
||||||||||||||||||||
|
Registers a state change callback.
Definition at line 1388 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, ast_state_cb_type, ast_state_cb::data, hints, malloc, ast_hint::next, and statecbs. Referenced by init_manager().
01390 {
01391 struct ast_hint *list;
01392 struct ast_state_cb *cblist;
01393 struct ast_exten *e;
01394
01395 /* No context and extension add callback to statecbs list */
01396 if (!context && !exten) {
01397 ast_mutex_lock(&hintlock);
01398
01399 cblist = statecbs;
01400 while (cblist) {
01401 if (cblist->callback == callback) {
01402 cblist->data = data;
01403 ast_mutex_unlock(&hintlock);
01404 }
01405
01406 cblist = cblist->next;
01407 }
01408
01409 /* Now inserts the callback */
01410 cblist = malloc(sizeof(struct ast_state_cb));
01411 if (!cblist) {
01412 ast_mutex_unlock(&hintlock);
01413 return -1;
01414 }
01415 memset(cblist, 0, sizeof(struct ast_state_cb));
01416 cblist->id = 0;
01417 cblist->callback = callback;
01418 cblist->data = data;
01419
01420 cblist->next = statecbs;
01421 statecbs = cblist;
01422
01423 ast_mutex_unlock(&hintlock);
01424 return 0;
01425 }
01426
01427 if (!context || !exten)
01428 return -1;
01429
01430 /* This callback type is for only one hint */
01431 e = ast_hint_extension(NULL, context, exten);
01432 if (!e) {
01433 return -1;
01434 }
01435
01436 ast_mutex_lock(&hintlock);
01437 list = hints;
01438
01439 while (list) {
01440 if (list->exten == e)
01441 break;
01442 list = list->next;
01443 }
01444
01445 if (!list) {
01446 ast_mutex_unlock(&hintlock);
01447 return -1;
01448 }
01449
01450 /* Now inserts the callback */
01451 cblist = malloc(sizeof(struct ast_state_cb));
01452 if (!cblist) {
01453 ast_mutex_unlock(&hintlock);
01454 return -1;
01455 }
01456 memset(cblist, 0, sizeof(struct ast_state_cb));
01457 cblist->id = stateid++;
01458 cblist->callback = callback;
01459 cblist->data = data;
01460
01461 cblist->next = list->callbacks;
01462 list->callbacks = cblist;
01463
01464 ast_mutex_unlock(&hintlock);
01465 return cblist->id;
01466 }
|
|
||||||||||||
|
Deletes a registered state change callback by ID.
Definition at line 1468 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, ast_state_cb_type, ast_hint::callbacks, free, hints, ast_state_cb::next, and statecbs.
01469 {
01470 struct ast_hint *list;
01471 struct ast_state_cb *cblist, *cbprev;
01472
01473 if (!id && !callback)
01474 return -1;
01475
01476 ast_mutex_lock(&hintlock);
01477
01478 /* id is zero is a callback without extension */
01479 if (!id) {
01480 cbprev = NULL;
01481 cblist = statecbs;
01482 while (cblist) {
01483 if (cblist->callback == callback) {
01484 if (!cbprev)
01485 statecbs = cblist->next;
01486 else
01487 cbprev->next = cblist->next;
01488
01489 free(cblist);
01490
01491 ast_mutex_unlock(&hintlock);
01492 return 0;
01493 }
01494 cbprev = cblist;
01495 cblist = cblist->next;
01496 }
01497
01498 ast_mutex_lock(&hintlock);
01499 return -1;
01500 }
01501
01502 /* id greater zero is a callback with extension */
01503 list = hints;
01504 while (list) {
01505 cblist = list->callbacks;
01506 cbprev = NULL;
01507 while (cblist) {
01508 if (cblist->id==id) {
01509 if (!cbprev)
01510 list->callbacks = cblist->next;
01511 else
01512 cbprev->next = cblist->next;
01513
01514 free(cblist);
01515
01516 ast_mutex_unlock(&hintlock);
01517 return 0;
01518 }
01519 cbprev = cblist;
01520 cblist = cblist->next;
01521 }
01522 list = list->next;
01523 }
01524
01525 ast_mutex_unlock(&hintlock);
01526 return -1;
01527 }
|
|
|
Definition at line 4612 of file pbx.c. References ast_ignorepat::pattern. Referenced by ast_context_remove_extension(), ast_context_remove_include(), ast_context_remove_switch(), and ast_ignore_pattern().
04613 {
04614 return con ? con->name : NULL;
04615 }
|
|
|
Definition at line 4640 of file pbx.c. References ast_ignorepat::registrar.
04641 {
04642 return c ? c->registrar : NULL;
04643 }
|
|
|
Definition at line 4660 of file pbx.c. References ast_sw::data. Referenced by ast_device_state_changed(), and ast_get_hint().
04661 {
04662 return e ? e->app : NULL;
04663 }
|
|
|
Definition at line 4665 of file pbx.c. References ast_sw::registrar.
04666 {
04667 return e ? e->data : NULL;
04668 }
|
|
|
Definition at line 4617 of file pbx.c. References ast_exten::priority.
04618 {
04619 return exten ? exten->exten : NULL;
04620 }
|
|
|
Definition at line 4632 of file pbx.c.
04633 {
04634 return exten ? exten->priority : -1;
04635 }
|
|
|
Definition at line 4645 of file pbx.c. References ast_exten::app.
04646 {
04647 return e ? e->registrar : NULL;
04648 }
|
|
||||||||||||||||||||||||
|
If an extension exists, return non-zero.
Definition at line 1629 of file pbx.c. References ast_get_extension_app().
01630 {
01631 struct ast_exten *e;
01632 e = ast_hint_extension(c, context, exten);
01633 if (e) {
01634 strncpy(hint, ast_get_extension_app(e), maxlen);
01635 return -1;
01636 }
01637 return 0;
01638 }
|
|
|
Definition at line 4627 of file pbx.c.
04628 {
04629 return ip ? ip->pattern : NULL;
04630 }
|
|
|
Definition at line 4655 of file pbx.c. References ast_sw::name.
04656 {
04657 return ip ? ip->registrar : NULL;
04658 }
|
|
|
Definition at line 4622 of file pbx.c. References ast_context::registrar.
04623 {
04624 return inc ? inc->name : NULL;
04625 }
|
|
|
Definition at line 4650 of file pbx.c. References ast_exten::data.
04651 {
04652 return i ? i->registrar : NULL;
04653 }
|
|
|
Definition at line 4675 of file pbx.c.
04676 {
04677 return sw ? sw->data : NULL;
04678 }
|
|
|
Definition at line 4670 of file pbx.c.
04671 {
04672 return sw ? sw->name : NULL;
04673 }
|
|
|
Definition at line 4680 of file pbx.c. References ast_exten::next, and ast_context::root.
04681 {
04682 return sw ? sw->registrar : NULL;
04683 }
|
|
||||||||||||
|
Checks to see if a number should be ignored.
Definition at line 3451 of file pbx.c. References ast_add_extension2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
03452 {
03453 struct ast_context *con;
03454 struct ast_ignorepat *pat;
03455 con = ast_context_find(context);
03456 if (con) {
03457 pat = con->ignorepats;
03458 while (pat) {
03459 if (ast_extension_match(pat->pattern, pattern))
03460 return 1;
03461 pat = pat->next;
03462 }
03463 }
03464 return 0;
03465 }
|
|
|
Locks a given context.
Definition at line 4599 of file pbx.c.
04600 {
04601 return ast_mutex_lock(&con->lock);
04602 }
|
|
|
Locks the contexts. Locks the context list Returns 0 on success, -1 on error Definition at line 4586 of file pbx.c. Referenced by ast_context_remove_extension(), ast_context_remove_include(), ast_context_remove_switch(), and ast_ignore_pattern().
04587 {
04588 return ast_mutex_lock(&conlock);
04589 }
|
|
||||||||||||||||||||||||
|
Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
Definition at line 1650 of file pbx.c. References HELPER_MATCHMORE. Referenced by ast_pbx_run().
01651 {
01652 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE);
01653 }
|
|
||||||||||||
|
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
Definition at line 2825 of file pbx.c.
02825 {
02826 struct ast_context *tmp, *lasttmp = NULL;
02827 tmp = *extcontexts;
02828 ast_mutex_lock(&conlock);
02829 if (registrar) {
02830 __ast_context_destroy(NULL,registrar,0);
02831 while (tmp) {
02832 lasttmp = tmp;
02833 tmp = tmp->next;
02834 }
02835 } else {
02836 while (tmp) {
02837 __ast_context_destroy(tmp,tmp->registrar,0);
02838 lasttmp = tmp;
02839 tmp = tmp->next;
02840 }
02841 }
02842 if (lasttmp) {
02843 lasttmp->next = contexts;
02844 contexts = *extcontexts;
02845 *extcontexts = NULL;
02846 } else
02847 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
02848 ast_mutex_unlock(&conlock);
02849 return;
02850 }
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
Definition at line 3976 of file pbx.c.
03977 {
03978 struct ast_channel *chan;
03979 struct async_stat *as;
03980 struct app_tmp *tmp;
03981 char *var, *vartmp;
03982 int res = -1;
03983 pthread_attr_t attr;
03984
03985 if (!app || !strlen(app))
03986 return -1;
03987 if (sync) {
03988 chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
03989 if (chan) {
03990 pbx_builtin_setaccount(chan, account);
03991 if (variable) {
03992 vartmp = ast_strdupa(variable);
03993 for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp)) {
03994 pbx_builtin_setvar( chan, var );
03995 }
03996 }
03997 if (chan->_state == AST_STATE_UP) {
03998 res = 0;
03999 if (option_verbose > 3)
04000 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
04001 tmp = malloc(sizeof(struct app_tmp));
04002 if (tmp) {
04003 memset(tmp, 0, sizeof(struct app_tmp));
04004 strncpy(tmp->app, app, sizeof(tmp->app) - 1);
04005 strncpy(tmp->data, appdata, sizeof(tmp->data) - 1);
04006 tmp->chan = chan;
04007 if (sync > 1) {
04008 ast_pbx_run_app(tmp);
04009 } else {
04010 pthread_attr_init(&attr);
04011 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04012 if (pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
04013 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
04014 free(tmp);
04015 ast_hangup(chan);
04016 res = -1;
04017 }
04018 }
04019 } else {
04020 ast_log(LOG_ERROR, "Out of memory :(\n");
04021 res = -1;
04022 }
04023 } else {
04024 if (option_verbose > 3)
04025 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
04026 ast_hangup(chan);
04027 }
04028 }
04029 } else {
04030 as = malloc(sizeof(struct async_stat));
04031 if (!as)
04032 return -1;
04033 memset(as, 0, sizeof(struct async_stat));
04034 chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
04035 if (!chan) {
04036 free(as);
04037 return -1;
04038 }
04039 pbx_builtin_setaccount(chan, account);
04040 as->chan = chan;
04041 strncpy(as->app, app, sizeof(as->app) - 1);
04042 if (appdata)
04043 strncpy(as->appdata, appdata, sizeof(as->appdata) - 1);
04044 as->timeout = timeout;
04045 if (pthread_create(&as->p, NULL, async_wait, as)) {
04046 ast_log(LOG_WARNING, "Failed to start async wait\n");
04047 free(as);
04048 ast_hangup(chan);
04049 return -1;
04050 }
04051 res = 0;
04052 }
04053 return res;
04054 }
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Definition at line 3865 of file pbx.c. References option_verbose.
03866 {
03867 struct ast_channel *chan;
03868 struct async_stat *as;
03869 int res = -1;
03870 char *var, *tmp;
03871 struct outgoing_helper oh;
03872 pthread_attr_t attr;
03873
03874 if (sync) {
03875 LOAD_OH(oh);
03876 chan = __ast_request_and_dial(type, format, data, timeout, reason, callerid, &oh);
03877 if (chan) {
03878 pbx_builtin_setaccount(chan, account);
03879 if (chan->_state == AST_STATE_UP) {
03880 res = 0;
03881 if (option_verbose > 3)
03882 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
03883
03884 if (sync > 1) {
03885 if (ast_pbx_run(chan)) {
03886 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
03887 ast_hangup(chan);
03888 res = -1;
03889 }
03890 } else {
03891 if (ast_pbx_start(chan)) {
03892 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
03893 ast_hangup(chan);
03894 res = -1;
03895 }
03896 }
03897 } else {
03898 if (option_verbose > 3)
03899 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
03900 ast_hangup(chan);
03901 }
03902 } else {
03903 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
03904 /* check if "failed" exists */
03905 if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
03906 chan = ast_channel_alloc(0);
03907 if (chan) {
03908 strncpy(chan->name, "OutgoingSpoolFailed", sizeof(chan->name) - 1);
03909 if (context && strlen(context))
03910 strncpy(chan->context, context, sizeof(chan->context) - 1);
03911 strncpy(chan->exten, "failed", sizeof(chan->exten) - 1);
03912 chan->priority = 1;
03913 if (variable) {
03914 tmp = ast_strdupa(variable);
03915 for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp)) {
03916 pbx_builtin_setvar( chan, var );
03917 }
03918 }
03919 ast_pbx_run(chan);
03920 } else
03921 ast_log(LOG_WARNING, "Can't allocate the channel structure, skipping execution of extension 'failed'\n");
03922 }
03923 }
03924 } else {
03925 as = malloc(sizeof(struct async_stat));
03926 if (!as)
03927 return -1;
03928 memset(as, 0, sizeof(struct async_stat));
03929 chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
03930 if (!chan) {
03931 free(as);
03932 return -1;
03933 }
03934 pbx_builtin_setaccount(chan, account);
03935 as->chan = chan;
03936 strncpy(as->context, context, sizeof(as->context) - 1);
03937 strncpy(as->exten, exten, sizeof(as->exten) - 1);
03938 as->priority = priority;
03939 as->timeout = timeout;
03940 pthread_attr_init(&attr);
03941 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
03942 if (pthread_create(&as->p, &attr, async_wait, as)) {
03943 ast_log(LOG_WARNING, "Failed to start async wait\n");
03944 free(as);
03945 ast_hangup(chan);
03946 return -1;
03947 }
03948 res = 0;
03949 }
03950 return res;
03951 }
|
|
|
Execute the PBX in the current thread.
Definition at line 1660 of file pbx.c. References ast_channel::_softhangup, ast_channel::amaflags, ast_cdr_alloc(), ast_cdr_init(), ast_cdr_start(), ast_cdr_update(), ast_exists_extension(), ast_hangup(), ast_log(), ast_matchmore_extension(), AST_PBX_KEEPALIVE, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_verbose(), ast_waitfordigit(), ast_channel::callerid, ast_channel::cdr, ast_channel::context, ast_pbx::dtimeout, EVENT_FLAG_CALL, ast_channel::exten, free, LOG_DEBUG, LOG_ERROR, LOG_WARNING, malloc, manager_event(), ast_channel::name, option_debug, option_verbose, ast_channel::pbx, pbx_builtin_setvar_helper(), ast_channel::priority, ast_pbx::rtimeout, ast_channel::uniqueid, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, and ast_channel::whentohangup.
01661 {
01662 int firstpass = 1;
01663 char digit;
01664 char exten[256];
01665 int pos;
01666 int waittime;
01667 int res=0;
01668
01669 /* A little initial setup here */
01670 if (c->pbx)
01671 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
01672 c->pbx = malloc(sizeof(struct ast_pbx));
01673 if (!c->pbx) {
01674 ast_log(LOG_ERROR, "Out of memory\n");
01675 return -1;
01676 }
01677 if (c->amaflags) {
01678 if (c->cdr) {
01679 ast_log(LOG_WARNING, "%s already has a call record??\n", c->name);
01680 } else {
01681 c->cdr = ast_cdr_alloc();
01682 if (!c->cdr) {
01683 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
01684 free(c->pbx);
01685 return -1;
01686 }
01687 ast_cdr_init(c->cdr, c);
01688 }
01689 }
01690 memset(c->pbx, 0, sizeof(struct ast_pbx));
01691 /* Set reasonable defaults */
01692 c->pbx->rtimeout = 10;
01693 c->pbx->dtimeout = 5;
01694
01695 /* Start by trying whatever the channel is set to */
01696 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01697 /* JK02: If not successfull fall back to 's' */
01698 strncpy(c->exten, "s", sizeof(c->exten)-1);
01699 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01700 /* JK02: And finally back to default if everything else failed */
01701 strncpy(c->context, "default", sizeof(c->context)-1);
01702 }
01703 c->priority = 1;
01704 }
01705 if (c->cdr)
01706 ast_cdr_start(c->cdr);
01707 for(;;) {
01708 pos = 0;
01709 digit = 0;
01710 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01711 memset(exten, 0, sizeof(exten));
01712 manager_event(EVENT_FLAG_CALL, "Newexten",
01713 "Channel: %s\r\n"
01714 "Context: %s\r\n"
01715 "Extension: %s\r\n"
01716 "Priority: %d\r\n"
01717 "Uniqueid: %s\r\n",
01718 c->name, c->context, c->exten, c->priority, c->uniqueid);
01719 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
01720 /* Something bad happened, or a hangup has been requested. */
01721 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
01722 (res == '*') || (res == '#')) {
01723 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
01724 memset(exten, 0, sizeof(exten));
01725 pos = 0;
01726 exten[pos++] = digit = res;
01727 break;
01728 }
01729 switch(res) {
01730 case AST_PBX_KEEPALIVE:
01731 if (option_debug)
01732 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
01733 else if (option_verbose > 1)
01734 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
01735 goto out;
01736 break;
01737 default:
01738 if (option_debug)
01739 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01740 else if (option_verbose > 1)
01741 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01742 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
01743 c->_softhangup =0;
01744 break;
01745 }
01746 /* atimeout */
01747 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
01748 break;
01749 }
01750
01751 if (c->cdr) {
01752 ast_cdr_update(c);
01753 }
01754 goto out;
01755 }
01756 }
01757 if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->callerid))) {
01758 strncpy(c->exten,"T",sizeof(c->exten) - 1);
01759 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
01760 c->whentohangup = 0;
01761 c->priority = 0;
01762 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
01763 } else if (c->_softhangup) {
01764 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
01765 c->exten, c->priority);
01766 goto out;
01767 }
01768 firstpass = 0;
01769 c->priority++;
01770 }
01771 if (!ast_exists_extension(c, c->context, c->exten, 1, c->callerid)) {
01772 /* It's not a valid extension anymore */
01773 if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
01774 if (option_verbose > 2)
01775 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
01776 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
01777 strncpy(c->exten, "i", sizeof(c->exten)-1);
01778 c->priority = 1;
01779 } else {
01780 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
01781 c->name, c->exten, c->context);
01782 goto out;
01783 }
01784 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
01785 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
01786 c->_softhangup = 0;
01787 } else {
01788 /* Done, wait for an extension */
01789 if (digit)
01790 waittime = c->pbx->dtimeout;
01791 else
01792 waittime = c->pbx->rtimeout;
01793 while (ast_matchmore_extension(c, c->context, exten, 1, c->callerid)) {
01794 /* As long as we're willing to wait, and as long as it's not defined,
01795 keep reading digits until we can't possibly get a right answer anymore. */
01796 digit = ast_waitfordigit(c, waittime * 1000);
01797 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
01798 c->_softhangup = 0;
01799 } else {
01800 if (!digit)
01801 /* No entry */
01802 break;
01803 if (digit < 0)
01804 /* Error, maybe a hangup */
01805 goto out;
01806 exten[pos++] = digit;
01807 waittime = c->pbx->dtimeout;
01808 }
01809 }
01810 if (ast_exists_extension(c, c->context, exten, 1, c->callerid)) {
01811 /* Prepare the next cycle */
01812 strncpy(c->exten, exten, sizeof(c->exten)-1);
01813 c->priority = 1;
01814 } else {
01815 /* No such extension */
01816 if (strlen(exten)) {
01817 /* An invalid extension */
01818 if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
01819 if (option_verbose > 2)
01820 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
01821 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
01822 strncpy(c->exten, "i", sizeof(c->exten)-1);
01823 c->priority = 1;
01824 } else {
01825 ast_log(LOG_WARNING, "Invalid extension, but no rule 'i' in context '%s'\n", c->context);
01826 goto out;
01827 }
01828 } else {
01829 /* A simple timeout */
01830 if (ast_exists_extension(c, c->context, "t", 1, c->callerid)) {
01831 if (option_verbose > 2)
01832 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
01833 strncpy(c->exten, "t", sizeof(c->exten)-1);
01834 c->priority = 1;
01835 } else {
01836 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
01837 goto out;
01838 }
01839 }
01840 }
01841 if (c->cdr) {
01842 if (option_verbose > 2)
01843 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);
01844 ast_cdr_update(c);
01845 }
01846 }
01847 }
01848 if (firstpass)
01849 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
01850 out:
01851 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->callerid)) {
01852 strcpy(c->exten, "h");
01853 c->priority = 1;
01854 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01855 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
01856 /* Something bad happened, or a hangup has been requested. */
01857 if (option_debug)
01858 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01859 else if (option_verbose > 1)
01860 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01861 break;
01862 }
01863 c->priority++;
01864 }
01865 }
01866
01867 pbx_destroy(c->pbx);
01868 c->pbx = NULL;
01869 if (res != AST_PBX_KEEPALIVE)
01870 ast_hangup(c);
01871 return 0;
01872 }
|
|
|
Create a new thread and start the PBX (or whatever).
Definition at line 1887 of file pbx.c. References ast_log(), and LOG_WARNING.
01888 {
01889 pthread_t t;
01890 pthread_attr_t attr;
01891 if (!c) {
01892 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
01893 return -1;
01894 }
01895
01896 /* Start a new thread, and get something handling this channel. */
01897 pthread_attr_init(&attr);
01898 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01899 if (pthread_create(&t, &attr, pbx_thread, c)) {
01900 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
01901 return -1;
01902 }
01903 return 0;
01904 }
|
|
||||||||||||||||||||
|
Add an application. The function 'execute' should return non-zero if the line needs to be hung up.
Definition at line 2195 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), COLOR_BRCYAN, LOG_ERROR, LOG_WARNING, malloc, ast_app::next, option_verbose, term_color(), and VERBOSE_PREFIX_2.
02196 {
02197 struct ast_app *tmp, *prev, *cur;
02198 char tmps[80];
02199 if (ast_mutex_lock(&applock)) {
02200 ast_log(LOG_ERROR, "Unable to lock application list\n");
02201 return -1;
02202 }
02203 tmp = apps;
02204 while(tmp) {
02205 if (!strcasecmp(app, tmp->name)) {
02206 ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
02207 ast_mutex_unlock(&applock);
02208 return -1;
02209 }
02210 tmp = tmp->next;
02211 }
02212 tmp = malloc(sizeof(struct ast_app));
02213 if (tmp) {
02214 memset(tmp, 0, sizeof(struct ast_app));
02215 strncpy(tmp->name, app, sizeof(tmp->name)-1);
02216 tmp->execute = execute;
02217 tmp->synopsis = synopsis;
02218 tmp->description = description;
02219 /* Store in alphabetical order */
02220 cur = apps;
02221 prev = NULL;
02222 while(cur) {
02223 if (strcasecmp(tmp->name, cur->name) < 0)
02224 break;
02225 prev = cur;
02226 cur = cur->next;
02227 }
02228 if (prev) {
02229 tmp->next = prev->next;
02230 prev->next = tmp;
02231 } else {
02232 tmp->next = apps;
02233 apps = tmp;
02234 }
02235 } else {
02236 ast_log(LOG_ERROR, "Out of memory\n");
02237 ast_mutex_unlock(&applock);
02238 return -1;
02239 }
02240 if (option_verbose > 1)
02241 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
02242 ast_mutex_unlock(&applock);
02243 return 0;
02244 }
|
|
|
Register an alternative switch.
Definition at line 2246 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_ERROR, LOG_WARNING, ast_switch::name, ast_switch::next, and switches.
02247 {
02248 struct ast_switch *tmp, *prev=NULL;
02249 if (ast_mutex_lock(&switchlock)) {
02250 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02251 return -1;
02252 }
02253 tmp = switches;
02254 while(tmp) {
02255 if (!strcasecmp(tmp->name, sw->name))
02256 break;
02257 prev = tmp;
02258 tmp = tmp->next;
02259 }
02260 if (tmp) {
02261 ast_mutex_unlock(&switchlock);
02262 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
02263 return -1;
02264 }
02265 sw->next = NULL;
02266 if (prev)
02267 prev->next = sw;
02268 else
02269 switches = sw;
02270 ast_mutex_unlock(&switchlock);
02271 return 0;
02272 }
|
|
||||||||||||||||||||||||
|
Launch a new extension (i.e. new stack).
Definition at line 1655 of file pbx.c. References HELPER_SPAWN. Referenced by ast_pbx_run().
01656 {
01657 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN);
01658 }
|
|
|
Unlocks the given context.
Definition at line 4604 of file pbx.c.
04605 {
04606 return ast_mutex_unlock(&con->lock);
04607 }
|
|
|
Unlocks contexts. Returns 0 on success, -1 on failure Definition at line 4591 of file pbx.c. Referenced by ast_context_remove_extension(), ast_context_remove_include(), ast_context_remove_switch(), and ast_ignore_pattern().
04592 {
04593 return ast_mutex_unlock(&conlock);
04594 }
|
|
|
Remove an application.
Definition at line 2755 of file pbx.c.
02755 {
02756 struct ast_app *tmp, *tmpl = NULL;
02757 if (ast_mutex_lock(&applock)) {
02758 ast_log(LOG_ERROR, "Unable to lock application list\n");
02759 return -1;
02760 }
02761 tmp = apps;
02762 while(tmp) {
02763 if (!strcasecmp(app, tmp->name)) {
02764 if (tmpl)
02765 tmpl->next = tmp->next;
02766 else
02767 apps = tmp->next;
02768 if (option_verbose > 1)
02769 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
02770 ast_mutex_unlock(&applock);
02771 return 0;
02772 }
02773 tmpl = tmp;
02774 tmp = tmp->next;
02775 }
02776 ast_mutex_unlock(&applock);
02777 return -1;
02778 }
|
|
|
Unregister an alternative switch.
Definition at line 2274 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_ERROR, ast_switch::next, and switches.
02275 {
02276 struct ast_switch *tmp, *prev=NULL;
02277 if (ast_mutex_lock(&switchlock)) {
02278 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02279 return;
02280 }
02281 tmp = switches;
02282 while(tmp) {
02283 if (tmp == sw) {
02284 if (prev)
02285 prev->next = tmp->next;
02286 else
02287 switches = tmp->next;
02288 tmp->next = NULL;
02289 break;
02290 }
02291 prev = tmp;
02292 tmp = tmp->next;
02293 }
02294 ast_mutex_unlock(&switchlock);
02295 }
|
|
||||||||||||
|
Definition at line 4696 of file pbx.c.
|
|
||||||||||||
|
Definition at line 4732 of file pbx.c.
04734 {
04735 if (!ip)
04736 return con ? con->ignorepats : NULL;
04737 else
04738 return ip->next;
04739 }
|
|
||||||||||||
|
Definition at line 4723 of file pbx.c.
|
|
||||||||||||
|
Definition at line 4705 of file pbx.c.
|
|
|
Definition at line 4688 of file pbx.c. References ast_context::alts, and ast_sw::next. Referenced by ast_context_remove_extension(), ast_context_remove_include(), ast_context_remove_switch(), and ast_ignore_pattern().
04689 {
04690 if (!con)
04691 return contexts;
04692 else
04693 return con->next;
04694 }
|
|
||||||||||||
|
Definition at line 4714 of file pbx.c.
04716 {
04717 if (!priority)
04718 return exten;
04719 else
04720 return priority->peer;
04721 }
|
|
|
Definition at line 4560 of file pbx.c. Referenced by main().
04561 {
04562 int x;
04563 /* Initialize the PBX */
04564 if (option_verbose) {
04565 ast_verbose( "Asterisk PBX Core Initializing\n");
04566 ast_verbose( "Registering builtin applications:\n");
04567 }
04568 ast_cli_register(&show_applications_cli);
04569 ast_cli_register(&show_application_cli);
04570 ast_cli_register(&show_dialplan_cli);
04571 ast_cli_register(&show_switches_cli);
04572 for (x=0;x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
04573 if (option_verbose)
04574 ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
04575 if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
04576 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
04577 return -1;
04578 }
04579 }
04580 return 0;
04581 }
|
|
|
Definition at line 4484 of file pbx.c.
04485 {
04486 struct ast_var_t *vardata;
04487 while (!AST_LIST_EMPTY(&globals)) {
04488 vardata = AST_LIST_FIRST(&globals);
04489 AST_LIST_REMOVE_HEAD(&globals, entries);
04490 ast_var_delete(vardata);
04491 }
04492 }
|
|
||||||||||||
|
Definition at line 4386 of file pbx.c. References ast_var_name(), and ast_var_value().
04386 {
04387 struct ast_var_t *variables;
04388 struct varshead *headp;
04389
04390 if (chan)
04391 headp=&chan->varshead;
04392 else
04393 headp=&globals;
04394
04395 if (name) {
04396 AST_LIST_TRAVERSE(headp,variables,entries) {
04397 if (!strcmp(name, ast_var_name(variables)))
04398 return ast_var_value(variables);
04399 }
04400 if (headp != &globals) {
04401 /* Check global variables if we haven't already */
04402 headp = &globals;
04403 AST_LIST_TRAVERSE(headp,variables,entries) {
04404 if (!strcmp(name, ast_var_name(variables)))
04405 return ast_var_value(variables);
04406 }
04407 }
04408 }
04409 return NULL;
04410 }
|
|
||||||||||||
|
Definition at line 4437 of file pbx.c.
04438 {
04439 char *name;
04440 char *value;
04441 char *stringp=NULL;
04442
04443 if (!data || !strlen(data)) {
04444 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
04445 return 0;
04446 }
04447
04448 stringp=data;
04449 name=strsep(&stringp,"=");
04450 value=strsep(&stringp,"\0");
04451
04452 pbx_builtin_setvar_helper(chan,name,value);
04453
04454 return(0);
04455 }
|
|
||||||||||||||||
|
Definition at line 4412 of file pbx.c. References AST_LIST_INSERT_HEAD, ast_var_assign(), ast_verbose(), option_verbose, and VERBOSE_PREFIX_3.
04412 {
04413 struct ast_var_t *newvariable;
04414 struct varshead *headp;
04415 if (chan)
04416 headp=&chan->varshead;
04417 else
04418 headp=&globals;
04419
04420 AST_LIST_TRAVERSE (headp,newvariable,entries) {
04421 if (strcasecmp(ast_var_name(newvariable),name)==0) {
04422 /* there is already such a variable, delete it */
04423 AST_LIST_REMOVE(headp,newvariable,ast_var_t,entries);
04424 ast_var_delete(newvariable);
04425 break;
04426 }
04427 }
04428
04429 if (value) {
04430 if ((option_verbose > 1) && (headp == &globals))
04431 ast_verbose(VERBOSE_PREFIX_3 "Setting global variable '%s' to '%s'\n",name, value);
04432 newvariable=ast_var_assign(name,value);
04433 AST_LIST_INSERT_HEAD(headp,newvariable,entries);
04434 }
04435 }
|
|
||||||||||||||||||||
|
executes an application
Definition at line 362 of file pbx.c. References ast_channel::app, ast_channel::appl, ast_cdr_setapp(), AST_CHANNEL_MAX_STACK, ast_log(), ast_channel::cdr, ast_channel::data, ast_app::execute, ast_channel::jmp, LOG_WARNING, ast_app::name, and ast_channel::stack.
00366 {
00367 /* This function is special. It saves the stack so that no matter
00368 how many times it is called, it returns to the same place */
00369 int res;
00370 int stack = c->stack;
00371 int (*execute)(struct ast_channel *chan, void *data) = app->execute;
00372 if (newstack && stack > AST_CHANNEL_MAX_STACK - 2) {
00373 /* Don't allow us to go over the max number of stacks we
00374 permit saving. */
00375 ast_log(LOG_WARNING, "Stack overflow, cannot create another stack\n");
00376 return -1;
00377 }
00378 if (newstack && (res = setjmp(c->jmp[++c->stack]))) {
00379 /* Okay, here's where it gets weird. If newstack is non-zero,
00380 then we increase the stack increment, but setjmp is not going
00381 to return until longjmp is called -- when the application
00382 exec'd is finished running. */
00383 if (res == 1)
00384 res = 0;
00385 if (c->stack != stack + 1)
00386 ast_log(LOG_WARNING, "Stack returned to an unexpected place!\n");
00387 else if (c->app[c->stack])
00388 ast_log(LOG_WARNING, "Application may have forgotten to free its memory\n");
00389 c->stack = stack;
00390 return res;
00391 } else {
00392 if (c->cdr)
00393 ast_cdr_setapp(c->cdr, app->name, data);
00394 c->appl = app->name;
00395 c->data = data;
00396 res = execute(c, data);
00397 c->appl = NULL;
00398 c->data = NULL;
00399 /* Any application that returns, we longjmp back, just in case. */
00400 if (c->stack != stack + 1)
00401 ast_log(LOG_WARNING, "Stack is not at expected value\n");
00402 longjmp(c->jmp[stack+1], res);
00403 /* Never returns */
00404 }
00405 }
|
|
|
Look up an application.
Definition at line 417 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_WARNING, and ast_app::next.
00418 {
00419 struct ast_app *tmp;
00420 if (ast_mutex_lock(&applock)) {
00421 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
00422 return NULL;
00423 }
00424 tmp = apps;
00425 while(tmp) {
00426 if (!strcasecmp(tmp->name, app))
00427 break;
00428 tmp = tmp->next;
00429 }
00430 ast_mutex_unlock(&applock);
00431 return tmp;
00432 }
|
|
||||||||||||||||||||
|
Definition at line 945 of file pbx.c. References ast_expr(), ast_log(), free, LOG_DEBUG, and LOG_NOTICE.
00946 {
00947 char *cp4;
00948 const char *tmp, *whereweare;
00949 int length;
00950 char workspace[256];
00951 char ltmp[256], var[256];
00952 char *nextvar, *nextexp;
00953 char *vars, *vare;
00954 int pos, brackets, needsub, len;
00955
00956 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
00957 zero-filled */
00958 whereweare=tmp=cp1;
00959 while(strlen(whereweare) && count) {
00960 /* Assume we're copying the whole remaining string */
00961 pos = strlen(whereweare);
00962
00963 /* Look for a variable */
00964 nextvar = strstr(whereweare, "${");
00965
00966 nextexp = strstr(whereweare, "$[");
00967
00968 if (nextvar && nextexp) {
00969 if (nextvar < nextexp)
00970 nextexp = NULL;
00971 else
00972 nextvar = NULL;
00973 }
00974
00975 /* If there is one, we only go that far */
00976 if (nextvar)
00977 pos = nextvar - whereweare;
00978 else if (nextexp)
00979 pos = nextexp - whereweare;
00980
00981 /* Can't copy more than 'count' bytes */
00982 if (pos > count)
00983 pos = count;
00984
00985 /* Copy that many bytes */
00986 memcpy(cp2, whereweare, pos);
00987
00988 count -= pos;
00989 cp2 += pos;
00990 whereweare += pos;
00991
00992 if (nextvar) {
00993 /* We have a variable. Find the start and end, and determine
00994 if we are going to have to recursively call ourselves on the
00995 contents */
00996 vars = vare = nextvar + 2;
00997 brackets = 1;
00998 needsub = 0;
00999
01000 /* Find the end of it */
01001 while(brackets && *vare) {
01002 if ((vare[0] == '$') && (vare[1] == '{')) {
01003 needsub++;
01004 brackets++;
01005 } else if (vare[0] == '}') {
01006 brackets--;
01007 } else if ((vare[0] == '$') && (vare[1] == '['))
01008 needsub++;
01009 vare++;
01010 }
01011 if (brackets)
01012 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
01013 len = vare - vars - 1;
01014
01015 /* Skip totally over variable name */
01016 whereweare += ( len + 3);
01017
01018 /* Store variable name (and truncate) */
01019 memset(var, 0, sizeof(var));
01020 strncpy(var, vars, sizeof(var) - 1);
01021 var[len] = '\0';
01022
01023 /* Substitute if necessary */
01024 if (needsub) {
01025 memset(ltmp, 0, sizeof(ltmp));
01026 pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
01027 vars = ltmp;
01028 } else {
01029 vars = var;
01030 }
01031
01032 /* Retrieve variable value */
01033 strcpy(workspace, "");
01034 pbx_substitute_variables_temp(c,vars,&cp4, workspace, sizeof(workspace));
01035 if (cp4) {
01036 length = strlen(cp4);
01037 if (length > count)
01038 length = count;
01039 memcpy(cp2, cp4, length);
01040 count -= length;
01041 cp2 += length;
01042 }
01043
01044 } else if (nextexp) {
01045 /* We have an expression. Find the start and end, and determine
01046 if we are going to have to recursively call ourselves on the
01047 contents */
01048 vars = vare = nextexp + 2;
01049 brackets = 1;
01050 needsub = 0;
01051
01052 /* Find the end of it */
01053 while(brackets && *vare) {
01054 if ((vare[0] == '$') && (vare[1] == '[')) {
01055 needsub++;
01056 brackets++;
01057 } else if (vare[0] == ']') {
01058 brackets--;
01059 } else if ((vare[0] == '$') && (vare[1] == '{'))
01060 needsub++;
01061 vare++;
01062 }
01063 if (brackets)
01064 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
01065 len = vare - vars - 1;
01066
01067 /* Skip totally over variable name */
01068 whereweare += ( len + 3);
01069
01070 /* Store variable name (and truncate) */
01071 memset(var, 0, sizeof(var));
01072 strncpy(var, vars, sizeof(var) - 1);
01073 var[len] = '\0';
01074
01075 /* Substitute if necessary */
01076 if (needsub) {
01077 memset(ltmp, 0, sizeof(ltmp));
01078 pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
01079 vars = ltmp;
01080 } else {
01081 vars = var;
01082 }
01083
01084 /* Evaluate expression */
01085 cp4 = ast_expr(vars);
01086
01087 ast_log(LOG_DEBUG, "Expression is '%s'\n", cp4);
01088
01089 if (cp4) {
01090 length = strlen(cp4);
01091 if (length > count)
01092 length = count;
01093 memcpy(cp2, cp4, length);
01094 count -= length;
01095 cp2 += length;
01096 free(cp4);
01097 }
01098
01099 } else
01100 break;
01101 }
01102 }
|
|
|
Definition at line 359 of file pbx.c. Referenced by ast_device_state_changed(), ast_extension_state_add(), and ast_extension_state_del(). |
|
|
Definition at line 360 of file pbx.c. Referenced by ast_device_state_changed(), ast_extension_state_add(), and ast_extension_state_del(). |
|
|
Definition at line 354 of file pbx.c. Referenced by ast_register_switch(), and ast_unregister_switch(). |
1.3.6-20040222