#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 | app_tmp |
struct | ast_app |
struct | ast_context |
struct | ast_exten |
struct | ast_hint |
struct | ast_ignorepat |
struct | ast_include |
struct | ast_state_cb |
struct | ast_sw |
struct | async_stat |
struct | pbx_builtin |
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 | |
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,...) |
Tells Asterisk the State for Device is changed. | |
int | ast_extension_state_add (char *context, char *exten, ast_state_cb_type callback, void *data) |
Registers a state change callback. | |
int | ast_extension_state_del (int id, ast_state_cb_type callback) |
Deletes a registered state change callback by ID. | |
int | ast_get_hint (char *hint, int maxlen, struct ast_channel *c, char *context, char *exten) |
If an extension exists, return non-zero. | |
int | ast_exists_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid) |
If an extension exists, return non-zero. | |
int | ast_canmatch_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid) |
Looks for a valid matching extension. | |
int | ast_matchmore_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid) |
Looks to see if adding anything to this extension might match something. (exists ^ canmatch). | |
int | ast_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) |
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) |
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) |
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 3959 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, free, LOG_WARNING, ast_context::name, ast_exten::next, ast_context::next, and ast_exten::peer. Referenced by ast_context_destroy(), and ast_merge_contexts_and_delete().
03960 { 03961 struct ast_context *tmp, *tmpl=NULL; 03962 struct ast_include *tmpi, *tmpil= NULL; 03963 struct ast_sw *sw, *swl= NULL; 03964 struct ast_exten *e, *el, *en; 03965 if (lock) 03966 ast_mutex_lock(&conlock); 03967 tmp = contexts; 03968 while(tmp) { 03969 if (((tmp->name && con && con->name && !strcasecmp(tmp->name, con->name)) || !con) && 03970 (!registrar || !strcasecmp(registrar, tmp->registrar))) { 03971 /* Okay, let's lock the structure to be sure nobody else 03972 is searching through it. */ 03973 if (ast_mutex_lock(&tmp->lock)) { 03974 ast_log(LOG_WARNING, "Unable to lock context lock\n"); 03975 return; 03976 } 03977 if (tmpl) 03978 tmpl->next = tmp->next; 03979 else 03980 contexts = tmp->next; 03981 /* Okay, now we're safe to let it go -- in a sense, we were 03982 ready to let it go as soon as we locked it. */ 03983 ast_mutex_unlock(&tmp->lock); 03984 for (tmpi = tmp->includes; tmpi; ) { 03985 /* Free includes */ 03986 tmpil = tmpi; 03987 tmpi = tmpi->next; 03988 free(tmpil); 03989 tmpil = tmpi; 03990 } 03991 for (sw = tmp->alts; sw; ) { 03992 swl = sw; 03993 sw = sw->next; 03994 free(swl); 03995 swl = sw; 03996 } 03997 for (e = tmp->root; e;) { 03998 for (en = e->peer; en;) { 03999 el = en; 04000 en = en->peer; 04001 destroy_exten(el); 04002 } 04003 el = e; 04004 e = e->next; 04005 destroy_exten(el); 04006 } 04007 free(tmp); 04008 if (!con) { 04009 /* Might need to get another one -- restart */ 04010 tmp = contexts; 04011 tmpl = NULL; 04012 tmpil = NULL; 04013 continue; 04014 } 04015 if (lock) 04016 ast_mutex_unlock(&conlock); 04017 return; 04018 } 04019 tmpl = tmp; 04020 tmp = tmp->next; 04021 } 04022 if (lock) 04023 ast_mutex_unlock(&conlock); 04024 } |
|
Definition at line 3390 of file pbx.c. References ast_add_extension2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
03392 { 03393 struct ast_context *c; 03394 03395 if (ast_lock_contexts()) { 03396 errno = EBUSY; 03397 return -1; 03398 } 03399 03400 c = ast_walk_contexts(NULL); 03401 while (c) { 03402 if (!strcmp(context, ast_get_context_name(c))) { 03403 int ret = ast_add_extension2(c, replace, extension, priority, callerid, 03404 application, data, datad, registrar); 03405 ast_unlock_contexts(); 03406 return ret; 03407 } 03408 c = ast_walk_contexts(c); 03409 } 03410 03411 ast_unlock_contexts(); 03412 errno = ENOENT; 03413 return -1; 03414 } |
|
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 3522 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, free, ast_context::lock, LOG_WARNING, malloc, ast_context::name, ast_exten::next, ast_exten::peer, PRIORITY_HINT, ast_context::registrar, and ast_context::root. Referenced by ast_add_extension().
03526 { 03527 03528 #define LOG do { if (option_debug) {\ 03529 if (tmp->matchcid) { \ 03530 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \ 03531 } else { \ 03532 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \ 03533 } \ 03534 } else if (option_verbose > 2) { \ 03535 if (tmp->matchcid) { \ 03536 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \ 03537 } else { \ 03538 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \ 03539 } \ 03540 } } while(0) 03541 03542 /* 03543 * This is a fairly complex routine. Different extensions are kept 03544 * in order by the extension number. Then, extensions of different 03545 * priorities (same extension) are kept in a list, according to the 03546 * peer pointer. 03547 */ 03548 struct ast_exten *tmp, *e, *el = NULL, *ep = NULL; 03549 int res; 03550 /* Be optimistic: Build the extension structure first */ 03551 tmp = malloc(sizeof(struct ast_exten)); 03552 if (tmp) { 03553 memset(tmp, 0, sizeof(struct ast_exten)); 03554 ext_strncpy(tmp->exten, extension, sizeof(tmp->exten)); 03555 tmp->priority = priority; 03556 if (callerid) { 03557 ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch)); 03558 tmp->matchcid = 1; 03559 } else { 03560 strcpy(tmp->cidmatch, ""); 03561 tmp->matchcid = 0; 03562 } 03563 strncpy(tmp->app, application, sizeof(tmp->app)-1); 03564 tmp->parent = con; 03565 tmp->data = data; 03566 tmp->datad = datad; 03567 tmp->registrar = registrar; 03568 tmp->peer = NULL; 03569 tmp->next = NULL; 03570 } else { 03571 ast_log(LOG_WARNING, "Out of memory\n"); 03572 errno = ENOMEM; 03573 return -1; 03574 } 03575 if (ast_mutex_lock(&con->lock)) { 03576 free(tmp); 03577 /* And properly destroy the data */ 03578 datad(data); 03579 ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name); 03580 errno = EBUSY; 03581 return -1; 03582 } 03583 e = con->root; 03584 while(e) { 03585 res= strcasecmp(e->exten, extension); 03586 if (!res) { 03587 if (!e->matchcid && !tmp->matchcid) 03588 res = 0; 03589 else if (tmp->matchcid && !e->matchcid) 03590 res = 1; 03591 else if (e->matchcid && !tmp->matchcid) 03592 res = -1; 03593 else 03594 res = strcasecmp(e->cidmatch, tmp->cidmatch); 03595 } 03596 if (res == 0) { 03597 /* We have an exact match, now we find where we are 03598 and be sure there's no duplicates */ 03599 while(e) { 03600 if (e->priority == tmp->priority) { 03601 /* Can't have something exactly the same. Is this a 03602 replacement? If so, replace, otherwise, bonk. */ 03603 if (replace) { 03604 if (ep) { 03605 /* We're in the peer list, insert ourselves */ 03606 ep->peer = tmp; 03607 tmp->peer = e->peer; 03608 } else if (el) { 03609 /* We're the first extension. Take over e's functions */ 03610 el->next = tmp; 03611 tmp->next = e->next; 03612 tmp->peer = e->peer; 03613 } else { 03614 /* We're the very first extension. */ 03615 con->root = tmp; 03616 tmp->next = e->next; 03617 tmp->peer = e->peer; 03618 } 03619 if (tmp->priority == PRIORITY_HINT) 03620 ast_change_hint(e,tmp); 03621 /* Destroy the old one */ 03622 e->datad(e->data); 03623 free(e); 03624 ast_mutex_unlock(&con->lock); 03625 if (tmp->priority == PRIORITY_HINT) 03626 ast_change_hint(e, tmp); 03627 /* And immediately return success. */ 03628 LOG; 03629 return 0; 03630 } else { 03631 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 03632 tmp->datad(tmp->data); 03633 free(tmp); 03634 ast_mutex_unlock(&con->lock); 03635 errno = EEXIST; 03636 return -1; 03637 } 03638 } else if (e->priority > tmp->priority) { 03639 /* Slip ourselves in just before e */ 03640 if (ep) { 03641 /* Easy enough, we're just in the peer list */ 03642 ep->peer = tmp; 03643 tmp->peer = e; 03644 } else if (el) { 03645 /* We're the first extension in this peer list */ 03646 el->next = tmp; 03647 tmp->next = e->next; 03648 e->next = NULL; 03649 tmp->peer = e; 03650 } else { 03651 /* We're the very first extension altogether */ 03652 tmp->next = con->root; 03653 /* Con->root must always exist or we couldn't get here */ 03654 tmp->peer = con->root->peer; 03655 con->root = tmp; 03656 } 03657 ast_mutex_unlock(&con->lock); 03658 /* And immediately return success. */ 03659 if (tmp->priority == PRIORITY_HINT) 03660 ast_add_hint(tmp); 03661 03662 LOG; 03663 return 0; 03664 } 03665 ep = e; 03666 e = e->peer; 03667 } 03668 /* If we make it here, then it's time for us to go at the very end. 03669 ep *must* be defined or we couldn't have gotten here. */ 03670 ep->peer = tmp; 03671 ast_mutex_unlock(&con->lock); 03672 if (tmp->priority == PRIORITY_HINT) 03673 ast_add_hint(tmp); 03674 03675 /* And immediately return success. */ 03676 LOG; 03677 return 0; 03678 03679 } else if (res > 0) { 03680 /* Insert ourselves just before 'e'. We're the first extension of 03681 this kind */ 03682 tmp->next = e; 03683 if (el) { 03684 /* We're in the list somewhere */ 03685 el->next = tmp; 03686 } else { 03687 /* We're at the top of the list */ 03688 con->root = tmp; 03689 } 03690 ast_mutex_unlock(&con->lock); 03691 if (tmp->priority == PRIORITY_HINT) 03692 ast_add_hint(tmp); 03693 03694 /* And immediately return success. */ 03695 LOG; 03696 return 0; 03697 } 03698 03699 el = e; 03700 e = e->next; 03701 } 03702 /* If we fall all the way through to here, then we need to be on the end. */ 03703 if (el) 03704 el->next = tmp; 03705 else 03706 con->root = tmp; 03707 ast_mutex_unlock(&con->lock); 03708 if (tmp->priority == PRIORITY_HINT) 03709 ast_add_hint(tmp); 03710 LOG; 03711 return 0; 03712 } |
|
Definition at line 3416 of file pbx.c. References ast_channel::_state, ast_channel_alloc(), ast_channel_masquerade(), ast_frfree(), ast_hangup(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pbx_start(), ast_read(), ast_setstate(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_channel::context, ast_channel::exten, ast_channel::lock, LOG_WARNING, ast_channel::name, ast_channel::pbx, ast_channel::priority, ast_channel::readformat, and ast_channel::writeformat. Referenced by ast_async_goto_by_name().
03417 { 03418 int res = 0; 03419 if (needlock) 03420 ast_mutex_lock(&chan->lock); 03421 if (chan->pbx) { 03422 /* This channel is currently in the PBX */ 03423 if (context && strlen(context)) 03424 strncpy(chan->context, context, sizeof(chan->context) - 1); 03425 if (exten && strlen(exten)) 03426 strncpy(chan->exten, exten, sizeof(chan->context) - 1); 03427 if (priority) 03428 chan->priority = priority - 1; 03429 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 03430 if (needlock) 03431 ast_mutex_unlock(&chan->lock); 03432 } else { 03433 /* In order to do it when the channel doesn't really exist within 03434 the PBX, we have to make a new channel, masquerade, and start the PBX 03435 at the new location */ 03436 struct ast_channel *tmpchan; 03437 struct ast_frame *f; 03438 tmpchan = ast_channel_alloc(0); 03439 if (tmpchan) { 03440 snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name); 03441 ast_setstate(tmpchan, chan->_state); 03442 /* Make formats okay */ 03443 tmpchan->readformat = chan->readformat; 03444 tmpchan->writeformat = chan->writeformat; 03445 /* Setup proper location */ 03446 if (context && strlen(context)) 03447 strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1); 03448 else 03449 strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1); 03450 if (exten && strlen(exten)) 03451 strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1); 03452 else 03453 strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1); 03454 if (priority) 03455 tmpchan->priority = priority; 03456 else 03457 tmpchan->priority = chan->priority; 03458 if (needlock) 03459 ast_mutex_unlock(&chan->lock); 03460 03461 /* Masquerade into temp channel */ 03462 ast_channel_masquerade(tmpchan, chan); 03463 03464 /* Make the masquerade happen by reading a frame from the tmp channel */ 03465 f = ast_read(tmpchan); 03466 if (f) 03467 ast_frfree(f); 03468 /* Start the PBX going on our stolen channel */ 03469 if (ast_pbx_start(tmpchan)) { 03470 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 03471 ast_hangup(tmpchan); 03472 res = -1; 03473 } 03474 } else { 03475 res = -1; 03476 if (needlock) 03477 ast_mutex_unlock(&chan->lock); 03478 } 03479 } 03480 return res; 03481 } |
|
Definition at line 3483 of file pbx.c. References ast_async_goto(), ast_channel_walk(), and ast_channel::name.
03484 { 03485 struct ast_channel *chan; 03486 chan = ast_channel_walk(NULL); 03487 while(chan) { 03488 if (!strcasecmp(channame, chan->name)) 03489 break; 03490 chan = ast_channel_walk(chan); 03491 } 03492 if (chan) 03493 return ast_async_goto(chan, context, exten, priority, 1); 03494 return -1; 03495 } |
|
Looks for a valid matching extension.
Definition at line 1622 of file pbx.c. References HELPER_CANMATCH.
01623 {
01624 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH);
01625 }
|
|
Add an ignorepat.
Definition at line 3311 of file pbx.c. References ast_context_add_ignorepat2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
03312 { 03313 struct ast_context *c; 03314 03315 if (ast_lock_contexts()) { 03316 errno = EBUSY; 03317 return -1; 03318 } 03319 03320 c = ast_walk_contexts(NULL); 03321 while (c) { 03322 if (!strcmp(ast_get_context_name(c), con)) { 03323 int ret = ast_context_add_ignorepat2(c, value, registrar); 03324 ast_unlock_contexts(); 03325 return ret; 03326 } 03327 c = ast_walk_contexts(c); 03328 } 03329 03330 ast_unlock_contexts(); 03331 errno = ENOENT; 03332 return -1; 03333 } |
|
Definition at line 3335 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_context::ignorepats, ast_context::lock, LOG_WARNING, and malloc. Referenced by ast_context_add_ignorepat().
03336 { 03337 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 03338 ignorepat = malloc(sizeof(struct ast_ignorepat)); 03339 if (!ignorepat) { 03340 ast_log(LOG_WARNING, "Out of memory\n"); 03341 errno = ENOMEM; 03342 return -1; 03343 } 03344 memset(ignorepat, 0, sizeof(struct ast_ignorepat)); 03345 strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1); 03346 ignorepat->next = NULL; 03347 ignorepat->registrar = registrar; 03348 ast_mutex_lock(&con->lock); 03349 ignorepatc = con->ignorepats; 03350 while(ignorepatc) { 03351 ignorepatl = ignorepatc; 03352 if (!strcasecmp(ignorepatc->pattern, value)) { 03353 /* Already there */ 03354 ast_mutex_unlock(&con->lock); 03355 errno = EEXIST; 03356 return -1; 03357 } 03358 ignorepatc = ignorepatc->next; 03359 } 03360 if (ignorepatl) 03361 ignorepatl->next = ignorepat; 03362 else 03363 con->ignorepats = ignorepat; 03364 ast_mutex_unlock(&con->lock); 03365 return 0; 03366 03367 } |
|
Add an include.
Definition at line 2801 of file pbx.c. References ast_context_add_include2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
02802 { 02803 struct ast_context *c; 02804 02805 if (ast_lock_contexts()) { 02806 errno = EBUSY; 02807 return -1; 02808 } 02809 02810 /* walk contexts ... */ 02811 c = ast_walk_contexts(NULL); 02812 while (c) { 02813 /* ... search for the right one ... */ 02814 if (!strcmp(ast_get_context_name(c), context)) { 02815 int ret = ast_context_add_include2(c, include, registrar); 02816 /* ... unlock contexts list and return */ 02817 ast_unlock_contexts(); 02818 return ret; 02819 } 02820 c = ast_walk_contexts(c); 02821 } 02822 02823 /* we can't find the right context */ 02824 ast_unlock_contexts(); 02825 errno = ENOENT; 02826 return -1; 02827 } |
|
Add an include.
Definition at line 3092 of file pbx.c. References ast_get_context_name(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), free, ast_context::includes, ast_context::lock, LOG_WARNING, malloc, option_verbose, and VERBOSE_PREFIX_3. Referenced by ast_context_add_include().
03094 { 03095 struct ast_include *new_include; 03096 char *c; 03097 struct ast_include *i, *il = NULL; /* include, include_last */ 03098 03099 /* allocate new include structure ... */ 03100 if (!(new_include = malloc(sizeof(struct ast_include)))) { 03101 ast_log(LOG_WARNING, "Out of memory\n"); 03102 errno = ENOMEM; 03103 return -1; 03104 } 03105 03106 /* ... fill in this structure ... */ 03107 memset(new_include, 0, sizeof(struct ast_include)); 03108 strncpy(new_include->name, value, sizeof(new_include->name)-1); 03109 strncpy(new_include->rname, value, sizeof(new_include->rname)-1); 03110 c = new_include->rname; 03111 /* Strip off timing info */ 03112 while(*c && (*c != '|')) c++; 03113 /* Process if it's there */ 03114 if (*c) { 03115 build_timing(new_include, c+1); 03116 *c = '\0'; 03117 } 03118 new_include->next = NULL; 03119 new_include->registrar = registrar; 03120 03121 /* ... try to lock this context ... */ 03122 if (ast_mutex_lock(&con->lock)) { 03123 free(new_include); 03124 errno = EBUSY; 03125 return -1; 03126 } 03127 03128 /* ... go to last include and check if context is already included too... */ 03129 i = con->includes; 03130 while (i) { 03131 if (!strcasecmp(i->name, new_include->name)) { 03132 free(new_include); 03133 ast_mutex_unlock(&con->lock); 03134 errno = EEXIST; 03135 return -1; 03136 } 03137 il = i; 03138 i = i->next; 03139 } 03140 03141 /* ... include new context into context list, unlock, return */ 03142 if (il) 03143 il->next = new_include; 03144 else 03145 con->includes = new_include; 03146 if (option_verbose > 2) 03147 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 03148 ast_mutex_unlock(&con->lock); 03149 03150 return 0; 03151 } |
|
Add a switch.
Definition at line 3158 of file pbx.c. References ast_context_add_switch2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
03159 { 03160 struct ast_context *c; 03161 03162 if (ast_lock_contexts()) { 03163 errno = EBUSY; 03164 return -1; 03165 } 03166 03167 /* walk contexts ... */ 03168 c = ast_walk_contexts(NULL); 03169 while (c) { 03170 /* ... search for the right one ... */ 03171 if (!strcmp(ast_get_context_name(c), context)) { 03172 int ret = ast_context_add_switch2(c, sw, data, registrar); 03173 /* ... unlock contexts list and return */ 03174 ast_unlock_contexts(); 03175 return ret; 03176 } 03177 c = ast_walk_contexts(c); 03178 } 03179 03180 /* we can't find the right context */ 03181 ast_unlock_contexts(); 03182 errno = ENOENT; 03183 return -1; 03184 } |
|
Adds a switch (first param is a ast_context). Definition at line 3193 of file pbx.c. References ast_context::alts, ast_get_context_name(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), free, ast_context::lock, LOG_WARNING, malloc, option_verbose, and VERBOSE_PREFIX_3. Referenced by ast_context_add_switch().
03195 { 03196 struct ast_sw *new_sw; 03197 struct ast_sw *i, *il = NULL; /* sw, sw_last */ 03198 03199 /* allocate new sw structure ... */ 03200 if (!(new_sw = malloc(sizeof(struct ast_sw)))) { 03201 ast_log(LOG_WARNING, "Out of memory\n"); 03202 errno = ENOMEM; 03203 return -1; 03204 } 03205 03206 /* ... fill in this structure ... */ 03207 memset(new_sw, 0, sizeof(struct ast_sw)); 03208 strncpy(new_sw->name, value, sizeof(new_sw->name)-1); 03209 if (data) 03210 strncpy(new_sw->data, data, sizeof(new_sw->data)-1); 03211 else 03212 strncpy(new_sw->data, "", sizeof(new_sw->data)-1); 03213 new_sw->next = NULL; 03214 new_sw->registrar = registrar; 03215 03216 /* ... try to lock this context ... */ 03217 if (ast_mutex_lock(&con->lock)) { 03218 free(new_sw); 03219 errno = EBUSY; 03220 return -1; 03221 } 03222 03223 /* ... go to last sw and check if context is already swd too... */ 03224 i = con->alts; 03225 while (i) { 03226 if (!strcasecmp(i->name, new_sw->name)) { 03227 free(new_sw); 03228 ast_mutex_unlock(&con->lock); 03229 errno = EEXIST; 03230 return -1; 03231 } 03232 il = i; 03233 i = i->next; 03234 } 03235 03236 /* ... sw new context into context list, unlock, return */ 03237 if (il) 03238 il->next = new_sw; 03239 else 03240 con->alts = new_sw; 03241 if (option_verbose > 2) 03242 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 03243 ast_mutex_unlock(&con->lock); 03244 03245 return 0; 03246 } |
|
Register a new context.
Definition at line 2724 of file pbx.c. References ast_log(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_verbose(), LOG_DEBUG, LOG_WARNING, malloc, option_debug, option_verbose, and VERBOSE_PREFIX_3.
02725 { 02726 struct ast_context *tmp, **local_contexts; 02727 if (!extcontexts) { 02728 local_contexts = &contexts; 02729 ast_mutex_lock(&conlock); 02730 } else 02731 local_contexts = extcontexts; 02732 02733 tmp = *local_contexts; 02734 while(tmp) { 02735 if (!strcasecmp(tmp->name, name)) { 02736 ast_mutex_unlock(&conlock); 02737 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name); 02738 if (!extcontexts) 02739 ast_mutex_unlock(&conlock); 02740 return NULL; 02741 } 02742 tmp = tmp->next; 02743 } 02744 tmp = malloc(sizeof(struct ast_context)); 02745 if (tmp) { 02746 memset(tmp, 0, sizeof(struct ast_context)); 02747 ast_mutex_init(&tmp->lock); 02748 strncpy(tmp->name, name, sizeof(tmp->name)-1); 02749 tmp->root = NULL; 02750 tmp->registrar = registrar; 02751 tmp->next = *local_contexts; 02752 tmp->includes = NULL; 02753 tmp->ignorepats = NULL; 02754 *local_contexts = tmp; 02755 if (option_debug) 02756 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name); 02757 else if (option_verbose > 2) 02758 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name); 02759 } else 02760 ast_log(LOG_WARNING, "Out of memory\n"); 02761 02762 if (!extcontexts) 02763 ast_mutex_unlock(&conlock); 02764 return tmp; 02765 } |
|
Destroy a context (matches the specified context (or ANY context if NULL).
Definition at line 4026 of file pbx.c. References __ast_context_destroy().
04027 { 04028 __ast_context_destroy(con,registrar,1); 04029 } |
|
Find a context.
Definition at line 597 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, and ast_context::next. Referenced by ast_ignore_pattern().
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 2028 of file pbx.c. References ast_context_remove_extension2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
02029 { 02030 struct ast_context *c; 02031 02032 if (ast_lock_contexts()) return -1; 02033 02034 /* walk contexts ... */ 02035 c = ast_walk_contexts(NULL); 02036 while (c) { 02037 /* ... search for the right one ... */ 02038 if (!strcmp(ast_get_context_name(c), context)) { 02039 /* ... remove extension ... */ 02040 int ret = ast_context_remove_extension2(c, extension, priority, 02041 registrar); 02042 /* ... unlock contexts list and return */ 02043 ast_unlock_contexts(); 02044 return ret; 02045 } 02046 c = ast_walk_contexts(c); 02047 } 02048 02049 /* we can't find the right context */ 02050 ast_unlock_contexts(); 02051 return -1; 02052 } |
|
Definition at line 2064 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().
02065 { 02066 struct ast_exten *exten, *prev_exten = NULL; 02067 02068 if (ast_mutex_lock(&con->lock)) return -1; 02069 02070 /* go through all extensions in context and search the right one ... */ 02071 exten = con->root; 02072 while (exten) { 02073 02074 /* look for right extension */ 02075 if (!strcmp(exten->exten, extension) && 02076 (!strcmp(exten->registrar, registrar) || !registrar)) { 02077 struct ast_exten *peer; 02078 02079 /* should we free all peers in this extension? (priority == 0)? */ 02080 if (priority == 0) { 02081 /* remove this extension from context list */ 02082 if (prev_exten) 02083 prev_exten->next = exten->next; 02084 else 02085 con->root = exten->next; 02086 02087 /* fire out all peers */ 02088 peer = exten; 02089 while (peer) { 02090 exten = peer->peer; 02091 02092 if (!peer->priority==PRIORITY_HINT) 02093 ast_remove_hint(peer); 02094 02095 peer->datad(peer->data); 02096 free(peer); 02097 02098 peer = exten; 02099 } 02100 02101 ast_mutex_unlock(&con->lock); 02102 return 0; 02103 } else { 02104 /* remove only extension with exten->priority == priority */ 02105 struct ast_exten *previous_peer = NULL; 02106 02107 peer = exten; 02108 while (peer) { 02109 /* is this our extension? */ 02110 if (peer->priority == priority && 02111 (!strcmp(peer->registrar, registrar) || !registrar)) { 02112 /* we are first priority extension? */ 02113 if (!previous_peer) { 02114 /* exists previous extension here? */ 02115 if (prev_exten) { 02116 /* yes, so we must change next pointer in 02117 * previous connection to next peer 02118 */ 02119 if (peer->peer) { 02120 prev_exten->next = peer->peer; 02121 peer->peer->next = exten->next; 02122 } else 02123 prev_exten->next = exten->next; 02124 } else { 02125 /* no previous extension, we are first 02126 * extension, so change con->root ... 02127 */ 02128 if (peer->peer) 02129 con->root = peer->peer; 02130 else 02131 con->root = exten->next; 02132 } 02133 } else { 02134 /* we are not first priority in extension */ 02135 previous_peer->peer = peer->peer; 02136 } 02137 02138 /* now, free whole priority extension */ 02139 if (peer->priority==PRIORITY_HINT) 02140 ast_remove_hint(peer); 02141 peer->datad(peer->data); 02142 free(peer); 02143 02144 ast_mutex_unlock(&con->lock); 02145 return 0; 02146 } else { 02147 /* this is not right extension, skip to next peer */ 02148 previous_peer = peer; 02149 peer = peer->peer; 02150 } 02151 } 02152 02153 ast_mutex_unlock(&con->lock); 02154 return -1; 02155 } 02156 } 02157 02158 prev_exten = exten; 02159 exten = exten->next; 02160 } 02161 02162 /* we can't find right extension */ 02163 ast_mutex_unlock(&con->lock); 02164 return -1; 02165 } |
|
Definition at line 3252 of file pbx.c. References ast_context_remove_ignorepat2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
03253 { 03254 struct ast_context *c; 03255 03256 if (ast_lock_contexts()) { 03257 errno = EBUSY; 03258 return -1; 03259 } 03260 03261 c = ast_walk_contexts(NULL); 03262 while (c) { 03263 if (!strcmp(ast_get_context_name(c), context)) { 03264 int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 03265 ast_unlock_contexts(); 03266 return ret; 03267 } 03268 c = ast_walk_contexts(c); 03269 } 03270 03271 ast_unlock_contexts(); 03272 errno = ENOENT; 03273 return -1; 03274 } |
|
Definition at line 3276 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, free, ast_context::ignorepats, ast_context::lock, and ast_ignorepat::next. Referenced by ast_context_remove_ignorepat().
03277 { 03278 struct ast_ignorepat *ip, *ipl = NULL; 03279 03280 if (ast_mutex_lock(&con->lock)) { 03281 errno = EBUSY; 03282 return -1; 03283 } 03284 03285 ip = con->ignorepats; 03286 while (ip) { 03287 if (!strcmp(ip->pattern, ignorepat) && 03288 (registrar == ip->registrar || !registrar)) { 03289 if (ipl) { 03290 ipl->next = ip->next; 03291 free(ip); 03292 } else { 03293 con->ignorepats = ip->next; 03294 free(ip); 03295 } 03296 ast_mutex_unlock(&con->lock); 03297 return 0; 03298 } 03299 ipl = ip; ip = ip->next; 03300 } 03301 03302 ast_mutex_unlock(&con->lock); 03303 errno = EINVAL; 03304 return -1; 03305 } |
|
Removes an include. See add_include Definition at line 1884 of file pbx.c. References ast_context_remove_include2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
01885 { 01886 struct ast_context *c; 01887 01888 if (ast_lock_contexts()) return -1; 01889 01890 /* walk contexts and search for the right one ...*/ 01891 c = ast_walk_contexts(NULL); 01892 while (c) { 01893 /* we found one ... */ 01894 if (!strcmp(ast_get_context_name(c), context)) { 01895 int ret; 01896 /* remove include from this context ... */ 01897 ret = ast_context_remove_include2(c, include, registrar); 01898 01899 ast_unlock_contexts(); 01900 01901 /* ... return results */ 01902 return ret; 01903 } 01904 c = ast_walk_contexts(c); 01905 } 01906 01907 /* we can't find the right one context */ 01908 ast_unlock_contexts(); 01909 return -1; 01910 } |
|
Removes an include by an ast_context structure. See add_include2 Definition at line 1920 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().
01921 { 01922 struct ast_include *i, *pi = NULL; 01923 01924 if (ast_mutex_lock(&con->lock)) return -1; 01925 01926 /* walk includes */ 01927 i = con->includes; 01928 while (i) { 01929 /* find our include */ 01930 if (!strcmp(i->name, include) && 01931 (!strcmp(i->registrar, registrar) || !registrar)) { 01932 /* remove from list */ 01933 if (pi) 01934 pi->next = i->next; 01935 else 01936 con->includes = i->next; 01937 /* free include and return */ 01938 free(i); 01939 ast_mutex_unlock(&con->lock); 01940 return 0; 01941 } 01942 pi = i; 01943 i = i->next; 01944 } 01945 01946 /* we can't find the right include */ 01947 ast_mutex_unlock(&con->lock); 01948 return -1; 01949 } |
|
Remove a switch. Removes a switch with the given parameters Returns 0 on success, -1 on failure Definition at line 1956 of file pbx.c. References ast_context_remove_switch2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
01957 { 01958 struct ast_context *c; 01959 01960 if (ast_lock_contexts()) return -1; 01961 01962 /* walk contexts and search for the right one ...*/ 01963 c = ast_walk_contexts(NULL); 01964 while (c) { 01965 /* we found one ... */ 01966 if (!strcmp(ast_get_context_name(c), context)) { 01967 int ret; 01968 /* remove switch from this context ... */ 01969 ret = ast_context_remove_switch2(c, sw, data, registrar); 01970 01971 ast_unlock_contexts(); 01972 01973 /* ... return results */ 01974 return ret; 01975 } 01976 c = ast_walk_contexts(c); 01977 } 01978 01979 /* we can't find the right one context */ 01980 ast_unlock_contexts(); 01981 return -1; 01982 } |
|
Definition at line 1992 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().
01993 { 01994 struct ast_sw *i, *pi = NULL; 01995 01996 if (ast_mutex_lock(&con->lock)) return -1; 01997 01998 /* walk switchs */ 01999 i = con->alts; 02000 while (i) { 02001 /* find our switch */ 02002 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 02003 (!strcmp(i->registrar, registrar) || !registrar)) { 02004 /* remove from list */ 02005 if (pi) 02006 pi->next = i->next; 02007 else 02008 con->alts = i->next; 02009 /* free switch and return */ 02010 free(i); 02011 ast_mutex_unlock(&con->lock); 02012 return 0; 02013 } 02014 pi = i; 02015 i = i->next; 02016 } 02017 02018 /* we can't find the right switch */ 02019 ast_mutex_unlock(&con->lock); 02020 return -1; 02021 } |
|
Tells Asterisk the State for Device is changed.
Definition at line 1298 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.
01299 { 01300 struct ast_hint *list; 01301 struct ast_state_cb *cblist; 01302 char hint[AST_MAX_EXTENSION]; 01303 char device[AST_MAX_EXTENSION]; 01304 char *cur, *rest; 01305 int state; 01306 01307 va_list ap; 01308 01309 va_start(ap, fmt); 01310 vsnprintf(device, sizeof(device)-1, fmt, ap); 01311 va_end(ap); 01312 01313 rest = strchr(device, '-'); 01314 if (rest) { 01315 *rest = 0; 01316 } 01317 01318 ast_mutex_lock(&hintlock); 01319 01320 list = hints; 01321 01322 while (list) { 01323 01324 strcpy(hint, ast_get_extension_app(list->exten)); 01325 cur = hint; 01326 do { 01327 rest = strchr(cur, '&'); 01328 if (rest) { 01329 *rest = 0; 01330 rest++; 01331 } 01332 01333 if (!strcmp(cur, device)) { 01334 // Found extension execute callbacks 01335 state = ast_extension_state2(list->exten); 01336 if ((state != -1) && (state != list->laststate)) { 01337 // For general callbacks 01338 cblist = statecbs; 01339 while (cblist) { 01340 cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data); 01341 cblist = cblist->next; 01342 } 01343 01344 // For extension callbacks 01345 cblist = list->callbacks; 01346 while (cblist) { 01347 cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data); 01348 cblist = cblist->next; 01349 } 01350 01351 list->laststate = state; 01352 } 01353 break; 01354 } 01355 cur = rest; 01356 } while (cur); 01357 01358 list = list->next; 01359 } 01360 01361 ast_mutex_unlock(&hintlock); 01362 return 1; 01363 } |
|
If an extension exists, return non-zero.
Definition at line 1617 of file pbx.c. References HELPER_EXISTS. Referenced by ast_pbx_run().
01618 {
01619 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
01620 }
|
|
Determine if a given extension matches a given pattern (in NXX format).
Definition at line 564 of file pbx.c. References EXTENSION_MATCH_CORE. Referenced by ast_ignore_pattern().
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 1287 of file pbx.c.
01288 { 01289 struct ast_exten *e; 01290 01291 e = ast_hint_extension(c, context, exten); 01292 if (!e) 01293 return -1; 01294 01295 return ast_extension_state2(e); 01296 } |
|
Registers a state change callback.
Definition at line 1365 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().
01367 { 01368 struct ast_hint *list; 01369 struct ast_state_cb *cblist; 01370 struct ast_exten *e; 01371 01372 /* No context and extension add callback to statecbs list */ 01373 if (!context && !exten) { 01374 ast_mutex_lock(&hintlock); 01375 01376 cblist = statecbs; 01377 while (cblist) { 01378 if (cblist->callback == callback) { 01379 cblist->data = data; 01380 ast_mutex_unlock(&hintlock); 01381 } 01382 01383 cblist = cblist->next; 01384 } 01385 01386 /* Now inserts the callback */ 01387 cblist = malloc(sizeof(struct ast_state_cb)); 01388 if (!cblist) { 01389 ast_mutex_unlock(&hintlock); 01390 return -1; 01391 } 01392 memset(cblist, 0, sizeof(struct ast_state_cb)); 01393 cblist->id = 0; 01394 cblist->callback = callback; 01395 cblist->data = data; 01396 01397 cblist->next = statecbs; 01398 statecbs = cblist; 01399 01400 ast_mutex_unlock(&hintlock); 01401 return 0; 01402 } 01403 01404 if (!context || !exten) 01405 return -1; 01406 01407 /* This callback type is for only one hint */ 01408 e = ast_hint_extension(NULL, context, exten); 01409 if (!e) { 01410 return -1; 01411 } 01412 01413 ast_mutex_lock(&hintlock); 01414 list = hints; 01415 01416 while (list) { 01417 if (list->exten == e) 01418 break; 01419 list = list->next; 01420 } 01421 01422 if (!list) { 01423 ast_mutex_unlock(&hintlock); 01424 return -1; 01425 } 01426 01427 /* Now inserts the callback */ 01428 cblist = malloc(sizeof(struct ast_state_cb)); 01429 if (!cblist) { 01430 ast_mutex_unlock(&hintlock); 01431 return -1; 01432 } 01433 memset(cblist, 0, sizeof(struct ast_state_cb)); 01434 cblist->id = stateid++; 01435 cblist->callback = callback; 01436 cblist->data = data; 01437 01438 cblist->next = list->callbacks; 01439 list->callbacks = cblist; 01440 01441 ast_mutex_unlock(&hintlock); 01442 return cblist->id; 01443 } |
|
Deletes a registered state change callback by ID.
Definition at line 1445 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.
01446 { 01447 struct ast_hint *list; 01448 struct ast_state_cb *cblist, *cbprev; 01449 01450 if (!id && !callback) 01451 return -1; 01452 01453 ast_mutex_lock(&hintlock); 01454 01455 /* id is zero is a callback without extension */ 01456 if (!id) { 01457 cbprev = NULL; 01458 cblist = statecbs; 01459 while (cblist) { 01460 if (cblist->callback == callback) { 01461 if (!cbprev) 01462 statecbs = cblist->next; 01463 else 01464 cbprev->next = cblist->next; 01465 01466 free(cblist); 01467 01468 ast_mutex_unlock(&hintlock); 01469 return 0; 01470 } 01471 cbprev = cblist; 01472 cblist = cblist->next; 01473 } 01474 01475 ast_mutex_lock(&hintlock); 01476 return -1; 01477 } 01478 01479 /* id greater zero is a callback with extension */ 01480 list = hints; 01481 while (list) { 01482 cblist = list->callbacks; 01483 cbprev = NULL; 01484 while (cblist) { 01485 if (cblist->id==id) { 01486 if (!cbprev) 01487 list->callbacks = cblist->next; 01488 else 01489 cbprev->next = cblist->next; 01490 01491 free(cblist); 01492 01493 ast_mutex_unlock(&hintlock); 01494 return 0; 01495 } 01496 cbprev = cblist; 01497 cblist = cblist->next; 01498 } 01499 list = list->next; 01500 } 01501 01502 ast_mutex_unlock(&hintlock); 01503 return -1; 01504 } |
|
Definition at line 4497 of file pbx.c. References ast_context::name. Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_include2(), ast_context_add_switch(), ast_context_add_switch2(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().
04498 { 04499 return con ? con->name : NULL; 04500 } |
|
Definition at line 4525 of file pbx.c. References ast_context::registrar.
04526 { 04527 return c ? c->registrar : NULL; 04528 } |
|
Definition at line 4545 of file pbx.c. References ast_exten::app. Referenced by ast_device_state_changed(), and ast_get_hint().
04546 { 04547 return e ? e->app : NULL; 04548 } |
|
Definition at line 4550 of file pbx.c. References ast_exten::data.
04551 { 04552 return e ? e->data : NULL; 04553 } |
|
Definition at line 4502 of file pbx.c. References ast_exten::exten.
04503 { 04504 return exten ? exten->exten : NULL; 04505 } |
|
Definition at line 4517 of file pbx.c. References ast_exten::priority.
04518 { 04519 return exten ? exten->priority : -1; 04520 } |
|
Definition at line 4530 of file pbx.c. References ast_exten::registrar.
04531 { 04532 return e ? e->registrar : NULL; 04533 } |
|
If an extension exists, return non-zero.
Definition at line 1606 of file pbx.c. References ast_get_extension_app().
01607 { 01608 struct ast_exten *e; 01609 e = ast_hint_extension(c, context, exten); 01610 if (e) { 01611 strncpy(hint, ast_get_extension_app(e), maxlen); 01612 return -1; 01613 } 01614 return 0; 01615 } |
|
Definition at line 4512 of file pbx.c. References ast_ignorepat::pattern.
04513 { 04514 return ip ? ip->pattern : NULL; 04515 } |
|
Definition at line 4540 of file pbx.c. References ast_ignorepat::registrar.
04541 { 04542 return ip ? ip->registrar : NULL; 04543 } |
|
Definition at line 4507 of file pbx.c. References ast_include::name.
04508 { 04509 return inc ? inc->name : NULL; 04510 } |
|
Definition at line 4535 of file pbx.c. References ast_include::registrar.
04536 { 04537 return i ? i->registrar : NULL; 04538 } |
|
Definition at line 4560 of file pbx.c. References ast_sw::data.
04561 { 04562 return sw ? sw->data : NULL; 04563 } |
|
Definition at line 4555 of file pbx.c. References ast_sw::name.
04556 { 04557 return sw ? sw->name : NULL; 04558 } |
|
Definition at line 4565 of file pbx.c. References ast_sw::registrar.
04566 { 04567 return sw ? sw->registrar : NULL; 04568 } |
|
Checks to see if a number should be ignored.
Definition at line 3369 of file pbx.c. References ast_context_find(), and ast_extension_match().
03370 { 03371 struct ast_context *con; 03372 struct ast_ignorepat *pat; 03373 con = ast_context_find(context); 03374 if (con) { 03375 pat = con->ignorepats; 03376 while (pat) { 03377 if (ast_extension_match(pat->pattern, pattern)) 03378 return 1; 03379 pat = pat->next; 03380 } 03381 } 03382 return 0; 03383 } |
|
Locks a given context.
Definition at line 4484 of file pbx.c. References ast_mutex_lock, and ast_context::lock.
04485 { 04486 return ast_mutex_lock(&con->lock); 04487 } |
|
Locks the contexts. Locks the context list Returns 0 on success, -1 on error Definition at line 4471 of file pbx.c. References ast_mutex_lock. Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().
04472 { 04473 return ast_mutex_lock(&conlock); 04474 } |
|
Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
Definition at line 1627 of file pbx.c. References HELPER_MATCHMORE. Referenced by ast_pbx_run().
01628 {
01629 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE);
01630 }
|
|
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
Definition at line 2769 of file pbx.c. References __ast_context_destroy(), ast_log(), ast_mutex_lock, ast_mutex_unlock, and LOG_WARNING.
02769 { 02770 struct ast_context *tmp, *lasttmp = NULL; 02771 tmp = *extcontexts; 02772 ast_mutex_lock(&conlock); 02773 if (registrar) { 02774 __ast_context_destroy(NULL,registrar,0); 02775 while (tmp) { 02776 lasttmp = tmp; 02777 tmp = tmp->next; 02778 } 02779 } else { 02780 while (tmp) { 02781 __ast_context_destroy(tmp,tmp->registrar,0); 02782 lasttmp = tmp; 02783 tmp = tmp->next; 02784 } 02785 } 02786 if (lasttmp) { 02787 lasttmp->next = contexts; 02788 contexts = *extcontexts; 02789 *extcontexts = NULL; 02790 } else 02791 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n"); 02792 ast_mutex_unlock(&conlock); 02793 return; 02794 } |
|
Definition at line 3877 of file pbx.c. References ast_channel::_state, ast_hangup(), ast_log(), ast_request_and_dial(), AST_STATE_UP, ast_verbose(), free, LOG_WARNING, malloc, ast_channel::name, option_verbose, type, and VERBOSE_PREFIX_4.
03878 { 03879 struct ast_channel *chan; 03880 struct async_stat *as; 03881 struct app_tmp *tmp; 03882 char *var, *vartmp; 03883 int res = -1; 03884 if (!app || !strlen(app)) 03885 return -1; 03886 if (sync) { 03887 chan = ast_request_and_dial(type, format, data, timeout, reason, callerid); 03888 if (chan) { 03889 vartmp = variable; 03890 while( (var = strtok_r(NULL, "|", &vartmp)) ) { 03891 pbx_builtin_setvar( chan, var ); 03892 } 03893 if (chan->_state == AST_STATE_UP) { 03894 res = 0; 03895 if (option_verbose > 3) 03896 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 03897 tmp = malloc(sizeof(struct app_tmp)); 03898 if (tmp) { 03899 memset(tmp, 0, sizeof(struct app_tmp)); 03900 strncpy(tmp->app, app, sizeof(tmp->app) - 1); 03901 strncpy(tmp->data, appdata, sizeof(tmp->data) - 1); 03902 tmp->chan = chan; 03903 if (sync > 1) { 03904 ast_pbx_run_app(tmp); 03905 } else { 03906 if (pthread_create(&tmp->t, NULL, ast_pbx_run_app, tmp)) { 03907 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 03908 free(tmp); 03909 ast_hangup(chan); 03910 res = -1; 03911 } 03912 } 03913 } else { 03914 ast_log(LOG_WARNING, "Out of memory :(\n"); 03915 res = -1; 03916 } 03917 } else { 03918 if (option_verbose > 3) 03919 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 03920 ast_hangup(chan); 03921 } 03922 } 03923 } else { 03924 as = malloc(sizeof(struct async_stat)); 03925 if (!as) 03926 return -1; 03927 memset(as, 0, sizeof(struct async_stat)); 03928 chan = ast_request_and_dial(type, format, data, 0, reason, callerid); 03929 if (!chan) { 03930 free(as); 03931 return -1; 03932 } 03933 as->chan = chan; 03934 strncpy(as->app, app, sizeof(as->app) - 1); 03935 if (appdata) 03936 strncpy(as->appdata, appdata, sizeof(as->appdata) - 1); 03937 as->timeout = timeout; 03938 if (pthread_create(&as->p, NULL, async_wait, as)) { 03939 ast_log(LOG_WARNING, "Failed to start async wait\n"); 03940 free(as); 03941 ast_hangup(chan); 03942 return -1; 03943 } 03944 res = 0; 03945 } 03946 return res; 03947 } |
|
Definition at line 3782 of file pbx.c. References ast_channel::_state, ast_hangup(), ast_log(), ast_pbx_run(), ast_pbx_start(), ast_request_and_dial(), AST_STATE_UP, ast_verbose(), ast_channel::callerid, ast_channel::context, ast_channel::exten, free, LOG_WARNING, malloc, ast_channel::name, option_verbose, ast_channel::priority, type, and VERBOSE_PREFIX_4.
03783 { 03784 struct ast_channel *chan; 03785 struct async_stat *as; 03786 int res = -1; 03787 char *var, *tmp; 03788 if (sync) { 03789 chan = ast_request_and_dial(type, format, data, timeout, reason, callerid); 03790 if (chan) { 03791 /* JDG chanvar */ 03792 tmp = variable; 03793 /* FIXME replace this call with strsep NOT*/ 03794 while( (var = strtok_r(NULL, "|", &tmp)) ) { 03795 pbx_builtin_setvar( chan, var ); 03796 } /* /JDG */ 03797 if (chan->_state == AST_STATE_UP) { 03798 res = 0; 03799 if (option_verbose > 3) 03800 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 03801 if (context && strlen(context)) 03802 strncpy(chan->context, context, sizeof(chan->context) - 1); 03803 if (exten && strlen(exten)) 03804 strncpy(chan->exten, exten, sizeof(chan->exten) - 1); 03805 if (callerid && strlen(callerid)) 03806 strncpy(chan->callerid, callerid, sizeof(chan->callerid) - 1); 03807 if (priority > 0) 03808 chan->priority = priority; 03809 if (sync > 1) { 03810 if (ast_pbx_run(chan)) { 03811 ast_log(LOG_WARNING, "Unable to run PBX on %s\n", chan->name); 03812 ast_hangup(chan); 03813 res = -1; 03814 } 03815 } else { 03816 if (ast_pbx_start(chan)) { 03817 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", chan->name); 03818 ast_hangup(chan); 03819 res = -1; 03820 } 03821 } 03822 } else { 03823 if (option_verbose > 3) 03824 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 03825 ast_hangup(chan); 03826 } 03827 } 03828 } else { 03829 as = malloc(sizeof(struct async_stat)); 03830 if (!as) 03831 return -1; 03832 memset(as, 0, sizeof(struct async_stat)); 03833 chan = ast_request_and_dial(type, format, data, 0, reason, callerid); 03834 if (!chan) { 03835 free(as); 03836 return -1; 03837 } 03838 as->chan = chan; 03839 strncpy(as->context, context, sizeof(as->context) - 1); 03840 strncpy(as->exten, exten, sizeof(as->exten) - 1); 03841 as->priority = priority; 03842 as->timeout = timeout; 03843 if (pthread_create(&as->p, NULL, async_wait, as)) { 03844 ast_log(LOG_WARNING, "Failed to start async wait\n"); 03845 free(as); 03846 ast_hangup(chan); 03847 return -1; 03848 } 03849 res = 0; 03850 } 03851 return res; 03852 } |
|
Execute the PBX in the current thread.
Definition at line 1637 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_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. Referenced by ast_pbx_outgoing_exten().
01638 { 01639 int firstpass = 1; 01640 char digit; 01641 char exten[256]; 01642 int pos; 01643 int waittime; 01644 int res=0; 01645 01646 /* A little initial setup here */ 01647 if (c->pbx) 01648 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 01649 c->pbx = malloc(sizeof(struct ast_pbx)); 01650 if (!c->pbx) { 01651 ast_log(LOG_WARNING, "Out of memory\n"); 01652 return -1; 01653 } 01654 if (c->amaflags) { 01655 if (c->cdr) { 01656 ast_log(LOG_WARNING, "%s already has a call record??\n", c->name); 01657 } else { 01658 c->cdr = ast_cdr_alloc(); 01659 if (!c->cdr) { 01660 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n"); 01661 free(c->pbx); 01662 return -1; 01663 } 01664 ast_cdr_init(c->cdr, c); 01665 } 01666 } 01667 memset(c->pbx, 0, sizeof(struct ast_pbx)); 01668 /* Set reasonable defaults */ 01669 c->pbx->rtimeout = 10; 01670 c->pbx->dtimeout = 5; 01671 01672 /* Start by trying whatever the channel is set to */ 01673 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) { 01674 /* JK02: If not successfull fall back to 's' */ 01675 strncpy(c->exten, "s", sizeof(c->exten)-1); 01676 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) { 01677 /* JK02: And finally back to default if everything else failed */ 01678 strncpy(c->context, "default", sizeof(c->context)-1); 01679 } 01680 c->priority = 1; 01681 } 01682 if (c->cdr) 01683 ast_cdr_start(c->cdr); 01684 for(;;) { 01685 pos = 0; 01686 digit = 0; 01687 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) { 01688 memset(exten, 0, sizeof(exten)); 01689 manager_event(EVENT_FLAG_CALL, "Newexten", 01690 "Channel: %s\r\n" 01691 "Context: %s\r\n" 01692 "Extension: %s\r\n" 01693 "Priority: %d\r\n" 01694 "Uniqueid: %s\r\n", 01695 c->name, c->context, c->exten, c->priority, c->uniqueid); 01696 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) { 01697 /* Something bad happened, or a hangup has been requested. */ 01698 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) || 01699 (res == '*') || (res == '#')) { 01700 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res); 01701 memset(exten, 0, sizeof(exten)); 01702 pos = 0; 01703 exten[pos++] = digit = res; 01704 break; 01705 } 01706 switch(res) { 01707 case AST_PBX_KEEPALIVE: 01708 if (option_debug) 01709 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 01710 else if (option_verbose > 1) 01711 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 01712 goto out; 01713 break; 01714 default: 01715 if (option_debug) 01716 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 01717 else if (option_verbose > 1) 01718 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 01719 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 01720 c->_softhangup =0; 01721 break; 01722 } 01723 /* atimeout */ 01724 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 01725 break; 01726 } 01727 goto out; 01728 } 01729 } 01730 if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->callerid))) { 01731 strncpy(c->exten,"T",sizeof(c->exten) - 1); 01732 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 01733 c->whentohangup = 0; 01734 c->priority = 0; 01735 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 01736 } else if (c->_softhangup) { 01737 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n", 01738 c->exten, c->priority); 01739 goto out; 01740 } 01741 firstpass = 0; 01742 c->priority++; 01743 } 01744 if (!ast_exists_extension(c, c->context, c->exten, 1, c->callerid)) { 01745 /* It's not a valid extension anymore */ 01746 if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) { 01747 if (option_verbose > 2) 01748 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 01749 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 01750 strncpy(c->exten, "i", sizeof(c->exten)-1); 01751 c->priority = 1; 01752 } else { 01753 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 01754 c->name, c->exten, c->context); 01755 goto out; 01756 } 01757 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 01758 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 01759 c->_softhangup = 0; 01760 } else { 01761 /* Done, wait for an extension */ 01762 if (digit) 01763 waittime = c->pbx->dtimeout; 01764 else 01765 waittime = c->pbx->rtimeout; 01766 while (ast_matchmore_extension(c, c->context, exten, 1, c->callerid)) { 01767 /* As long as we're willing to wait, and as long as it's not defined, 01768 keep reading digits until we can't possibly get a right answer anymore. */ 01769 digit = ast_waitfordigit(c, waittime * 1000); 01770 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 01771 c->_softhangup = 0; 01772 } else { 01773 if (!digit) 01774 /* No entry */ 01775 break; 01776 if (digit < 0) 01777 /* Error, maybe a hangup */ 01778 goto out; 01779 exten[pos++] = digit; 01780 waittime = c->pbx->dtimeout; 01781 } 01782 } 01783 if (ast_exists_extension(c, c->context, exten, 1, c->callerid)) { 01784 /* Prepare the next cycle */ 01785 strncpy(c->exten, exten, sizeof(c->exten)-1); 01786 c->priority = 1; 01787 } else { 01788 /* No such extension */ 01789 if (strlen(exten)) { 01790 /* An invalid extension */ 01791 if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) { 01792 if (option_verbose > 2) 01793 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name); 01794 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten); 01795 strncpy(c->exten, "i", sizeof(c->exten)-1); 01796 c->priority = 1; 01797 } else { 01798 ast_log(LOG_WARNING, "Invalid extension, but no rule 'i' in context '%s'\n", c->context); 01799 goto out; 01800 } 01801 } else { 01802 /* A simple timeout */ 01803 if (ast_exists_extension(c, c->context, "t", 1, c->callerid)) { 01804 if (option_verbose > 2) 01805 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name); 01806 strncpy(c->exten, "t", sizeof(c->exten)-1); 01807 c->priority = 1; 01808 } else { 01809 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); 01810 goto out; 01811 } 01812 } 01813 } 01814 if (c->cdr) { 01815 if (option_verbose > 2) 01816 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name); 01817 ast_cdr_update(c); 01818 } 01819 } 01820 } 01821 if (firstpass) 01822 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 01823 out: 01824 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->callerid)) { 01825 strcpy(c->exten, "h"); 01826 c->priority = 1; 01827 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) { 01828 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) { 01829 /* Something bad happened, or a hangup has been requested. */ 01830 if (option_debug) 01831 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 01832 else if (option_verbose > 1) 01833 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 01834 break; 01835 } 01836 c->priority++; 01837 } 01838 } 01839 01840 pbx_destroy(c->pbx); 01841 c->pbx = NULL; 01842 if (res != AST_PBX_KEEPALIVE) 01843 ast_hangup(c); 01844 return 0; 01845 } |
|
Create a new thread and start the PBX (or whatever).
Definition at line 1860 of file pbx.c. References ast_log(), and LOG_WARNING. Referenced by ast_async_goto(), and ast_pbx_outgoing_exten().
01861 { 01862 pthread_t t; 01863 pthread_attr_t attr; 01864 if (!c) { 01865 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 01866 return -1; 01867 } 01868 01869 /* Start a new thread, and get something handling this channel. */ 01870 pthread_attr_init(&attr); 01871 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 01872 if (pthread_create(&t, &attr, pbx_thread, c)) { 01873 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 01874 return -1; 01875 } 01876 return 0; 01877 } |
|
Add an application. The function 'execute' should return non-zero if the line needs to be hung up.
Definition at line 2168 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), COLOR_BRCYAN, description(), LOG_ERROR, LOG_WARNING, malloc, ast_app::next, option_verbose, term_color(), and VERBOSE_PREFIX_2. Referenced by load_pbx().
02169 { 02170 struct ast_app *tmp, *prev, *cur; 02171 char tmps[80]; 02172 if (ast_mutex_lock(&applock)) { 02173 ast_log(LOG_ERROR, "Unable to lock application list\n"); 02174 return -1; 02175 } 02176 tmp = apps; 02177 while(tmp) { 02178 if (!strcasecmp(app, tmp->name)) { 02179 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 02180 ast_mutex_unlock(&applock); 02181 return -1; 02182 } 02183 tmp = tmp->next; 02184 } 02185 tmp = malloc(sizeof(struct ast_app)); 02186 if (tmp) { 02187 memset(tmp, 0, sizeof(struct ast_app)); 02188 strncpy(tmp->name, app, sizeof(tmp->name)-1); 02189 tmp->execute = execute; 02190 tmp->synopsis = synopsis; 02191 tmp->description = description; 02192 /* Store in alphabetical order */ 02193 cur = apps; 02194 prev = NULL; 02195 while(cur) { 02196 if (strcasecmp(tmp->name, cur->name) < 0) 02197 break; 02198 prev = cur; 02199 cur = cur->next; 02200 } 02201 if (prev) { 02202 tmp->next = prev->next; 02203 prev->next = tmp; 02204 } else { 02205 tmp->next = apps; 02206 apps = tmp; 02207 } 02208 } else { 02209 ast_log(LOG_WARNING, "Out of memory\n"); 02210 ast_mutex_unlock(&applock); 02211 return -1; 02212 } 02213 if (option_verbose > 1) 02214 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 02215 ast_mutex_unlock(&applock); 02216 return 0; 02217 } |
|
Register an alternative switch.
Definition at line 2219 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.
02220 { 02221 struct ast_switch *tmp, *prev=NULL; 02222 if (ast_mutex_lock(&switchlock)) { 02223 ast_log(LOG_ERROR, "Unable to lock switch lock\n"); 02224 return -1; 02225 } 02226 tmp = switches; 02227 while(tmp) { 02228 if (!strcasecmp(tmp->name, sw->name)) 02229 break; 02230 prev = tmp; 02231 tmp = tmp->next; 02232 } 02233 if (tmp) { 02234 ast_mutex_unlock(&switchlock); 02235 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 02236 return -1; 02237 } 02238 sw->next = NULL; 02239 if (prev) 02240 prev->next = sw; 02241 else 02242 switches = sw; 02243 ast_mutex_unlock(&switchlock); 02244 return 0; 02245 } |
|
Launch a new extension (i.e. new stack).
Definition at line 1632 of file pbx.c. References HELPER_SPAWN. Referenced by ast_pbx_run().
01633 {
01634 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN);
01635 }
|
|
Unlocks the given context.
Definition at line 4489 of file pbx.c. References ast_mutex_unlock, and ast_context::lock.
04490 { 04491 return ast_mutex_unlock(&con->lock); 04492 } |
|
Unlocks contexts. Returns 0 on success, -1 on failure Definition at line 4476 of file pbx.c. References ast_mutex_unlock. Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().
04477 { 04478 return ast_mutex_unlock(&conlock); 04479 } |
|
Remove an application.
Definition at line 2699 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), LOG_ERROR, ast_app::next, option_verbose, and VERBOSE_PREFIX_2.
02699 { 02700 struct ast_app *tmp, *tmpl = NULL; 02701 if (ast_mutex_lock(&applock)) { 02702 ast_log(LOG_ERROR, "Unable to lock application list\n"); 02703 return -1; 02704 } 02705 tmp = apps; 02706 while(tmp) { 02707 if (!strcasecmp(app, tmp->name)) { 02708 if (tmpl) 02709 tmpl->next = tmp->next; 02710 else 02711 apps = tmp->next; 02712 if (option_verbose > 1) 02713 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name); 02714 ast_mutex_unlock(&applock); 02715 return 0; 02716 } 02717 tmpl = tmp; 02718 tmp = tmp->next; 02719 } 02720 ast_mutex_unlock(&applock); 02721 return -1; 02722 } |
|
Unregister an alternative switch.
Definition at line 2247 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_ERROR, ast_switch::next, and switches.
02248 { 02249 struct ast_switch *tmp, *prev=NULL; 02250 if (ast_mutex_lock(&switchlock)) { 02251 ast_log(LOG_ERROR, "Unable to lock switch lock\n"); 02252 return; 02253 } 02254 tmp = switches; 02255 while(tmp) { 02256 if (tmp == sw) { 02257 if (prev) 02258 prev->next = tmp->next; 02259 else 02260 switches = tmp->next; 02261 tmp->next = NULL; 02262 break; 02263 } 02264 prev = tmp; 02265 tmp = tmp->next; 02266 } 02267 ast_mutex_unlock(&switchlock); 02268 } |
|
Definition at line 4581 of file pbx.c. References ast_exten::next, and ast_context::root.
|
|
Definition at line 4617 of file pbx.c. References ast_context::ignorepats, and ast_ignorepat::next.
04619 { 04620 if (!ip) 04621 return con ? con->ignorepats : NULL; 04622 else 04623 return ip->next; 04624 } |
|
Definition at line 4608 of file pbx.c. References ast_context::includes, and ast_include::next.
|
|
Definition at line 4590 of file pbx.c. References ast_context::alts, and ast_sw::next.
|
|
Definition at line 4573 of file pbx.c. References ast_context::next. Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().
04574 { 04575 if (!con) 04576 return contexts; 04577 else 04578 return con->next; 04579 } |
|
Definition at line 4599 of file pbx.c. References ast_exten::peer.
04601 { 04602 if (!priority) 04603 return exten; 04604 else 04605 return priority->peer; 04606 } |
|
Definition at line 4445 of file pbx.c. References ast_cli_register(), ast_log(), ast_register_application(), ast_verbose(), description(), LOG_ERROR, option_verbose, and VERBOSE_PREFIX_1. Referenced by main().
04446 { 04447 int x; 04448 /* Initialize the PBX */ 04449 if (option_verbose) { 04450 ast_verbose( "Asterisk PBX Core Initializing\n"); 04451 ast_verbose( "Registering builtin applications:\n"); 04452 } 04453 ast_cli_register(&show_applications_cli); 04454 ast_cli_register(&show_application_cli); 04455 ast_cli_register(&show_dialplan_cli); 04456 ast_cli_register(&show_switches_cli); 04457 for (x=0;x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) { 04458 if (option_verbose) 04459 ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name); 04460 if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) { 04461 ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name); 04462 return -1; 04463 } 04464 } 04465 return 0; 04466 } |
|
Definition at line 4369 of file pbx.c. References AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_REMOVE_HEAD, and ast_var_delete().
04370 { 04371 struct ast_var_t *vardata; 04372 while (!AST_LIST_EMPTY(&globals)) { 04373 vardata = AST_LIST_FIRST(&globals); 04374 AST_LIST_REMOVE_HEAD(&globals, entries); 04375 ast_var_delete(vardata); 04376 } 04377 } |
|
Definition at line 4271 of file pbx.c. References AST_LIST_TRAVERSE, ast_var_name(), and ast_var_value().
04271 { 04272 struct ast_var_t *variables; 04273 struct varshead *headp; 04274 04275 if (chan) 04276 headp=&chan->varshead; 04277 else 04278 headp=&globals; 04279 04280 if (name) { 04281 AST_LIST_TRAVERSE(headp,variables,entries) { 04282 if (!strcmp(name, ast_var_name(variables))) 04283 return ast_var_value(variables); 04284 } 04285 if (headp != &globals) { 04286 /* Check global variables if we haven't already */ 04287 headp = &globals; 04288 AST_LIST_TRAVERSE(headp,variables,entries) { 04289 if (!strcmp(name, ast_var_name(variables))) 04290 return ast_var_value(variables); 04291 } 04292 } 04293 } 04294 return NULL; 04295 } |
|
Definition at line 4297 of file pbx.c. References AST_LIST_INSERT_HEAD, AST_LIST_REMOVE, AST_LIST_TRAVERSE, ast_var_assign(), ast_var_delete(), ast_var_name(), ast_verbose(), option_verbose, and VERBOSE_PREFIX_3.
04297 { 04298 struct ast_var_t *newvariable; 04299 struct varshead *headp; 04300 if (chan) 04301 headp=&chan->varshead; 04302 else 04303 headp=&globals; 04304 04305 AST_LIST_TRAVERSE (headp,newvariable,entries) { 04306 if (strcasecmp(ast_var_name(newvariable),name)==0) { 04307 /* there is already such a variable, delete it */ 04308 AST_LIST_REMOVE(headp,newvariable,ast_var_t,entries); 04309 ast_var_delete(newvariable); 04310 break; 04311 } 04312 } 04313 04314 if (value) { 04315 if ((option_verbose > 1) && (headp == &globals)) 04316 ast_verbose(VERBOSE_PREFIX_3 "Setting global variable '%s' to '%s'\n",name, value); 04317 newvariable=ast_var_assign(name,value); 04318 AST_LIST_INSERT_HEAD(headp,newvariable,entries); 04319 } 04320 } |
|
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 922 of file pbx.c. References ast_expr(), ast_log(), free, LOG_DEBUG, and LOG_NOTICE.
00923 { 00924 char *cp4; 00925 const char *tmp, *whereweare; 00926 int length; 00927 char workspace[256]; 00928 char ltmp[256], var[256]; 00929 char *nextvar, *nextexp; 00930 char *vars, *vare; 00931 int pos, brackets, needsub, len; 00932 00933 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be 00934 zero-filled */ 00935 whereweare=tmp=cp1; 00936 while(strlen(whereweare) && count) { 00937 /* Assume we're copying the whole remaining string */ 00938 pos = strlen(whereweare); 00939 00940 /* Look for a variable */ 00941 nextvar = strstr(whereweare, "${"); 00942 00943 nextexp = strstr(whereweare, "$["); 00944 00945 if (nextvar && nextexp) { 00946 if (nextvar < nextexp) 00947 nextexp = NULL; 00948 else 00949 nextvar = NULL; 00950 } 00951 00952 /* If there is one, we only go that far */ 00953 if (nextvar) 00954 pos = nextvar - whereweare; 00955 else if (nextexp) 00956 pos = nextexp - whereweare; 00957 00958 /* Can't copy more than 'count' bytes */ 00959 if (pos > count) 00960 pos = count; 00961 00962 /* Copy that many bytes */ 00963 memcpy(cp2, whereweare, pos); 00964 00965 count -= pos; 00966 cp2 += pos; 00967 whereweare += pos; 00968 00969 if (nextvar) { 00970 /* We have a variable. Find the start and end, and determine 00971 if we are going to have to recursively call ourselves on the 00972 contents */ 00973 vars = vare = nextvar + 2; 00974 brackets = 1; 00975 needsub = 0; 00976 00977 /* Find the end of it */ 00978 while(brackets && *vare) { 00979 if ((vare[0] == '$') && (vare[1] == '{')) { 00980 needsub++; 00981 brackets++; 00982 } else if (vare[0] == '}') { 00983 brackets--; 00984 } else if ((vare[0] == '$') && (vare[1] == '[')) 00985 needsub++; 00986 vare++; 00987 } 00988 if (brackets) 00989 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n"); 00990 len = vare - vars - 1; 00991 00992 /* Skip totally over variable name */ 00993 whereweare += ( len + 3); 00994 00995 /* Store variable name (and truncate) */ 00996 memset(var, 0, sizeof(var)); 00997 strncpy(var, vars, sizeof(var) - 1); 00998 var[len] = '\0'; 00999 01000 /* Substitute if necessary */ 01001 if (needsub) { 01002 memset(ltmp, 0, sizeof(ltmp)); 01003 pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1); 01004 vars = ltmp; 01005 } else { 01006 vars = var; 01007 } 01008 01009 /* Retrieve variable value */ 01010 strcpy(workspace, ""); 01011 pbx_substitute_variables_temp(c,vars,&cp4, workspace, sizeof(workspace)); 01012 if (cp4) { 01013 length = strlen(cp4); 01014 if (length > count) 01015 length = count; 01016 memcpy(cp2, cp4, length); 01017 count -= length; 01018 cp2 += length; 01019 } 01020 01021 } else if (nextexp) { 01022 /* We have an expression. Find the start and end, and determine 01023 if we are going to have to recursively call ourselves on the 01024 contents */ 01025 vars = vare = nextexp + 2; 01026 brackets = 1; 01027 needsub = 0; 01028 01029 /* Find the end of it */ 01030 while(brackets && *vare) { 01031 if ((vare[0] == '$') && (vare[1] == '[')) { 01032 needsub++; 01033 brackets++; 01034 } else if (vare[0] == ']') { 01035 brackets--; 01036 } else if ((vare[0] == '$') && (vare[1] == '{')) 01037 needsub++; 01038 vare++; 01039 } 01040 if (brackets) 01041 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n"); 01042 len = vare - vars - 1; 01043 01044 /* Skip totally over variable name */ 01045 whereweare += ( len + 3); 01046 01047 /* Store variable name (and truncate) */ 01048 memset(var, 0, sizeof(var)); 01049 strncpy(var, vars, sizeof(var) - 1); 01050 var[len] = '\0'; 01051 01052 /* Substitute if necessary */ 01053 if (needsub) { 01054 memset(ltmp, 0, sizeof(ltmp)); 01055 pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1); 01056 vars = ltmp; 01057 } else { 01058 vars = var; 01059 } 01060 01061 /* Evaluate expression */ 01062 cp4 = ast_expr(vars); 01063 01064 ast_log(LOG_DEBUG, "Expression is '%s'\n", cp4); 01065 01066 if (cp4) { 01067 length = strlen(cp4); 01068 if (length > count) 01069 length = count; 01070 memcpy(cp2, cp4, length); 01071 count -= length; 01072 cp2 += length; 01073 free(cp4); 01074 } 01075 01076 } else 01077 break; 01078 } 01079 } |
|
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(). |