#include <asterisk/sched.h>
#include <asterisk/channel.h>
Go to the source code of this file.
Defines | |
#define | AST_PBX_KEEP 0 |
#define | AST_PBX_REPLACE 1 |
#define | AST_MAX_APP 32 |
Max length of an application. | |
#define | AST_PBX_KEEPALIVE 10 |
Special return values from applications to the PBX. | |
#define | AST_PBX_NO_HANGUP_PEER 11 |
#define | PRIORITY_HINT -1 |
Special Priority for an hint. | |
#define | AST_EXTENSION_NOT_INUSE 0 |
#define | AST_EXTENSION_INUSE 1 |
One or more devices INUSE. | |
#define | AST_EXTENSION_BUSY 2 |
All devices BUSY. | |
#define | AST_EXTENSION_UNAVAILABLE 3 |
All devices UNAVAILABLE/UNREGISTERED. | |
#define | AST_EXTENSION_RINGING 4 |
One ore more devices RINGING. | |
Typedefs | |
typedef int(* | ast_state_cb_type )(char *context, char *id, int state, void *data) |
Functions | |
int | ast_register_switch (struct ast_switch *sw) |
Register an alternative switch. | |
void | ast_unregister_switch (struct ast_switch *sw) |
Unregister an alternative switch. | |
ast_app * | pbx_findapp (char *app) |
Look up an application. | |
void * | ast_pbx_run_app (void *data) |
int | pbx_exec (struct ast_channel *c, struct ast_app *app, void *data, int newstack) |
executes an application | |
ast_context * | ast_context_create (struct ast_context **extcontexts, char *name, char *registrar) |
Register a new context. | |
void | ast_merge_contexts_and_delete (struct ast_context **extcontexts, char *registrar) |
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added. | |
void | ast_context_destroy (struct ast_context *con, char *registrar) |
Destroy a context (matches the specified context (or ANY context if NULL). | |
ast_context * | ast_context_find (char *name) |
Find a context. | |
int | ast_pbx_start (struct ast_channel *c) |
Create a new thread and start the PBX (or whatever). | |
int | ast_pbx_run (struct ast_channel *c) |
Execute the PBX in the current thread. | |
int | ast_add_extension (char *context, int replace, char *extension, int priority, char *callerid, char *application, void *data, void(*datad)(void *), char *registrar) |
int | ast_add_extension2 (struct ast_context *con, int replace, char *extension, int priority, char *callerid, char *application, void *data, void(*datad)(void *), char *registrar) |
Add an extension to an extension context, this time with an ast_context *. CallerID is a pattern to match on callerid, or NULL to not care about callerid. | |
int | ast_register_application (char *app, int(*execute)(struct ast_channel *, void *), char *synopsis, char *description) |
Add an application. The function 'execute' should return non-zero if the line needs to be hung up. | |
int | ast_unregister_application (char *app) |
Remove an application. | |
int | ast_extension_state (struct ast_channel *c, char *context, char *exten) |
Uses hint and devicestate callback to get the state of an extension. | |
int | ast_device_state_changed (const char *fmt,...) __attribute__((format(printf |
Tells Asterisk the State for Device is changed. | |
int int | ast_extension_state_add (char *context, char *exten, ast_state_cb_type callback, void *data) |
Registers a state change callback. | |
int | ast_extension_state_del (int id, ast_state_cb_type callback) |
Deletes a registered state change callback by ID. | |
int | ast_get_hint (char *hint, int maxlen, struct ast_channel *c, char *context, char *exten) |
If an extension exists, return non-zero. | |
int | ast_exists_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid) |
If an extension exists, return non-zero. | |
int | ast_canmatch_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid) |
Looks for a valid matching extension. | |
int | ast_matchmore_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid) |
Looks to see if adding anything to this extension might match something. (exists ^ canmatch). | |
int | ast_extension_match (char *pattern, char *extension) |
Determine if a given extension matches a given pattern (in NXX format). | |
int | ast_spawn_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid) |
Launch a new extension (i.e. new stack). | |
int | ast_exec_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid) |
Execute an extension. | |
int | ast_context_add_include (char *context, char *include, char *registrar) |
Add an include. | |
int | ast_context_add_include2 (struct ast_context *con, char *include, char *registrar) |
Add an include. | |
int | ast_context_remove_include (char *context, char *include, char *registrar) |
Removes an include. | |
int | ast_context_remove_include2 (struct ast_context *con, char *include, char *registrar) |
Removes an include by an ast_context structure. | |
int | ast_context_verify_includes (struct ast_context *con) |
Verifies includes in an ast_contect structure. | |
int | ast_context_add_switch (char *context, char *sw, char *data, char *registrar) |
Add a switch. | |
int | ast_context_add_switch2 (struct ast_context *con, char *sw, char *data, char *registrar) |
Adds a switch (first param is a ast_context). | |
int | ast_context_remove_switch (char *context, char *sw, char *data, char *registrar) |
Remove a switch. | |
int | ast_context_remove_switch2 (struct ast_context *con, char *sw, char *data, char *registrar) |
int | ast_context_remove_extension (char *context, char *extension, int priority, char *registrar) |
Simply remove extension from context. | |
int | ast_context_remove_extension2 (struct ast_context *con, char *extension, int priority, char *registrar) |
int | ast_context_add_ignorepat (char *context, char *ignorepat, char *registrar) |
Add an ignorepat. | |
int | ast_context_add_ignorepat2 (struct ast_context *con, char *ignorepat, char *registrar) |
int | ast_context_remove_ignorepat (char *context, char *ignorepat, char *registrar) |
int | ast_context_remove_ignorepat2 (struct ast_context *con, char *ignorepat, char *registrar) |
int | ast_ignore_pattern (char *context, char *pattern) |
Checks to see if a number should be ignored. | |
int | ast_lock_contexts (void) |
Locks the contexts. | |
int | ast_unlock_contexts (void) |
Unlocks contexts. | |
int | ast_lock_context (struct ast_context *con) |
Locks a given context. | |
int | ast_unlock_context (struct ast_context *con) |
Unlocks the given context. | |
int | ast_async_goto (struct ast_channel *chan, char *context, char *exten, int priority) |
int | ast_async_goto_by_name (char *chan, char *context, char *exten, int priority) |
int | ast_pbx_outgoing_exten (char *type, int format, void *data, int timeout, char *context, char *exten, int priority, int *reason, int sync, int callingpres, char *callerid, char *variable, char *account, char *uniqueid) |
int | ast_pbx_outgoing_app (char *type, int format, void *data, int timeout, char *app, char *appdata, int *reason, int sync, char *callerid, char *variable, char *account, char *uniqueid) |
char * | ast_get_context_name (struct ast_context *con) |
char * | ast_get_extension_name (struct ast_exten *exten) |
char * | ast_get_include_name (struct ast_include *include) |
char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
char * | ast_get_switch_name (struct ast_sw *sw) |
char * | ast_get_switch_data (struct ast_sw *sw) |
int | ast_get_extension_priority (struct ast_exten *exten) |
int | ast_get_extension_matchcid (struct ast_exten *e) |
char * | ast_get_extension_cidmatch (struct ast_exten *e) |
char * | ast_get_extension_app (struct ast_exten *e) |
void * | ast_get_extension_app_data (struct ast_exten *e) |
char * | ast_get_context_registrar (struct ast_context *c) |
char * | ast_get_extension_registrar (struct ast_exten *e) |
char * | ast_get_include_registrar (struct ast_include *i) |
char * | ast_get_ignorepat_registrar (struct ast_ignorepat *ip) |
char * | ast_get_switch_registrar (struct ast_sw *sw) |
ast_context * | ast_walk_contexts (struct ast_context *con) |
ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *priority) |
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) |
ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
char * | pbx_builtin_getvar_helper (struct ast_channel *chan, char *name) |
void | pbx_builtin_setvar_helper (struct ast_channel *chan, char *name, char *value) |
void | pbx_builtin_clear_globals (void) |
int | pbx_builtin_setvar (struct ast_channel *chan, void *data) |
void | pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count) |
int | ast_extension_patmatch (const char *pattern, const char *data) |
|
All devices BUSY.
|
|
One or more devices INUSE.
|
|
Extension states No device INUSE or BUSY |
|
One ore more devices RINGING.
|
|
All devices UNAVAILABLE/UNREGISTERED.
|
|
Max length of an application.
|
|
|
|
Special return values from applications to the PBX.
Definition at line 30 of file pbx.h. Referenced by ast_pbx_run(). |
|
|
|
|
|
Special Priority for an hint.
Definition at line 34 of file pbx.h. Referenced by ast_add_extension2(), and ast_context_remove_extension2(). |
|
|
|
Definition at line 3667 of file pbx.c. References ast_add_extension2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts(). 03669 { 03670 struct ast_context *c; 03671 03672 if (ast_lock_contexts()) { 03673 errno = EBUSY; 03674 return -1; 03675 } 03676 03677 c = ast_walk_contexts(NULL); 03678 while (c) { 03679 if (!strcmp(context, ast_get_context_name(c))) { 03680 int ret = ast_add_extension2(c, replace, extension, priority, callerid, 03681 application, data, datad, registrar); 03682 ast_unlock_contexts(); 03683 return ret; 03684 } 03685 c = ast_walk_contexts(c); 03686 } 03687 03688 ast_unlock_contexts(); 03689 errno = ENOENT; 03690 return -1; 03691 }
|
|
Add an extension to an extension context, this time with an ast_context *. CallerID is a pattern to match on callerid, or NULL to not care about callerid. For details about the arguements, check ast_add_extension() Definition at line 3800 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_exten::cidmatch, ast_exten::data, ast_exten::datad, ast_exten::exten, free, ast_context::lock, LOG, LOG_ERROR, LOG_WARNING, malloc, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_exten::peer, ast_exten::priority, PRIORITY_HINT, ast_context::registrar, and ast_context::root. Referenced by ast_add_extension(). 03804 { 03805 03806 #define LOG do { if (option_debug) {\ 03807 if (tmp->matchcid) { \ 03808 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \ 03809 } else { \ 03810 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \ 03811 } \ 03812 } else if (option_verbose > 2) { \ 03813 if (tmp->matchcid) { \ 03814 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \ 03815 } else { \ 03816 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \ 03817 } \ 03818 } } while(0) 03819 03820 /* 03821 * This is a fairly complex routine. Different extensions are kept 03822 * in order by the extension number. Then, extensions of different 03823 * priorities (same extension) are kept in a list, according to the 03824 * peer pointer. 03825 */ 03826 struct ast_exten *tmp, *e, *el = NULL, *ep = NULL; 03827 int res; 03828 03829 /* Be optimistic: Build the extension structure first */ 03830 tmp = malloc(sizeof(struct ast_exten)); 03831 if (tmp) { 03832 memset(tmp, 0, sizeof(struct ast_exten)); 03833 ext_strncpy(tmp->exten, extension, sizeof(tmp->exten)); 03834 tmp->priority = priority; 03835 if (callerid) { 03836 ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch)); 03837 tmp->matchcid = 1; 03838 } else { 03839 tmp->cidmatch[0] = '\0'; 03840 tmp->matchcid = 0; 03841 } 03842 strncpy(tmp->app, application, sizeof(tmp->app)-1); 03843 tmp->parent = con; 03844 tmp->data = data; 03845 tmp->datad = datad; 03846 tmp->registrar = registrar; 03847 tmp->peer = NULL; 03848 tmp->next = NULL; 03849 } else { 03850 ast_log(LOG_ERROR, "Out of memory\n"); 03851 errno = ENOMEM; 03852 return -1; 03853 } 03854 if (ast_mutex_lock(&con->lock)) { 03855 free(tmp); 03856 /* And properly destroy the data */ 03857 datad(data); 03858 ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name); 03859 errno = EBUSY; 03860 return -1; 03861 } 03862 e = con->root; 03863 while(e) { 03864 /* Make sure patterns are always last! */ 03865 if ((e->exten[0] != '_') && (extension[0] == '_')) 03866 res = -1; 03867 else if ((e->exten[0] == '_') && (extension[0] != '_')) 03868 res = 1; 03869 else 03870 res= strcmp(e->exten, extension); 03871 if (!res) { 03872 if (!e->matchcid && !tmp->matchcid) 03873 res = 0; 03874 else if (tmp->matchcid && !e->matchcid) 03875 res = 1; 03876 else if (e->matchcid && !tmp->matchcid) 03877 res = -1; 03878 else 03879 res = strcasecmp(e->cidmatch, tmp->cidmatch); 03880 } 03881 if (res == 0) { 03882 /* We have an exact match, now we find where we are 03883 and be sure there's no duplicates */ 03884 while(e) { 03885 if (e->priority == tmp->priority) { 03886 /* Can't have something exactly the same. Is this a 03887 replacement? If so, replace, otherwise, bonk. */ 03888 if (replace) { 03889 if (ep) { 03890 /* We're in the peer list, insert ourselves */ 03891 ep->peer = tmp; 03892 tmp->peer = e->peer; 03893 } else if (el) { 03894 /* We're the first extension. Take over e's functions */ 03895 el->next = tmp; 03896 tmp->next = e->next; 03897 tmp->peer = e->peer; 03898 } else { 03899 /* We're the very first extension. */ 03900 con->root = tmp; 03901 tmp->next = e->next; 03902 tmp->peer = e->peer; 03903 } 03904 if (tmp->priority == PRIORITY_HINT) 03905 ast_change_hint(e,tmp); 03906 /* Destroy the old one */ 03907 e->datad(e->data); 03908 free(e); 03909 ast_mutex_unlock(&con->lock); 03910 if (tmp->priority == PRIORITY_HINT) 03911 ast_change_hint(e, tmp); 03912 /* And immediately return success. */ 03913 LOG; 03914 return 0; 03915 } else { 03916 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 03917 tmp->datad(tmp->data); 03918 free(tmp); 03919 ast_mutex_unlock(&con->lock); 03920 errno = EEXIST; 03921 return -1; 03922 } 03923 } else if (e->priority > tmp->priority) { 03924 /* Slip ourselves in just before e */ 03925 if (ep) { 03926 /* Easy enough, we're just in the peer list */ 03927 ep->peer = tmp; 03928 tmp->peer = e; 03929 } else if (el) { 03930 /* We're the first extension in this peer list */ 03931 el->next = tmp; 03932 tmp->next = e->next; 03933 e->next = NULL; 03934 tmp->peer = e; 03935 } else { 03936 /* We're the very first extension altogether */ 03937 tmp->next = con->root->next; 03938 /* Con->root must always exist or we couldn't get here */ 03939 tmp->peer = con->root; 03940 con->root = tmp; 03941 } 03942 ast_mutex_unlock(&con->lock); 03943 /* And immediately return success. */ 03944 if (tmp->priority == PRIORITY_HINT) 03945 ast_add_hint(tmp); 03946 03947 LOG; 03948 return 0; 03949 } 03950 ep = e; 03951 e = e->peer; 03952 } 03953 /* If we make it here, then it's time for us to go at the very end. 03954 ep *must* be defined or we couldn't have gotten here. */ 03955 ep->peer = tmp; 03956 ast_mutex_unlock(&con->lock); 03957 if (tmp->priority == PRIORITY_HINT) 03958 ast_add_hint(tmp); 03959 03960 /* And immediately return success. */ 03961 LOG; 03962 return 0; 03963 03964 } else if (res > 0) { 03965 /* Insert ourselves just before 'e'. We're the first extension of 03966 this kind */ 03967 tmp->next = e; 03968 if (el) { 03969 /* We're in the list somewhere */ 03970 el->next = tmp; 03971 } else { 03972 /* We're at the top of the list */ 03973 con->root = tmp; 03974 } 03975 ast_mutex_unlock(&con->lock); 03976 if (tmp->priority == PRIORITY_HINT) 03977 ast_add_hint(tmp); 03978 03979 /* And immediately return success. */ 03980 LOG; 03981 return 0; 03982 } 03983 03984 el = e; 03985 e = e->next; 03986 } 03987 /* If we fall all the way through to here, then we need to be on the end. */ 03988 if (el) 03989 el->next = tmp; 03990 else 03991 con->root = tmp; 03992 ast_mutex_unlock(&con->lock); 03993 if (tmp->priority == PRIORITY_HINT) 03994 ast_add_hint(tmp); 03995 LOG; 03996 return 0; 03997 }
|
|
Definition at line 3693 of file pbx.c. References ast_channel::_state, ast_channel_alloc(), ast_channel_masquerade(), ast_do_masquerade(), ast_hangup(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pbx_start(), 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(). 03694 { 03695 int res = 0; 03696 ast_mutex_lock(&chan->lock); 03697 03698 if (chan->pbx) { 03699 /* This channel is currently in the PBX */ 03700 if (context && !ast_strlen_zero(context)) 03701 strncpy(chan->context, context, sizeof(chan->context) - 1); 03702 if (exten && !ast_strlen_zero(exten)) 03703 strncpy(chan->exten, exten, sizeof(chan->context) - 1); 03704 if (priority) 03705 chan->priority = priority - 1; 03706 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 03707 } else { 03708 /* In order to do it when the channel doesn't really exist within 03709 the PBX, we have to make a new channel, masquerade, and start the PBX 03710 at the new location */ 03711 struct ast_channel *tmpchan; 03712 tmpchan = ast_channel_alloc(0); 03713 if (tmpchan) { 03714 snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name); 03715 ast_setstate(tmpchan, chan->_state); 03716 /* Make formats okay */ 03717 tmpchan->readformat = chan->readformat; 03718 tmpchan->writeformat = chan->writeformat; 03719 /* Setup proper location */ 03720 if (context && !ast_strlen_zero(context)) 03721 strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1); 03722 else 03723 strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1); 03724 if (exten && !ast_strlen_zero(exten)) 03725 strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1); 03726 else 03727 strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1); 03728 if (priority) 03729 tmpchan->priority = priority; 03730 else 03731 tmpchan->priority = chan->priority; 03732 03733 /* Masquerade into temp channel */ 03734 ast_channel_masquerade(tmpchan, chan); 03735 03736 /* Grab the locks and get going */ 03737 ast_mutex_lock(&tmpchan->lock); 03738 ast_do_masquerade(tmpchan); 03739 ast_mutex_unlock(&tmpchan->lock); 03740 /* Start the PBX going on our stolen channel */ 03741 if (ast_pbx_start(tmpchan)) { 03742 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 03743 ast_hangup(tmpchan); 03744 res = -1; 03745 } 03746 } else { 03747 res = -1; 03748 } 03749 } 03750 ast_mutex_unlock(&chan->lock); 03751 return res; 03752 }
|
|
Definition at line 3754 of file pbx.c. References ast_async_goto(), ast_channel_walk_locked(), ast_mutex_unlock, ast_channel::lock, and ast_channel::name. 03755 { 03756 struct ast_channel *chan; 03757 int res = -1; 03758 03759 chan = ast_channel_walk_locked(NULL); 03760 while(chan) { 03761 if (!strcasecmp(channame, chan->name)) 03762 break; 03763 ast_mutex_unlock(&chan->lock); 03764 chan = ast_channel_walk_locked(chan); 03765 } 03766 03767 if (chan) { 03768 res = ast_async_goto(chan, context, exten, priority); 03769 ast_mutex_unlock(&chan->lock); 03770 } 03771 return res; 03772 }
|
|
Looks for a valid matching extension.
Definition at line 1761 of file pbx.c. References HELPER_CANMATCH. 01762 { 01763 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH); 01764 }
|
|
Add an ignorepat.
Definition at line 3586 of file pbx.c. References ast_context_add_ignorepat2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts(). 03587 { 03588 struct ast_context *c; 03589 03590 if (ast_lock_contexts()) { 03591 errno = EBUSY; 03592 return -1; 03593 } 03594 03595 c = ast_walk_contexts(NULL); 03596 while (c) { 03597 if (!strcmp(ast_get_context_name(c), con)) { 03598 int ret = ast_context_add_ignorepat2(c, value, registrar); 03599 ast_unlock_contexts(); 03600 return ret; 03601 } 03602 c = ast_walk_contexts(c); 03603 } 03604 03605 ast_unlock_contexts(); 03606 errno = ENOENT; 03607 return -1; 03608 }
|
|
Definition at line 3610 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_context::ignorepats, ast_context::lock, LOG_ERROR, malloc, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar. Referenced by ast_context_add_ignorepat(). 03611 { 03612 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 03613 03614 ignorepat = malloc(sizeof(struct ast_ignorepat)); 03615 if (!ignorepat) { 03616 ast_log(LOG_ERROR, "Out of memory\n"); 03617 errno = ENOMEM; 03618 return -1; 03619 } 03620 memset(ignorepat, 0, sizeof(struct ast_ignorepat)); 03621 strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1); 03622 ignorepat->next = NULL; 03623 ignorepat->registrar = registrar; 03624 ast_mutex_lock(&con->lock); 03625 ignorepatc = con->ignorepats; 03626 while(ignorepatc) { 03627 ignorepatl = ignorepatc; 03628 if (!strcasecmp(ignorepatc->pattern, value)) { 03629 /* Already there */ 03630 ast_mutex_unlock(&con->lock); 03631 errno = EEXIST; 03632 return -1; 03633 } 03634 ignorepatc = ignorepatc->next; 03635 } 03636 if (ignorepatl) 03637 ignorepatl->next = ignorepat; 03638 else 03639 con->ignorepats = ignorepat; 03640 ast_mutex_unlock(&con->lock); 03641 return 0; 03642 03643 }
|
|
Add an include.
Definition at line 3047 of file pbx.c. References ast_context_add_include2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts(). 03048 { 03049 struct ast_context *c; 03050 03051 if (ast_lock_contexts()) { 03052 errno = EBUSY; 03053 return -1; 03054 } 03055 03056 /* walk contexts ... */ 03057 c = ast_walk_contexts(NULL); 03058 while (c) { 03059 /* ... search for the right one ... */ 03060 if (!strcmp(ast_get_context_name(c), context)) { 03061 int ret = ast_context_add_include2(c, include, registrar); 03062 /* ... unlock contexts list and return */ 03063 ast_unlock_contexts(); 03064 return ret; 03065 } 03066 c = ast_walk_contexts(c); 03067 } 03068 03069 /* we can't find the right context */ 03070 ast_unlock_contexts(); 03071 errno = ENOENT; 03072 return -1; 03073 }
|
|
Add an include.
Definition at line 3367 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_ERROR, malloc, ast_include::name, ast_include::next, option_verbose, ast_include::registrar, ast_include::rname, and VERBOSE_PREFIX_3. Referenced by ast_context_add_include(). 03369 { 03370 struct ast_include *new_include; 03371 char *c; 03372 struct ast_include *i, *il = NULL; /* include, include_last */ 03373 03374 /* allocate new include structure ... */ 03375 if (!(new_include = malloc(sizeof(struct ast_include)))) { 03376 ast_log(LOG_ERROR, "Out of memory\n"); 03377 errno = ENOMEM; 03378 return -1; 03379 } 03380 03381 /* ... fill in this structure ... */ 03382 memset(new_include, 0, sizeof(struct ast_include)); 03383 strncpy(new_include->name, value, sizeof(new_include->name)-1); 03384 strncpy(new_include->rname, value, sizeof(new_include->rname)-1); 03385 c = new_include->rname; 03386 /* Strip off timing info */ 03387 while(*c && (*c != '|')) c++; 03388 /* Process if it's there */ 03389 if (*c) { 03390 build_timing(new_include, c+1); 03391 *c = '\0'; 03392 } 03393 new_include->next = NULL; 03394 new_include->registrar = registrar; 03395 03396 /* ... try to lock this context ... */ 03397 if (ast_mutex_lock(&con->lock)) { 03398 free(new_include); 03399 errno = EBUSY; 03400 return -1; 03401 } 03402 03403 /* ... go to last include and check if context is already included too... */ 03404 i = con->includes; 03405 while (i) { 03406 if (!strcasecmp(i->name, new_include->name)) { 03407 free(new_include); 03408 ast_mutex_unlock(&con->lock); 03409 errno = EEXIST; 03410 return -1; 03411 } 03412 il = i; 03413 i = i->next; 03414 } 03415 03416 /* ... include new context into context list, unlock, return */ 03417 if (il) 03418 il->next = new_include; 03419 else 03420 con->includes = new_include; 03421 if (option_verbose > 2) 03422 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 03423 ast_mutex_unlock(&con->lock); 03424 03425 return 0; 03426 }
|
|
Add a switch.
Definition at line 3433 of file pbx.c. References ast_context_add_switch2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts(). 03434 { 03435 struct ast_context *c; 03436 03437 if (ast_lock_contexts()) { 03438 errno = EBUSY; 03439 return -1; 03440 } 03441 03442 /* walk contexts ... */ 03443 c = ast_walk_contexts(NULL); 03444 while (c) { 03445 /* ... search for the right one ... */ 03446 if (!strcmp(ast_get_context_name(c), context)) { 03447 int ret = ast_context_add_switch2(c, sw, data, registrar); 03448 /* ... unlock contexts list and return */ 03449 ast_unlock_contexts(); 03450 return ret; 03451 } 03452 c = ast_walk_contexts(c); 03453 } 03454 03455 /* we can't find the right context */ 03456 ast_unlock_contexts(); 03457 errno = ENOENT; 03458 return -1; 03459 }
|
|
Adds a switch (first param is a ast_context). Definition at line 3468 of file pbx.c. References ast_context::alts, ast_get_context_name(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), ast_sw::data, free, ast_context::lock, LOG_ERROR, malloc, ast_sw::name, ast_sw::next, option_verbose, ast_sw::registrar, and VERBOSE_PREFIX_3. Referenced by ast_context_add_switch(). 03470 { 03471 struct ast_sw *new_sw; 03472 struct ast_sw *i, *il = NULL; /* sw, sw_last */ 03473 03474 /* allocate new sw structure ... */ 03475 if (!(new_sw = malloc(sizeof(struct ast_sw)))) { 03476 ast_log(LOG_ERROR, "Out of memory\n"); 03477 errno = ENOMEM; 03478 return -1; 03479 } 03480 03481 /* ... fill in this structure ... */ 03482 memset(new_sw, 0, sizeof(struct ast_sw)); 03483 strncpy(new_sw->name, value, sizeof(new_sw->name)-1); 03484 if (data) 03485 strncpy(new_sw->data, data, sizeof(new_sw->data)-1); 03486 else 03487 strncpy(new_sw->data, "", sizeof(new_sw->data)-1); 03488 new_sw->next = NULL; 03489 new_sw->registrar = registrar; 03490 03491 /* ... try to lock this context ... */ 03492 if (ast_mutex_lock(&con->lock)) { 03493 free(new_sw); 03494 errno = EBUSY; 03495 return -1; 03496 } 03497 03498 /* ... go to last sw and check if context is already swd too... */ 03499 i = con->alts; 03500 while (i) { 03501 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 03502 free(new_sw); 03503 ast_mutex_unlock(&con->lock); 03504 errno = EEXIST; 03505 return -1; 03506 } 03507 il = i; 03508 i = i->next; 03509 } 03510 03511 /* ... sw new context into context list, unlock, return */ 03512 if (il) 03513 il->next = new_sw; 03514 else 03515 con->alts = new_sw; 03516 if (option_verbose > 2) 03517 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 03518 ast_mutex_unlock(&con->lock); 03519 03520 return 0; 03521 }
|
|
Register a new context.
Definition at line 2970 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), ast_context::includes, LOG_DEBUG, LOG_ERROR, LOG_WARNING, malloc, ast_context::name, ast_context::next, option_debug, option_verbose, and VERBOSE_PREFIX_3. 02971 { 02972 struct ast_context *tmp, **local_contexts; 02973 if (!extcontexts) { 02974 local_contexts = &contexts; 02975 ast_mutex_lock(&conlock); 02976 } else 02977 local_contexts = extcontexts; 02978 02979 tmp = *local_contexts; 02980 while(tmp) { 02981 if (!strcasecmp(tmp->name, name)) { 02982 ast_mutex_unlock(&conlock); 02983 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name); 02984 if (!extcontexts) 02985 ast_mutex_unlock(&conlock); 02986 return NULL; 02987 } 02988 tmp = tmp->next; 02989 } 02990 tmp = malloc(sizeof(struct ast_context)); 02991 if (tmp) { 02992 memset(tmp, 0, sizeof(struct ast_context)); 02993 ast_mutex_init(&tmp->lock); 02994 strncpy(tmp->name, name, sizeof(tmp->name)-1); 02995 tmp->root = NULL; 02996 tmp->registrar = registrar; 02997 tmp->next = *local_contexts; 02998 tmp->includes = NULL; 02999 tmp->ignorepats = NULL; 03000 *local_contexts = tmp; 03001 if (option_debug) 03002 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name); 03003 else if (option_verbose > 2) 03004 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name); 03005 } else 03006 ast_log(LOG_ERROR, "Out of memory\n"); 03007 03008 if (!extcontexts) 03009 ast_mutex_unlock(&conlock); 03010 return tmp; 03011 }
|
|
Destroy a context (matches the specified context (or ANY context if NULL).
Definition at line 4356 of file pbx.c. References __ast_context_destroy(). 04357 { 04358 __ast_context_destroy(con,registrar); 04359 }
|
|
Find a context.
Definition at line 677 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, ast_context::name, and ast_context::next. Referenced by ast_context_verify_includes(), and ast_ignore_pattern(). 00678 { 00679 struct ast_context *tmp; 00680 ast_mutex_lock(&conlock); 00681 if (name) { 00682 tmp = contexts; 00683 while(tmp) { 00684 if (!strcasecmp(name, tmp->name)) 00685 break; 00686 tmp = tmp->next; 00687 } 00688 } else 00689 tmp = contexts; 00690 ast_mutex_unlock(&conlock); 00691 return tmp; 00692 }
|
|
Simply remove extension from context.
Definition at line 2169 of file pbx.c. References ast_context_remove_extension2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts(). 02170 { 02171 struct ast_context *c; 02172 02173 if (ast_lock_contexts()) return -1; 02174 02175 /* walk contexts ... */ 02176 c = ast_walk_contexts(NULL); 02177 while (c) { 02178 /* ... search for the right one ... */ 02179 if (!strcmp(ast_get_context_name(c), context)) { 02180 /* ... remove extension ... */ 02181 int ret = ast_context_remove_extension2(c, extension, priority, 02182 registrar); 02183 /* ... unlock contexts list and return */ 02184 ast_unlock_contexts(); 02185 return ret; 02186 } 02187 c = ast_walk_contexts(c); 02188 } 02189 02190 /* we can't find the right context */ 02191 ast_unlock_contexts(); 02192 return -1; 02193 }
|
|
Definition at line 2205 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, ast_exten::exten, free, ast_context::lock, ast_exten::next, ast_exten::peer, ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, and ast_context::root. Referenced by ast_context_remove_extension(). 02206 { 02207 struct ast_exten *exten, *prev_exten = NULL; 02208 02209 if (ast_mutex_lock(&con->lock)) return -1; 02210 02211 /* go through all extensions in context and search the right one ... */ 02212 exten = con->root; 02213 while (exten) { 02214 02215 /* look for right extension */ 02216 if (!strcmp(exten->exten, extension) && 02217 (!registrar || !strcmp(exten->registrar, registrar))) { 02218 struct ast_exten *peer; 02219 02220 /* should we free all peers in this extension? (priority == 0)? */ 02221 if (priority == 0) { 02222 /* remove this extension from context list */ 02223 if (prev_exten) 02224 prev_exten->next = exten->next; 02225 else 02226 con->root = exten->next; 02227 02228 /* fire out all peers */ 02229 peer = exten; 02230 while (peer) { 02231 exten = peer->peer; 02232 02233 if (!peer->priority==PRIORITY_HINT) 02234 ast_remove_hint(peer); 02235 02236 peer->datad(peer->data); 02237 free(peer); 02238 02239 peer = exten; 02240 } 02241 02242 ast_mutex_unlock(&con->lock); 02243 return 0; 02244 } else { 02245 /* remove only extension with exten->priority == priority */ 02246 struct ast_exten *previous_peer = NULL; 02247 02248 peer = exten; 02249 while (peer) { 02250 /* is this our extension? */ 02251 if (peer->priority == priority && 02252 (!registrar || !strcmp(peer->registrar, registrar) )) { 02253 /* we are first priority extension? */ 02254 if (!previous_peer) { 02255 /* exists previous extension here? */ 02256 if (prev_exten) { 02257 /* yes, so we must change next pointer in 02258 * previous connection to next peer 02259 */ 02260 if (peer->peer) { 02261 prev_exten->next = peer->peer; 02262 peer->peer->next = exten->next; 02263 } else 02264 prev_exten->next = exten->next; 02265 } else { 02266 /* no previous extension, we are first 02267 * extension, so change con->root ... 02268 */ 02269 if (peer->peer) 02270 con->root = peer->peer; 02271 else 02272 con->root = exten->next; 02273 } 02274 } else { 02275 /* we are not first priority in extension */ 02276 previous_peer->peer = peer->peer; 02277 } 02278 02279 /* now, free whole priority extension */ 02280 if (peer->priority==PRIORITY_HINT) 02281 ast_remove_hint(peer); 02282 peer->datad(peer->data); 02283 free(peer); 02284 02285 ast_mutex_unlock(&con->lock); 02286 return 0; 02287 } else { 02288 /* this is not right extension, skip to next peer */ 02289 previous_peer = peer; 02290 peer = peer->peer; 02291 } 02292 } 02293 02294 ast_mutex_unlock(&con->lock); 02295 return -1; 02296 } 02297 } 02298 02299 prev_exten = exten; 02300 exten = exten->next; 02301 } 02302 02303 /* we can't find right extension */ 02304 ast_mutex_unlock(&con->lock); 02305 return -1; 02306 }
|
|
Definition at line 3527 of file pbx.c. References ast_context_remove_ignorepat2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts(). 03528 { 03529 struct ast_context *c; 03530 03531 if (ast_lock_contexts()) { 03532 errno = EBUSY; 03533 return -1; 03534 } 03535 03536 c = ast_walk_contexts(NULL); 03537 while (c) { 03538 if (!strcmp(ast_get_context_name(c), context)) { 03539 int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 03540 ast_unlock_contexts(); 03541 return ret; 03542 } 03543 c = ast_walk_contexts(c); 03544 } 03545 03546 ast_unlock_contexts(); 03547 errno = ENOENT; 03548 return -1; 03549 }
|
|
Definition at line 3551 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, free, ast_context::ignorepats, ast_context::lock, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar. Referenced by ast_context_remove_ignorepat(). 03552 { 03553 struct ast_ignorepat *ip, *ipl = NULL; 03554 03555 if (ast_mutex_lock(&con->lock)) { 03556 errno = EBUSY; 03557 return -1; 03558 } 03559 03560 ip = con->ignorepats; 03561 while (ip) { 03562 if (!strcmp(ip->pattern, ignorepat) && 03563 (!registrar || (registrar == ip->registrar))) { 03564 if (ipl) { 03565 ipl->next = ip->next; 03566 free(ip); 03567 } else { 03568 con->ignorepats = ip->next; 03569 free(ip); 03570 } 03571 ast_mutex_unlock(&con->lock); 03572 return 0; 03573 } 03574 ipl = ip; ip = ip->next; 03575 } 03576 03577 ast_mutex_unlock(&con->lock); 03578 errno = EINVAL; 03579 return -1; 03580 }
|
|
Removes an include. See add_include Definition at line 2025 of file pbx.c. References ast_context_remove_include2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts(). 02026 { 02027 struct ast_context *c; 02028 02029 if (ast_lock_contexts()) return -1; 02030 02031 /* walk contexts and search for the right one ...*/ 02032 c = ast_walk_contexts(NULL); 02033 while (c) { 02034 /* we found one ... */ 02035 if (!strcmp(ast_get_context_name(c), context)) { 02036 int ret; 02037 /* remove include from this context ... */ 02038 ret = ast_context_remove_include2(c, include, registrar); 02039 02040 ast_unlock_contexts(); 02041 02042 /* ... return results */ 02043 return ret; 02044 } 02045 c = ast_walk_contexts(c); 02046 } 02047 02048 /* we can't find the right one context */ 02049 ast_unlock_contexts(); 02050 return -1; 02051 }
|
|
Removes an include by an ast_context structure. See add_include2 Definition at line 2061 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, free, ast_context::includes, ast_context::lock, ast_include::name, ast_include::next, and ast_include::registrar. Referenced by ast_context_remove_include(). 02062 { 02063 struct ast_include *i, *pi = NULL; 02064 02065 if (ast_mutex_lock(&con->lock)) return -1; 02066 02067 /* walk includes */ 02068 i = con->includes; 02069 while (i) { 02070 /* find our include */ 02071 if (!strcmp(i->name, include) && 02072 (!registrar || !strcmp(i->registrar, registrar))) { 02073 /* remove from list */ 02074 if (pi) 02075 pi->next = i->next; 02076 else 02077 con->includes = i->next; 02078 /* free include and return */ 02079 free(i); 02080 ast_mutex_unlock(&con->lock); 02081 return 0; 02082 } 02083 pi = i; 02084 i = i->next; 02085 } 02086 02087 /* we can't find the right include */ 02088 ast_mutex_unlock(&con->lock); 02089 return -1; 02090 }
|
|
Remove a switch. Removes a switch with the given parameters Returns 0 on success, -1 on failure Definition at line 2097 of file pbx.c. References ast_context_remove_switch2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts(). 02098 { 02099 struct ast_context *c; 02100 02101 if (ast_lock_contexts()) return -1; 02102 02103 /* walk contexts and search for the right one ...*/ 02104 c = ast_walk_contexts(NULL); 02105 while (c) { 02106 /* we found one ... */ 02107 if (!strcmp(ast_get_context_name(c), context)) { 02108 int ret; 02109 /* remove switch from this context ... */ 02110 ret = ast_context_remove_switch2(c, sw, data, registrar); 02111 02112 ast_unlock_contexts(); 02113 02114 /* ... return results */ 02115 return ret; 02116 } 02117 c = ast_walk_contexts(c); 02118 } 02119 02120 /* we can't find the right one context */ 02121 ast_unlock_contexts(); 02122 return -1; 02123 }
|
|
Definition at line 2133 of file pbx.c. References ast_context::alts, ast_mutex_lock, ast_mutex_unlock, ast_sw::data, free, ast_context::lock, ast_sw::name, ast_sw::next, and ast_sw::registrar. Referenced by ast_context_remove_switch(). 02134 { 02135 struct ast_sw *i, *pi = NULL; 02136 02137 if (ast_mutex_lock(&con->lock)) return -1; 02138 02139 /* walk switchs */ 02140 i = con->alts; 02141 while (i) { 02142 /* find our switch */ 02143 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 02144 (!registrar || !strcmp(i->registrar, registrar))) { 02145 /* remove from list */ 02146 if (pi) 02147 pi->next = i->next; 02148 else 02149 con->alts = i->next; 02150 /* free switch and return */ 02151 free(i); 02152 ast_mutex_unlock(&con->lock); 02153 return 0; 02154 } 02155 pi = i; 02156 i = i->next; 02157 } 02158 02159 /* we can't find the right switch */ 02160 ast_mutex_unlock(&con->lock); 02161 return -1; 02162 }
|
|
Verifies includes in an ast_contect structure.
Definition at line 5093 of file pbx.c. References ast_context_find(), ast_get_context_name(), ast_log(), ast_walk_context_includes(), LOG_WARNING, and ast_include::rname. 05094 { 05095 struct ast_include *inc; 05096 int res = 0; 05097 05098 for (inc = ast_walk_context_includes(con, NULL); inc; inc = ast_walk_context_includes(con, inc)) 05099 if (!ast_context_find(inc->rname)) { 05100 res = -1; 05101 ast_log(LOG_WARNING, "Context '%s' tries includes non-existant context '%s'\n", 05102 ast_get_context_name(con), inc->rname); 05103 } 05104 return res; 05105 }
|
|
Tells Asterisk the State for Device is changed.
|
|
Execute an extension.
|
|
If an extension exists, return non-zero.
Definition at line 1756 of file pbx.c. References HELPER_EXISTS. Referenced by ast_pbx_outgoing_exten(), and ast_pbx_run(). 01757 { 01758 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS); 01759 }
|
|
Determine if a given extension matches a given pattern (in NXX format).
Definition at line 644 of file pbx.c. References EXTENSION_MATCH_CORE. Referenced by ast_ignore_pattern(). 00645 { 00646 int match; 00647 /* If they're the same return */ 00648 if (!strcmp(pattern, data)) 00649 return 1; 00650 EXTENSION_MATCH_CORE(data,pattern,match); 00651 /* Must be at the end of both */ 00652 if (*data || (*pattern && (*pattern != '/'))) 00653 match = 0; 00654 return match; 00655 }
|
|
|
|
Uses hint and devicestate callback to get the state of an extension.
Definition at line 1430 of file pbx.c. 01431 { 01432 struct ast_exten *e; 01433 01434 e = ast_hint_extension(c, context, exten); 01435 if (!e) 01436 return -1; 01437 01438 return ast_extension_state2(e); 01439 }
|
|
Registers a state change callback.
Definition at line 1506 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, ast_state_cb::callback, ast_hint::callbacks, ast_state_cb::data, ast_hint::exten, ast_state_cb::id, malloc, ast_hint::next, and ast_state_cb::next. Referenced by init_manager(). 01508 { 01509 struct ast_hint *list; 01510 struct ast_state_cb *cblist; 01511 struct ast_exten *e; 01512 01513 /* No context and extension add callback to statecbs list */ 01514 if (!context && !exten) { 01515 ast_mutex_lock(&hintlock); 01516 01517 cblist = statecbs; 01518 while (cblist) { 01519 if (cblist->callback == callback) { 01520 cblist->data = data; 01521 ast_mutex_unlock(&hintlock); 01522 } 01523 cblist = cblist->next; 01524 } 01525 01526 /* Now inserts the callback */ 01527 cblist = malloc(sizeof(struct ast_state_cb)); 01528 if (!cblist) { 01529 ast_mutex_unlock(&hintlock); 01530 return -1; 01531 } 01532 memset(cblist, 0, sizeof(struct ast_state_cb)); 01533 cblist->id = 0; 01534 cblist->callback = callback; 01535 cblist->data = data; 01536 01537 cblist->next = statecbs; 01538 statecbs = cblist; 01539 01540 ast_mutex_unlock(&hintlock); 01541 return 0; 01542 } 01543 01544 if (!context || !exten) 01545 return -1; 01546 01547 /* This callback type is for only one hint */ 01548 e = ast_hint_extension(NULL, context, exten); 01549 if (!e) { 01550 return -1; 01551 } 01552 01553 ast_mutex_lock(&hintlock); 01554 list = hints; 01555 01556 while (list) { 01557 if (list->exten == e) 01558 break; 01559 list = list->next; 01560 } 01561 01562 if (!list) { 01563 ast_mutex_unlock(&hintlock); 01564 return -1; 01565 } 01566 01567 /* Now inserts the callback */ 01568 cblist = malloc(sizeof(struct ast_state_cb)); 01569 if (!cblist) { 01570 ast_mutex_unlock(&hintlock); 01571 return -1; 01572 } 01573 memset(cblist, 0, sizeof(struct ast_state_cb)); 01574 cblist->id = stateid++; 01575 cblist->callback = callback; 01576 cblist->data = data; 01577 01578 cblist->next = list->callbacks; 01579 list->callbacks = cblist; 01580 01581 ast_mutex_unlock(&hintlock); 01582 return cblist->id; 01583 }
|
|
Deletes a registered state change callback by ID.
Definition at line 1585 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, ast_hint::callbacks, free, ast_hint::next, and ast_state_cb::next. 01586 { 01587 struct ast_hint *list; 01588 struct ast_state_cb *cblist, *cbprev; 01589 01590 if (!id && !callback) 01591 return -1; 01592 01593 ast_mutex_lock(&hintlock); 01594 01595 /* id is zero is a callback without extension */ 01596 if (!id) { 01597 cbprev = NULL; 01598 cblist = statecbs; 01599 while (cblist) { 01600 if (cblist->callback == callback) { 01601 if (!cbprev) 01602 statecbs = cblist->next; 01603 else 01604 cbprev->next = cblist->next; 01605 01606 free(cblist); 01607 01608 ast_mutex_unlock(&hintlock); 01609 return 0; 01610 } 01611 cbprev = cblist; 01612 cblist = cblist->next; 01613 } 01614 01615 ast_mutex_lock(&hintlock); 01616 return -1; 01617 } 01618 01619 /* id greater than zero is a callback with extension */ 01620 list = hints; 01621 while (list) { 01622 cblist = list->callbacks; 01623 cbprev = NULL; 01624 while (cblist) { 01625 if (cblist->id==id) { 01626 if (!cbprev) 01627 list->callbacks = cblist->next; 01628 else 01629 cbprev->next = cblist->next; 01630 01631 free(cblist); 01632 01633 ast_mutex_unlock(&hintlock); 01634 return 0; 01635 } 01636 cbprev = cblist; 01637 cblist = cblist->next; 01638 } 01639 list = list->next; 01640 } 01641 01642 ast_mutex_unlock(&hintlock); 01643 return -1; 01644 }
|
|
Definition at line 4954 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(), ast_context_remove_switch(), and ast_context_verify_includes(). 04955 { 04956 return con ? con->name : NULL; 04957 }
|
|
Definition at line 4982 of file pbx.c. References ast_context::registrar. 04983 { 04984 return c ? c->registrar : NULL; 04985 }
|
|
Definition at line 5012 of file pbx.c. References ast_exten::app. Referenced by ast_device_state_changed(), and ast_get_hint(). 05013 { 05014 return e ? e->app : NULL; 05015 }
|
|
Definition at line 5017 of file pbx.c. References ast_exten::data. 05018 { 05019 return e ? e->data : NULL; 05020 }
|
|
Definition at line 5007 of file pbx.c. References ast_exten::cidmatch. 05008 { 05009 return e ? e->cidmatch : NULL; 05010 }
|
|
Definition at line 5002 of file pbx.c. References ast_exten::matchcid. 05003 { 05004 return e ? e->matchcid : 0; 05005 }
|
|
Definition at line 4959 of file pbx.c. References ast_exten::exten. 04960 { 04961 return exten ? exten->exten : NULL; 04962 }
|
|
Definition at line 4974 of file pbx.c. References ast_exten::priority. 04975 { 04976 return exten ? exten->priority : -1; 04977 }
|
|
Definition at line 4987 of file pbx.c. References ast_exten::registrar. 04988 { 04989 return e ? e->registrar : NULL; 04990 }
|
|
If an extension exists, return non-zero.
Definition at line 1745 of file pbx.c. References ast_get_extension_app(). 01746 { 01747 struct ast_exten *e; 01748 e = ast_hint_extension(c, context, exten); 01749 if (e) { 01750 strncpy(hint, ast_get_extension_app(e), hintsize - 1); 01751 return -1; 01752 } 01753 return 0; 01754 }
|
|
Definition at line 4969 of file pbx.c. References ast_ignorepat::pattern. 04970 { 04971 return ip ? ip->pattern : NULL; 04972 }
|
|
Definition at line 4997 of file pbx.c. References ast_ignorepat::registrar. 04998 { 04999 return ip ? ip->registrar : NULL; 05000 }
|
|
Definition at line 4964 of file pbx.c. References ast_include::name. 04965 {
04966 return inc ? inc->name : NULL;
04967 }
|
|
Definition at line 4992 of file pbx.c. References ast_include::registrar. 04993 { 04994 return i ? i->registrar : NULL; 04995 }
|
|
Definition at line 5027 of file pbx.c. References ast_sw::data. 05028 { 05029 return sw ? sw->data : NULL; 05030 }
|
|
Definition at line 5022 of file pbx.c. References ast_sw::name. 05023 { 05024 return sw ? sw->name : NULL; 05025 }
|
|
Definition at line 5032 of file pbx.c. References ast_sw::registrar. 05033 { 05034 return sw ? sw->registrar : NULL; 05035 }
|
|
Checks to see if a number should be ignored.
Definition at line 3645 of file pbx.c. References ast_context_find(), ast_extension_match(), and ast_context::ignorepats. 03646 { 03647 struct ast_context *con; 03648 struct ast_ignorepat *pat; 03649 03650 con = ast_context_find(context); 03651 if (con) { 03652 pat = con->ignorepats; 03653 while (pat) { 03654 if (ast_extension_match(pat->pattern, pattern)) 03655 return 1; 03656 pat = pat->next; 03657 } 03658 } 03659 return 0; 03660 }
|
|
Locks a given context.
Definition at line 4941 of file pbx.c. References ast_mutex_lock, and ast_context::lock. 04942 { 04943 return ast_mutex_lock(&con->lock); 04944 }
|
|
Locks the contexts. Locks the context list Returns 0 on success, -1 on error Definition at line 4928 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(). 04929 { 04930 return ast_mutex_lock(&conlock); 04931 }
|
|
Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
Definition at line 1766 of file pbx.c. References HELPER_MATCHMORE. Referenced by ast_pbx_run(). 01767 { 01768 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE); 01769 }
|
|
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
Definition at line 3015 of file pbx.c. References __ast_context_destroy(), ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_WARNING, and ast_context::next. 03015 { 03016 struct ast_context *tmp, *lasttmp = NULL; 03017 tmp = *extcontexts; 03018 ast_mutex_lock(&conlock); 03019 if (registrar) { 03020 __ast_context_destroy(NULL,registrar); 03021 while (tmp) { 03022 lasttmp = tmp; 03023 tmp = tmp->next; 03024 } 03025 } else { 03026 while (tmp) { 03027 __ast_context_destroy(tmp,tmp->registrar); 03028 lasttmp = tmp; 03029 tmp = tmp->next; 03030 } 03031 } 03032 if (lasttmp) { 03033 lasttmp->next = contexts; 03034 contexts = *extcontexts; 03035 *extcontexts = NULL; 03036 } else 03037 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n"); 03038 ast_mutex_unlock(&conlock); 03039 return; 03040 }
|
|
Definition at line 4185 of file pbx.c. References ast_hangup(), ast_log(), ast_pbx_run_app(), ast_pthread_create(), ast_request_and_dial(), AST_STATE_UP, ast_verbose(), free, LOG_ERROR, LOG_WARNING, malloc, option_verbose, pbx_builtin_setvar(), and VERBOSE_PREFIX_4. 04186 { 04187 struct ast_channel *chan; 04188 struct async_stat *as; 04189 struct app_tmp *tmp; 04190 char *var, *vartmp; 04191 int res = -1; 04192 pthread_attr_t attr; 04193 04194 if (!app || ast_strlen_zero(app)) 04195 return -1; 04196 if (sync) { 04197 chan = ast_request_and_dial(type, format, data, timeout, reason, 0, callerid, uniqueid); 04198 if (chan) { 04199 pbx_builtin_setaccount(chan, account); 04200 if (variable) { 04201 vartmp = ast_strdupa(variable); 04202 for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp)) { 04203 pbx_builtin_setvar( chan, var ); 04204 } 04205 } 04206 if (chan->_state == AST_STATE_UP) { 04207 res = 0; 04208 if (option_verbose > 3) 04209 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 04210 tmp = malloc(sizeof(struct app_tmp)); 04211 if (tmp) { 04212 memset(tmp, 0, sizeof(struct app_tmp)); 04213 strncpy(tmp->app, app, sizeof(tmp->app) - 1); 04214 strncpy(tmp->data, appdata, sizeof(tmp->data) - 1); 04215 tmp->chan = chan; 04216 if (sync > 1) { 04217 ast_pbx_run_app(tmp); 04218 } else { 04219 pthread_attr_init(&attr); 04220 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 04221 if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) { 04222 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno)); 04223 free(tmp); 04224 ast_hangup(chan); 04225 res = -1; 04226 } 04227 } 04228 } else { 04229 ast_log(LOG_ERROR, "Out of memory :(\n"); 04230 res = -1; 04231 } 04232 } else { 04233 if (option_verbose > 3) 04234 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 04235 ast_hangup(chan); 04236 } 04237 } 04238 } else { 04239 as = malloc(sizeof(struct async_stat)); 04240 if (!as) 04241 return -1; 04242 memset(as, 0, sizeof(struct async_stat)); 04243 chan = ast_request_and_dial(type, format, data, timeout, reason, 0, callerid, uniqueid); 04244 if (!chan) { 04245 free(as); 04246 return -1; 04247 } 04248 pbx_builtin_setaccount(chan, account); 04249 as->chan = chan; 04250 strncpy(as->app, app, sizeof(as->app) - 1); 04251 if (appdata) 04252 strncpy(as->appdata, appdata, sizeof(as->appdata) - 1); 04253 as->timeout = timeout; 04254 if (variable) { 04255 vartmp = ast_strdupa(variable); 04256 for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp)) 04257 pbx_builtin_setvar( chan, var ); 04258 } 04259 /* Start a new thread, and get something handling this channel. */ 04260 pthread_attr_init(&attr); 04261 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 04262 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 04263 ast_log(LOG_WARNING, "Failed to start async wait\n"); 04264 free(as); 04265 ast_hangup(chan); 04266 return -1; 04267 } 04268 res = 0; 04269 } 04270 return res; 04271 }
|
|
Definition at line 4067 of file pbx.c. References __ast_request_and_dial(), ast_channel_alloc(), ast_exists_extension(), ast_hangup(), ast_log(), ast_pbx_run(), ast_pbx_start(), ast_pthread_create(), ast_request_and_dial(), AST_STATE_UP, ast_verbose(), ast_channel::context, ast_channel::exten, free, LOAD_OH, LOG_ERROR, LOG_WARNING, malloc, ast_channel::name, option_verbose, pbx_builtin_setvar(), ast_channel::priority, and VERBOSE_PREFIX_4. 04068 { 04069 struct ast_channel *chan; 04070 struct async_stat *as; 04071 int res = -1; 04072 char *var, *tmp; 04073 struct outgoing_helper oh; 04074 pthread_attr_t attr; 04075 04076 if (sync) { 04077 LOAD_OH(oh); 04078 chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, callerid, &oh, uniqueid); 04079 if (chan) { 04080 pbx_builtin_setaccount(chan, account); 04081 if (chan->_state == AST_STATE_UP) { 04082 res = 0; 04083 if (option_verbose > 3) 04084 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name); 04085 04086 if (sync > 1) { 04087 if (ast_pbx_run(chan)) { 04088 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name); 04089 ast_hangup(chan); 04090 res = -1; 04091 } 04092 } else { 04093 if (ast_pbx_start(chan)) { 04094 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name); 04095 ast_hangup(chan); 04096 res = -1; 04097 } 04098 } 04099 } else { 04100 if (option_verbose > 3) 04101 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name); 04102 ast_hangup(chan); 04103 } 04104 } 04105 04106 if(res < 0) { /* the call failed for some reason */ 04107 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */ 04108 /* check if "failed" exists */ 04109 if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 04110 chan = ast_channel_alloc(0); 04111 if (chan) { 04112 strncpy(chan->name, "OutgoingSpoolFailed", sizeof(chan->name) - 1); 04113 if (context && !ast_strlen_zero(context)) 04114 strncpy(chan->context, context, sizeof(chan->context) - 1); 04115 strncpy(chan->exten, "failed", sizeof(chan->exten) - 1); 04116 chan->priority = 1; 04117 if (variable) { 04118 tmp = ast_strdupa(variable); 04119 for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp)) { 04120 pbx_builtin_setvar( chan, var ); 04121 } 04122 } 04123 ast_pbx_run(chan); 04124 } else 04125 ast_log(LOG_WARNING, "Can't allocate the channel structure, skipping execution of extension 'failed'\n"); 04126 } 04127 } 04128 } else { 04129 as = malloc(sizeof(struct async_stat)); 04130 if (!as) 04131 return -1; 04132 memset(as, 0, sizeof(struct async_stat)); 04133 chan = ast_request_and_dial(type, format, data, timeout, reason, callingpres, callerid, uniqueid); 04134 if (!chan) { 04135 free(as); 04136 return -1; 04137 } 04138 pbx_builtin_setaccount(chan, account); 04139 as->chan = chan; 04140 strncpy(as->context, context, sizeof(as->context) - 1); 04141 strncpy(as->exten, exten, sizeof(as->exten) - 1); 04142 as->priority = priority; 04143 as->timeout = timeout; 04144 if (variable) { 04145 tmp = ast_strdupa(variable); 04146 for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp)) 04147 pbx_builtin_setvar( chan, var ); 04148 } 04149 pthread_attr_init(&attr); 04150 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 04151 if (ast_pthread_create(&as->p, &attr, async_wait, as)) { 04152 ast_log(LOG_WARNING, "Failed to start async wait\n"); 04153 free(as); 04154 ast_hangup(chan); 04155 return -1; 04156 } 04157 res = 0; 04158 } 04159 return res; 04160 }
|
|
Execute the PBX in the current thread.
Definition at line 1776 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, ast_channel::exten, free, LOG_DEBUG, LOG_ERROR, LOG_WARNING, malloc, ast_channel::name, option_debug, option_verbose, ast_channel::pbx, pbx_builtin_setvar_helper(), ast_channel::priority, ast_pbx::rtimeout, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, and ast_channel::whentohangup. Referenced by ast_pbx_outgoing_exten(). 01777 { 01778 int firstpass = 1; 01779 char digit; 01780 char exten[256]; 01781 int pos; 01782 int waittime; 01783 int res=0; 01784 01785 /* A little initial setup here */ 01786 if (c->pbx) 01787 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 01788 c->pbx = malloc(sizeof(struct ast_pbx)); 01789 if (!c->pbx) { 01790 ast_log(LOG_ERROR, "Out of memory\n"); 01791 return -1; 01792 } 01793 if (c->amaflags) { 01794 if (c->cdr) { 01795 ast_log(LOG_WARNING, "%s already has a call record??\n", c->name); 01796 } else { 01797 c->cdr = ast_cdr_alloc(); 01798 if (!c->cdr) { 01799 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n"); 01800 free(c->pbx); 01801 return -1; 01802 } 01803 ast_cdr_init(c->cdr, c); 01804 } 01805 } 01806 memset(c->pbx, 0, sizeof(struct ast_pbx)); 01807 /* Set reasonable defaults */ 01808 c->pbx->rtimeout = 10; 01809 c->pbx->dtimeout = 5; 01810 01811 /* Start by trying whatever the channel is set to */ 01812 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) { 01813 /* JK02: If not successfull fall back to 's' */ 01814 if (option_verbose > 1) 01815 ast_verbose( VERBOSE_PREFIX_2 "Starting %s at %s,%s,%d failed so falling back to exten 's'\n", c->name, c->context, c->exten, c->priority); 01816 strncpy(c->exten, "s", sizeof(c->exten)-1); 01817 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) { 01818 /* JK02: And finally back to default if everything else failed */ 01819 if (option_verbose > 1) 01820 ast_verbose( VERBOSE_PREFIX_2 "Starting %s at %s,%s,%d still failed so falling back to context 'default'\n", c->name, c->context, c->exten, c->priority); 01821 strncpy(c->context, "default", sizeof(c->context)-1); 01822 } 01823 c->priority = 1; 01824 } 01825 if (c->cdr) 01826 ast_cdr_start(c->cdr); 01827 for(;;) { 01828 pos = 0; 01829 digit = 0; 01830 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) { 01831 memset(exten, 0, sizeof(exten)); 01832 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) { 01833 /* Something bad happened, or a hangup has been requested. */ 01834 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) || 01835 (res == '*') || (res == '#')) { 01836 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res); 01837 memset(exten, 0, sizeof(exten)); 01838 pos = 0; 01839 exten[pos++] = digit = res; 01840 break; 01841 } 01842 switch(res) { 01843 case AST_PBX_KEEPALIVE: 01844 if (option_debug) 01845 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 01846 else if (option_verbose > 1) 01847 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 01848 goto out; 01849 break; 01850 default: 01851 if (option_debug) 01852 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 01853 else if (option_verbose > 1) 01854 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 01855 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 01856 c->_softhangup =0; 01857 break; 01858 } 01859 /* atimeout */ 01860 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 01861 break; 01862 } 01863 01864 if (c->cdr) { 01865 ast_cdr_update(c); 01866 } 01867 goto out; 01868 } 01869 } 01870 if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->callerid))) { 01871 strncpy(c->exten,"T",sizeof(c->exten) - 1); 01872 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 01873 c->whentohangup = 0; 01874 c->priority = 0; 01875 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 01876 } else if (c->_softhangup) { 01877 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n", 01878 c->exten, c->priority); 01879 goto out; 01880 } 01881 firstpass = 0; 01882 c->priority++; 01883 } 01884 if (!ast_exists_extension(c, c->context, c->exten, 1, c->callerid)) { 01885 /* It's not a valid extension anymore */ 01886 if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) { 01887 if (option_verbose > 2) 01888 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 01889 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 01890 strncpy(c->exten, "i", sizeof(c->exten)-1); 01891 c->priority = 1; 01892 } else { 01893 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 01894 c->name, c->exten, c->context); 01895 goto out; 01896 } 01897 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 01898 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 01899 c->_softhangup = 0; 01900 } else { 01901 /* Done, wait for an extension */ 01902 if (digit) 01903 waittime = c->pbx->dtimeout; 01904 else 01905 waittime = c->pbx->rtimeout; 01906 while (ast_matchmore_extension(c, c->context, exten, 1, c->callerid)) { 01907 /* As long as we're willing to wait, and as long as it's not defined, 01908 keep reading digits until we can't possibly get a right answer anymore. */ 01909 digit = ast_waitfordigit(c, waittime * 1000); 01910 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 01911 c->_softhangup = 0; 01912 } else { 01913 if (!digit) 01914 /* No entry */ 01915 break; 01916 if (digit < 0) 01917 /* Error, maybe a hangup */ 01918 goto out; 01919 exten[pos++] = digit; 01920 waittime = c->pbx->dtimeout; 01921 } 01922 } 01923 if (ast_exists_extension(c, c->context, exten, 1, c->callerid)) { 01924 /* Prepare the next cycle */ 01925 strncpy(c->exten, exten, sizeof(c->exten)-1); 01926 c->priority = 1; 01927 } else { 01928 /* No such extension */ 01929 if (!ast_strlen_zero(exten)) { 01930 /* An invalid extension */ 01931 if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) { 01932 if (option_verbose > 2) 01933 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name); 01934 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten); 01935 strncpy(c->exten, "i", sizeof(c->exten)-1); 01936 c->priority = 1; 01937 } else { 01938 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", exten, c->context); 01939 goto out; 01940 } 01941 } else { 01942 /* A simple timeout */ 01943 if (ast_exists_extension(c, c->context, "t", 1, c->callerid)) { 01944 if (option_verbose > 2) 01945 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name); 01946 strncpy(c->exten, "t", sizeof(c->exten)-1); 01947 c->priority = 1; 01948 } else { 01949 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); 01950 goto out; 01951 } 01952 } 01953 } 01954 if (c->cdr) { 01955 if (option_verbose > 2) 01956 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name); 01957 ast_cdr_update(c); 01958 } 01959 } 01960 } 01961 if (firstpass) 01962 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 01963 out: 01964 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->callerid)) { 01965 c->exten[0] = 'h'; 01966 c->exten[1] = '\0'; 01967 c->priority = 1; 01968 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) { 01969 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) { 01970 /* Something bad happened, or a hangup has been requested. */ 01971 if (option_debug) 01972 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 01973 else if (option_verbose > 1) 01974 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 01975 break; 01976 } 01977 c->priority++; 01978 } 01979 } 01980 01981 pbx_destroy(c->pbx); 01982 c->pbx = NULL; 01983 if (res != AST_PBX_KEEPALIVE) 01984 ast_hangup(c); 01985 return 0; 01986 }
|
|
Definition at line 4169 of file pbx.c. References app_tmp::app, ast_hangup(), ast_log(), ast_verbose(), app_tmp::chan, app_tmp::data, free, LOG_WARNING, ast_channel::name, option_verbose, pbx_exec(), pbx_findapp(), and VERBOSE_PREFIX_4. Referenced by ast_pbx_outgoing_app(). 04170 { 04171 struct app_tmp *tmp = data; 04172 struct ast_app *app; 04173 app = pbx_findapp(tmp->app); 04174 if (app) { 04175 if (option_verbose > 3) 04176 ast_verbose(VERBOSE_PREFIX_4 "Lauching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name); 04177 pbx_exec(tmp->chan, app, tmp->data, 1); 04178 } else 04179 ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app); 04180 ast_hangup(tmp->chan); 04181 free(tmp); 04182 return NULL; 04183 }
|
|
Create a new thread and start the PBX (or whatever).
Definition at line 2001 of file pbx.c. References ast_log(), ast_pthread_create(), and LOG_WARNING. Referenced by ast_async_goto(), and ast_pbx_outgoing_exten(). 02002 { 02003 pthread_t t; 02004 pthread_attr_t attr; 02005 if (!c) { 02006 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n"); 02007 return -1; 02008 } 02009 02010 /* Start a new thread, and get something handling this channel. */ 02011 pthread_attr_init(&attr); 02012 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 02013 if (ast_pthread_create(&t, &attr, pbx_thread, c)) { 02014 ast_log(LOG_WARNING, "Failed to create new channel thread\n"); 02015 return -1; 02016 } 02017 return 0; 02018 }
|
|
Add an application. The function 'execute' should return non-zero if the line needs to be hung up.
Definition at line 2309 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), COLOR_BRCYAN, LOG_ERROR, LOG_WARNING, malloc, ast_app::name, ast_app::next, option_verbose, term_color(), and VERBOSE_PREFIX_2. Referenced by load_pbx(). 02310 { 02311 struct ast_app *tmp, *prev, *cur; 02312 char tmps[80]; 02313 if (ast_mutex_lock(&applock)) { 02314 ast_log(LOG_ERROR, "Unable to lock application list\n"); 02315 return -1; 02316 } 02317 tmp = apps; 02318 while(tmp) { 02319 if (!strcasecmp(app, tmp->name)) { 02320 ast_log(LOG_WARNING, "Already have an application '%s'\n", app); 02321 ast_mutex_unlock(&applock); 02322 return -1; 02323 } 02324 tmp = tmp->next; 02325 } 02326 tmp = malloc(sizeof(struct ast_app)); 02327 if (tmp) { 02328 memset(tmp, 0, sizeof(struct ast_app)); 02329 strncpy(tmp->name, app, sizeof(tmp->name)-1); 02330 tmp->execute = execute; 02331 tmp->synopsis = synopsis; 02332 tmp->description = description; 02333 /* Store in alphabetical order */ 02334 cur = apps; 02335 prev = NULL; 02336 while(cur) { 02337 if (strcasecmp(tmp->name, cur->name) < 0) 02338 break; 02339 prev = cur; 02340 cur = cur->next; 02341 } 02342 if (prev) { 02343 tmp->next = prev->next; 02344 prev->next = tmp; 02345 } else { 02346 tmp->next = apps; 02347 apps = tmp; 02348 } 02349 } else { 02350 ast_log(LOG_ERROR, "Out of memory\n"); 02351 ast_mutex_unlock(&applock); 02352 return -1; 02353 } 02354 if (option_verbose > 1) 02355 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps))); 02356 ast_mutex_unlock(&applock); 02357 return 0; 02358 }
|
|
Register an alternative switch.
Definition at line 2360 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_ERROR, LOG_WARNING, ast_switch::name, and ast_switch::next. 02361 { 02362 struct ast_switch *tmp, *prev=NULL; 02363 if (ast_mutex_lock(&switchlock)) { 02364 ast_log(LOG_ERROR, "Unable to lock switch lock\n"); 02365 return -1; 02366 } 02367 tmp = switches; 02368 while(tmp) { 02369 if (!strcasecmp(tmp->name, sw->name)) 02370 break; 02371 prev = tmp; 02372 tmp = tmp->next; 02373 } 02374 if (tmp) { 02375 ast_mutex_unlock(&switchlock); 02376 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name); 02377 return -1; 02378 } 02379 sw->next = NULL; 02380 if (prev) 02381 prev->next = sw; 02382 else 02383 switches = sw; 02384 ast_mutex_unlock(&switchlock); 02385 return 0; 02386 }
|
|
Launch a new extension (i.e. new stack).
Definition at line 1771 of file pbx.c. References HELPER_SPAWN. Referenced by ast_pbx_run(). 01772 { 01773 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN); 01774 }
|
|
Unlocks the given context.
Definition at line 4946 of file pbx.c. References ast_mutex_unlock, and ast_context::lock. 04947 { 04948 return ast_mutex_unlock(&con->lock); 04949 }
|
|
Unlocks contexts. Returns 0 on success, -1 on failure Definition at line 4933 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(). 04934 { 04935 return ast_mutex_unlock(&conlock); 04936 }
|
|
Remove an application.
Definition at line 2944 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), free, LOG_ERROR, ast_app::name, ast_app::next, option_verbose, and VERBOSE_PREFIX_2. 02944 { 02945 struct ast_app *tmp, *tmpl = NULL; 02946 if (ast_mutex_lock(&applock)) { 02947 ast_log(LOG_ERROR, "Unable to lock application list\n"); 02948 return -1; 02949 } 02950 tmp = apps; 02951 while(tmp) { 02952 if (!strcasecmp(app, tmp->name)) { 02953 if (tmpl) 02954 tmpl->next = tmp->next; 02955 else 02956 apps = tmp->next; 02957 if (option_verbose > 1) 02958 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name); 02959 free(tmp); 02960 ast_mutex_unlock(&applock); 02961 return 0; 02962 } 02963 tmpl = tmp; 02964 tmp = tmp->next; 02965 } 02966 ast_mutex_unlock(&applock); 02967 return -1; 02968 }
|
|
Unregister an alternative switch.
Definition at line 2388 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_ERROR, and ast_switch::next. 02389 { 02390 struct ast_switch *tmp, *prev=NULL; 02391 if (ast_mutex_lock(&switchlock)) { 02392 ast_log(LOG_ERROR, "Unable to lock switch lock\n"); 02393 return; 02394 } 02395 tmp = switches; 02396 while(tmp) { 02397 if (tmp == sw) { 02398 if (prev) 02399 prev->next = tmp->next; 02400 else 02401 switches = tmp->next; 02402 tmp->next = NULL; 02403 break; 02404 } 02405 prev = tmp; 02406 tmp = tmp->next; 02407 } 02408 ast_mutex_unlock(&switchlock); 02409 }
|
|
Definition at line 5048 of file pbx.c. References ast_exten::next. 05050 { 05051 if (!exten) 05052 return con ? con->root : NULL; 05053 else 05054 return exten->next; 05055 }
|
|
Definition at line 5084 of file pbx.c. References ast_ignorepat::next. 05086 { 05087 if (!ip) 05088 return con ? con->ignorepats : NULL; 05089 else 05090 return ip->next; 05091 }
|
|
Definition at line 5075 of file pbx.c. References ast_include::next. Referenced by ast_context_verify_includes(). 05077 { 05078 if (!inc) 05079 return con ? con->includes : NULL; 05080 else 05081 return inc->next; 05082 }
|
|
Definition at line 5057 of file pbx.c. References ast_sw::next. 05059 { 05060 if (!sw) 05061 return con ? con->alts : NULL; 05062 else 05063 return sw->next; 05064 }
|
|
Definition at line 5040 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(). 05041 { 05042 if (!con) 05043 return contexts; 05044 else 05045 return con->next; 05046 }
|
|
Definition at line 5066 of file pbx.c. References ast_exten::peer. 05068 { 05069 if (!priority) 05070 return exten; 05071 else 05072 return priority->peer; 05073 }
|
|
Definition at line 4786 of file pbx.c. References AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_REMOVE_HEAD, and ast_var_delete(). 04787 { 04788 struct ast_var_t *vardata; 04789 while (!AST_LIST_EMPTY(&globals)) { 04790 vardata = AST_LIST_FIRST(&globals); 04791 AST_LIST_REMOVE_HEAD(&globals, entries); 04792 ast_var_delete(vardata); 04793 } 04794 }
|
|
|
|
|
|
|
|
executes an application
Definition at line 426 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. Referenced by ast_pbx_run_app(). 00430 { 00431 /* This function is special. It saves the stack so that no matter 00432 how many times it is called, it returns to the same place */ 00433 int res; 00434 00435 char *saved_c_appl; 00436 char *saved_c_data; 00437 00438 int stack = c->stack; 00439 int (*execute)(struct ast_channel *chan, void *data) = app->execute; 00440 00441 if (newstack && stack > AST_CHANNEL_MAX_STACK - 2) { 00442 /* Don't allow us to go over the max number of stacks we 00443 permit saving. */ 00444 ast_log(LOG_WARNING, "Stack overflow, cannot create another stack\n"); 00445 return -1; 00446 } 00447 if (newstack && (res = setjmp(c->jmp[++c->stack]))) { 00448 /* Okay, here's where it gets weird. If newstack is non-zero, 00449 then we increase the stack increment, but setjmp is not going 00450 to return until longjmp is called -- when the application 00451 exec'd is finished running. */ 00452 if (res == 1) 00453 res = 0; 00454 if (c->stack != stack + 1) 00455 ast_log(LOG_WARNING, "Stack returned to an unexpected place!\n"); 00456 else if (c->app[c->stack]) 00457 ast_log(LOG_WARNING, "Application may have forgotten to free its memory\n"); 00458 c->stack = stack; 00459 return res; 00460 } else { 00461 if (c->cdr) 00462 ast_cdr_setapp(c->cdr, app->name, data); 00463 00464 /* save channel values */ 00465 saved_c_appl= c->appl; 00466 saved_c_data= c->data; 00467 00468 c->appl = app->name; 00469 c->data = data; 00470 res = execute(c, data); 00471 /* restore channel values */ 00472 c->appl= saved_c_appl; 00473 c->data= saved_c_data; 00474 00475 /* Any application that returns, we longjmp back, just in case. */ 00476 if (c->stack != stack + 1) 00477 ast_log(LOG_WARNING, "Stack is not at expected value\n"); 00478 longjmp(c->jmp[stack+1], res); 00479 /* Never returns */ 00480 } 00481 }
|
|
Look up an application.
Definition at line 493 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_WARNING, ast_app::name, and ast_app::next. Referenced by ast_pbx_run_app(). 00494 { 00495 struct ast_app *tmp; 00496 00497 if (ast_mutex_lock(&applock)) { 00498 ast_log(LOG_WARNING, "Unable to obtain application lock\n"); 00499 return NULL; 00500 } 00501 tmp = apps; 00502 while(tmp) { 00503 if (!strcasecmp(tmp->name, app)) 00504 break; 00505 tmp = tmp->next; 00506 } 00507 ast_mutex_unlock(&applock); 00508 return tmp; 00509 }
|
|
Definition at line 1044 of file pbx.c. References ast_expr(), ast_log(), free, LOG_DEBUG, LOG_NOTICE, and pbx_substitute_variables_helper(). Referenced by pbx_substitute_variables_helper(). 01045 { 01046 char *cp4; 01047 const char *tmp, *whereweare; 01048 int length; 01049 char workspace[4096]; 01050 char ltmp[4096], var[4096]; 01051 char *nextvar, *nextexp; 01052 char *vars, *vare; 01053 int pos, brackets, needsub, len; 01054 01055 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be 01056 zero-filled */ 01057 whereweare=tmp=cp1; 01058 while(!ast_strlen_zero(whereweare) && count) { 01059 /* Assume we're copying the whole remaining string */ 01060 pos = strlen(whereweare); 01061 01062 /* Look for a variable */ 01063 nextvar = strstr(whereweare, "${"); 01064 01065 /* Look for an expression */ 01066 nextexp = strstr(whereweare, "$["); 01067 01068 /* Pick the first one only */ 01069 if (nextvar && nextexp) { 01070 if (nextvar < nextexp) 01071 nextexp = NULL; 01072 else 01073 nextvar = NULL; 01074 } 01075 01076 /* If there is one, we only go that far */ 01077 if (nextvar) 01078 pos = nextvar - whereweare; 01079 else if (nextexp) 01080 pos = nextexp - whereweare; 01081 01082 /* Can't copy more than 'count' bytes */ 01083 if (pos > count) 01084 pos = count; 01085 01086 /* Copy that many bytes */ 01087 memcpy(cp2, whereweare, pos); 01088 01089 count -= pos; 01090 cp2 += pos; 01091 whereweare += pos; 01092 01093 if (nextvar) { 01094 /* We have a variable. Find the start and end, and determine 01095 if we are going to have to recursively call ourselves on the 01096 contents */ 01097 vars = vare = nextvar + 2; 01098 brackets = 1; 01099 needsub = 0; 01100 01101 /* Find the end of it */ 01102 while(brackets && *vare) { 01103 if ((vare[0] == '$') && (vare[1] == '{')) { 01104 needsub++; 01105 brackets++; 01106 } else if (vare[0] == '}') { 01107 brackets--; 01108 } else if ((vare[0] == '$') && (vare[1] == '[')) 01109 needsub++; 01110 vare++; 01111 } 01112 if (brackets) 01113 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n"); 01114 len = vare - vars - 1; 01115 01116 /* Skip totally over variable name */ 01117 whereweare += ( len + 3); 01118 01119 /* Store variable name (and truncate) */ 01120 memset(var, 0, sizeof(var)); 01121 strncpy(var, vars, sizeof(var) - 1); 01122 var[len] = '\0'; 01123 01124 /* Substitute if necessary */ 01125 if (needsub) { 01126 memset(ltmp, 0, sizeof(ltmp)); 01127 pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1); 01128 vars = ltmp; 01129 } else { 01130 vars = var; 01131 } 01132 01133 /* Retrieve variable value */ 01134 workspace[0] = '\0'; 01135 pbx_substitute_variables_temp(c,vars,&cp4, workspace, sizeof(workspace)); 01136 if (cp4) { 01137 length = strlen(cp4); 01138 if (length > count) 01139 length = count; 01140 memcpy(cp2, cp4, length); 01141 count -= length; 01142 cp2 += length; 01143 } 01144 01145 } else if (nextexp) { 01146 /* We have an expression. Find the start and end, and determine 01147 if we are going to have to recursively call ourselves on the 01148 contents */ 01149 vars = vare = nextexp + 2; 01150 brackets = 1; 01151 needsub = 0; 01152 01153 /* Find the end of it */ 01154 while(brackets && *vare) { 01155 if ((vare[0] == '$') && (vare[1] == '[')) { 01156 needsub++; 01157 brackets++; 01158 vare++; 01159 } else if (vare[0] == '[') { 01160 brackets++; 01161 } else if (vare[0] == ']') { 01162 brackets--; 01163 } else if ((vare[0] == '$') && (vare[1] == '{')) { 01164 needsub++; 01165 vare++; 01166 } 01167 vare++; 01168 } 01169 if (brackets) 01170 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n"); 01171 len = vare - vars - 1; 01172 01173 /* Skip totally over variable name */ 01174 whereweare += ( len + 3); 01175 01176 /* Store variable name (and truncate) */ 01177 memset(var, 0, sizeof(var)); 01178 strncpy(var, vars, sizeof(var) - 1); 01179 var[len] = '\0'; 01180 01181 /* Substitute if necessary */ 01182 if (needsub) { 01183 memset(ltmp, 0, sizeof(ltmp)); 01184 pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1); 01185 vars = ltmp; 01186 } else { 01187 vars = var; 01188 } 01189 01190 /* Evaluate expression */ 01191 cp4 = ast_expr(vars); 01192 01193 ast_log(LOG_DEBUG, "Expression is '%s'\n", cp4); 01194 01195 if (cp4) { 01196 length = strlen(cp4); 01197 if (length > count) 01198 length = count; 01199 memcpy(cp2, cp4, length); 01200 count -= length; 01201 cp2 += length; 01202 free(cp4); 01203 } 01204 01205 } else 01206 break; 01207 } 01208 }
|