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