#include <asterisk/sched.h>#include <asterisk/channel.h>Go to the source code of this file.
Data Structures | |
| struct | ast_pbx |
| struct | ast_switch |
| Data structure associated with an asterisk switch. More... | |
Defines | |
| #define | AST_PBX_KEEP 0 |
| #define | AST_PBX_REPLACE 1 |
| #define | AST_MAX_APP 32 |
| Max length of an application. More... | |
| #define | AST_PBX_KEEPALIVE 10 |
| Special return values from applications to the PBX. More... | |
| #define | AST_PBX_NO_HANGUP_PEER 11 |
| #define | PRIORITY_HINT -1 |
| Special Priority for an hint. More... | |
| #define | AST_EXTENSION_NOT_INUSE 0 |
| Extension states No device INUSE or BUSY. More... | |
| #define | AST_EXTENSION_INUSE 1 |
| One or more devices INUSE. More... | |
| #define | AST_EXTENSION_BUSY 2 |
| All devices BUSY. More... | |
| #define | AST_EXTENSION_UNAVAILABLE 3 |
| All devices UNAVAILABLE/UNREGISTERED. More... | |
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. More... | |
| void | ast_unregister_switch (struct ast_switch *sw) |
| Unregister an alternative switch. More... | |
| ast_app * | pbx_findapp (char *app) |
| Look up an application. More... | |
| int | pbx_exec (struct ast_channel *c, struct ast_app *app, void *data, int newstack) |
| executes an application. More... | |
| ast_context * | ast_context_create (struct ast_context **extcontexts, char *name, char *registrar) |
| Register a new context. More... | |
| 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. More... | |
| void | ast_context_destroy (struct ast_context *con, char *registrar) |
| Destroy a context (matches the specified context (or ANY context if NULL). More... | |
| ast_context * | ast_context_find (char *name) |
| Find a context. More... | |
| int | ast_pbx_start (struct ast_channel *c) |
| Create a new thread and start the PBX (or whatever). More... | |
| int | ast_pbx_run (struct ast_channel *c) |
| Execute the PBX in the current thread. More... | |
| 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. More... | |
| 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. More... | |
| int | ast_unregister_application (char *app) |
| Remove an application. More... | |
| int | ast_extension_state (struct ast_channel *c, char *context, char *exten) |
| Uses hint and devicestate callback to get the state of an extension. More... | |
| int | ast_device_state_changed (const char *fmt,...) __attribute__((format(printf |
| Tells Asterisk the State for Device is changed. More... | |
| int | ast_extension_state_add (char *context, char *exten, ast_state_cb_type callback, void *data) |
| Registers a state change callback. More... | |
| int | ast_extension_state_del (int id, ast_state_cb_type callback) |
| Deletes a registered state change callback by ID. More... | |
| int | ast_get_hint (char *hint, int maxlen, struct ast_channel *c, char *context, char *exten) |
| If an extension exists, return non-zero. More... | |
| int | ast_exists_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid) |
| If an extension exists, return non-zero. More... | |
| int | ast_canmatch_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid) |
| Looks for a valid matching extension. More... | |
| 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). More... | |
| int | ast_extension_match (char *pattern, char *extension) |
| Determine if a given extension matches a given pattern (in NXX format). More... | |
| int | ast_spawn_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid) |
| Launch a new extension (i.e. new stack). More... | |
| int | ast_exec_extension (struct ast_channel *c, char *context, char *exten, int priority, char *callerid) |
| Execute an extension. More... | |
| int | ast_context_add_include (char *context, char *include, char *registrar) |
| Add an include. More... | |
| int | ast_context_add_include2 (struct ast_context *con, char *include, char *registrar) |
| Add an include. More... | |
| int | ast_context_remove_include (char *context, char *include, char *registrar) |
| Removes an include. More... | |
| int | ast_context_remove_include2 (struct ast_context *con, char *include, char *registrar) |
| Removes an include by an ast_context structure. More... | |
| int | ast_context_verify_includes (struct ast_context *con) |
| Verifies includes in an ast_contect structure. More... | |
| int | ast_context_add_switch (char *context, char *sw, char *data, char *registrar) |
| Add a switch. More... | |
| int | ast_context_add_switch2 (struct ast_context *con, char *sw, char *data, char *registrar) |
| Adds a switch (first param is a ast_context). More... | |
| int | ast_context_remove_switch (char *context, char *sw, char *data, char *registrar) |
| Remove a switch. More... | |
| 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. More... | |
| 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. More... | |
| 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. More... | |
| int | ast_lock_contexts (void) |
| Locks the contexts. More... | |
| int | ast_unlock_contexts (void) |
| Unlocks contexts. More... | |
| int | ast_lock_context (struct ast_context *con) |
| Locks a given context. More... | |
| int | ast_unlock_context (struct ast_context *con) |
| Unlocks the given context. More... | |
| int | ast_async_goto (struct ast_channel *chan, char *context, char *exten, int priority) |
| int | ast_async_goto_by_name (char *chan, char *context, char *exten, int priority) |
| int | ast_pbx_outgoing_exten (char *type, int format, void *data, int timeout, char *context, char *exten, int priority, int *reason, int sync, char *callerid, char *variable, char *account) |
| int | ast_pbx_outgoing_app (char *type, int format, void *data, int timeout, char *app, char *appdata, int *reason, int sync, char *callerid, char *variable, char *account) |
| char * | ast_get_context_name (struct ast_context *con) |
| char * | ast_get_extension_name (struct ast_exten *exten) |
| char * | ast_get_include_name (struct ast_include *include) |
| char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
| char * | ast_get_switch_name (struct ast_sw *sw) |
| char * | ast_get_switch_data (struct ast_sw *sw) |
| int | ast_get_extension_priority (struct ast_exten *exten) |
| int | ast_get_extension_matchcid (struct ast_exten *e) |
| char * | ast_get_extension_cidmatch (struct ast_exten *e) |
| char * | ast_get_extension_app (struct ast_exten *e) |
| void * | ast_get_extension_app_data (struct ast_exten *e) |
| char * | ast_get_context_registrar (struct ast_context *c) |
| char * | ast_get_extension_registrar (struct ast_exten *e) |
| char * | ast_get_include_registrar (struct ast_include *i) |
| char * | ast_get_ignorepat_registrar (struct ast_ignorepat *ip) |
| char * | ast_get_switch_registrar (struct ast_sw *sw) |
| 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.
|
|
|
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 52 of file pbx.h. Referenced by ast_extension_state_add(), and ast_extension_state_del(). |
|
||||||||||||||||||||||||||||||||||||||||
|
Definition at line 3636 of file pbx.c. References ast_add_extension2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
03638 {
03639 struct ast_context *c;
03640
03641 if (ast_lock_contexts()) {
03642 errno = EBUSY;
03643 return -1;
03644 }
03645
03646 c = ast_walk_contexts(NULL);
03647 while (c) {
03648 if (!strcmp(context, ast_get_context_name(c))) {
03649 int ret = ast_add_extension2(c, replace, extension, priority, callerid,
03650 application, data, datad, registrar);
03651 ast_unlock_contexts();
03652 return ret;
03653 }
03654 c = ast_walk_contexts(c);
03655 }
03656
03657 ast_unlock_contexts();
03658 errno = ENOENT;
03659 return -1;
03660 }
|
|
||||||||||||||||||||||||||||||||||||||||
|
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 3769 of file pbx.c. References ast_exten::app, 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_ERROR, LOG_WARNING, malloc, ast_exten::matchcid, ast_context::name, ast_exten::next, ast_exten::parent, ast_exten::peer, ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, and ast_context::root. Referenced by ast_add_extension().
03773 {
03774
03775 #define LOG do { if (option_debug) {\
03776 if (tmp->matchcid) { \
03777 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
03778 } else { \
03779 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
03780 } \
03781 } else if (option_verbose > 2) { \
03782 if (tmp->matchcid) { \
03783 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", tmp->exten, tmp->priority, tmp->cidmatch, con->name); \
03784 } else { \
03785 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", tmp->exten, tmp->priority, con->name); \
03786 } \
03787 } } while(0)
03788
03789 /*
03790 * This is a fairly complex routine. Different extensions are kept
03791 * in order by the extension number. Then, extensions of different
03792 * priorities (same extension) are kept in a list, according to the
03793 * peer pointer.
03794 */
03795 struct ast_exten *tmp, *e, *el = NULL, *ep = NULL;
03796 int res;
03797
03798 /* Be optimistic: Build the extension structure first */
03799 tmp = malloc(sizeof(struct ast_exten));
03800 if (tmp) {
03801 memset(tmp, 0, sizeof(struct ast_exten));
03802 ext_strncpy(tmp->exten, extension, sizeof(tmp->exten));
03803 tmp->priority = priority;
03804 if (callerid) {
03805 ext_strncpy(tmp->cidmatch, callerid, sizeof(tmp->cidmatch));
03806 tmp->matchcid = 1;
03807 } else {
03808 tmp->cidmatch[0] = '\0';
03809 tmp->matchcid = 0;
03810 }
03811 strncpy(tmp->app, application, sizeof(tmp->app)-1);
03812 tmp->parent = con;
03813 tmp->data = data;
03814 tmp->datad = datad;
03815 tmp->registrar = registrar;
03816 tmp->peer = NULL;
03817 tmp->next = NULL;
03818 } else {
03819 ast_log(LOG_ERROR, "Out of memory\n");
03820 errno = ENOMEM;
03821 return -1;
03822 }
03823 if (ast_mutex_lock(&con->lock)) {
03824 free(tmp);
03825 /* And properly destroy the data */
03826 datad(data);
03827 ast_log(LOG_WARNING, "Failed to lock context '%s'\n", con->name);
03828 errno = EBUSY;
03829 return -1;
03830 }
03831 e = con->root;
03832 while(e) {
03833 /* Make sure patterns are always last! */
03834 if ((e->exten[0] != '_') && (extension[0] == '_'))
03835 res = -1;
03836 else if ((e->exten[0] == '_') && (extension[0] != '_'))
03837 res = 1;
03838 else
03839 res= strcmp(e->exten, extension);
03840 if (!res) {
03841 if (!e->matchcid && !tmp->matchcid)
03842 res = 0;
03843 else if (tmp->matchcid && !e->matchcid)
03844 res = 1;
03845 else if (e->matchcid && !tmp->matchcid)
03846 res = -1;
03847 else
03848 res = strcasecmp(e->cidmatch, tmp->cidmatch);
03849 }
03850 if (res == 0) {
03851 /* We have an exact match, now we find where we are
03852 and be sure there's no duplicates */
03853 while(e) {
03854 if (e->priority == tmp->priority) {
03855 /* Can't have something exactly the same. Is this a
03856 replacement? If so, replace, otherwise, bonk. */
03857 if (replace) {
03858 if (ep) {
03859 /* We're in the peer list, insert ourselves */
03860 ep->peer = tmp;
03861 tmp->peer = e->peer;
03862 } else if (el) {
03863 /* We're the first extension. Take over e's functions */
03864 el->next = tmp;
03865 tmp->next = e->next;
03866 tmp->peer = e->peer;
03867 } else {
03868 /* We're the very first extension. */
03869 con->root = tmp;
03870 tmp->next = e->next;
03871 tmp->peer = e->peer;
03872 }
03873 if (tmp->priority == PRIORITY_HINT)
03874 ast_change_hint(e,tmp);
03875 /* Destroy the old one */
03876 e->datad(e->data);
03877 free(e);
03878 ast_mutex_unlock(&con->lock);
03879 if (tmp->priority == PRIORITY_HINT)
03880 ast_change_hint(e, tmp);
03881 /* And immediately return success. */
03882 LOG;
03883 return 0;
03884 } else {
03885 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
03886 tmp->datad(tmp->data);
03887 free(tmp);
03888 ast_mutex_unlock(&con->lock);
03889 errno = EEXIST;
03890 return -1;
03891 }
03892 } else if (e->priority > tmp->priority) {
03893 /* Slip ourselves in just before e */
03894 if (ep) {
03895 /* Easy enough, we're just in the peer list */
03896 ep->peer = tmp;
03897 tmp->peer = e;
03898 } else if (el) {
03899 /* We're the first extension in this peer list */
03900 el->next = tmp;
03901 tmp->next = e->next;
03902 e->next = NULL;
03903 tmp->peer = e;
03904 } else {
03905 /* We're the very first extension altogether */
03906 tmp->next = con->root->next;
03907 /* Con->root must always exist or we couldn't get here */
03908 tmp->peer = con->root;
03909 con->root = tmp;
03910 }
03911 ast_mutex_unlock(&con->lock);
03912 /* And immediately return success. */
03913 if (tmp->priority == PRIORITY_HINT)
03914 ast_add_hint(tmp);
03915
03916 LOG;
03917 return 0;
03918 }
03919 ep = e;
03920 e = e->peer;
03921 }
03922 /* If we make it here, then it's time for us to go at the very end.
03923 ep *must* be defined or we couldn't have gotten here. */
03924 ep->peer = tmp;
03925 ast_mutex_unlock(&con->lock);
03926 if (tmp->priority == PRIORITY_HINT)
03927 ast_add_hint(tmp);
03928
03929 /* And immediately return success. */
03930 LOG;
03931 return 0;
03932
03933 } else if (res > 0) {
03934 /* Insert ourselves just before 'e'. We're the first extension of
03935 this kind */
03936 tmp->next = e;
03937 if (el) {
03938 /* We're in the list somewhere */
03939 el->next = tmp;
03940 } else {
03941 /* We're at the top of the list */
03942 con->root = tmp;
03943 }
03944 ast_mutex_unlock(&con->lock);
03945 if (tmp->priority == PRIORITY_HINT)
03946 ast_add_hint(tmp);
03947
03948 /* And immediately return success. */
03949 LOG;
03950 return 0;
03951 }
03952
03953 el = e;
03954 e = e->next;
03955 }
03956 /* If we fall all the way through to here, then we need to be on the end. */
03957 if (el)
03958 el->next = tmp;
03959 else
03960 con->root = tmp;
03961 ast_mutex_unlock(&con->lock);
03962 if (tmp->priority == PRIORITY_HINT)
03963 ast_add_hint(tmp);
03964 LOG;
03965 return 0;
03966 }
|
|
||||||||||||||||||||
|
Definition at line 3662 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().
03663 {
03664 int res = 0;
03665 ast_mutex_lock(&chan->lock);
03666
03667 if (chan->pbx) {
03668 /* This channel is currently in the PBX */
03669 if (context && !ast_strlen_zero(context))
03670 strncpy(chan->context, context, sizeof(chan->context) - 1);
03671 if (exten && !ast_strlen_zero(exten))
03672 strncpy(chan->exten, exten, sizeof(chan->context) - 1);
03673 if (priority)
03674 chan->priority = priority - 1;
03675 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
03676 } else {
03677 /* In order to do it when the channel doesn't really exist within
03678 the PBX, we have to make a new channel, masquerade, and start the PBX
03679 at the new location */
03680 struct ast_channel *tmpchan;
03681 tmpchan = ast_channel_alloc(0);
03682 if (tmpchan) {
03683 snprintf(tmpchan->name, sizeof(tmpchan->name), "AsyncGoto/%s", chan->name);
03684 ast_setstate(tmpchan, chan->_state);
03685 /* Make formats okay */
03686 tmpchan->readformat = chan->readformat;
03687 tmpchan->writeformat = chan->writeformat;
03688 /* Setup proper location */
03689 if (context && !ast_strlen_zero(context))
03690 strncpy(tmpchan->context, context, sizeof(tmpchan->context) - 1);
03691 else
03692 strncpy(tmpchan->context, chan->context, sizeof(tmpchan->context) - 1);
03693 if (exten && !ast_strlen_zero(exten))
03694 strncpy(tmpchan->exten, exten, sizeof(tmpchan->exten) - 1);
03695 else
03696 strncpy(tmpchan->exten, chan->exten, sizeof(tmpchan->exten) - 1);
03697 if (priority)
03698 tmpchan->priority = priority;
03699 else
03700 tmpchan->priority = chan->priority;
03701
03702 /* Masquerade into temp channel */
03703 ast_channel_masquerade(tmpchan, chan);
03704
03705 /* Grab the locks and get going */
03706 ast_mutex_lock(&tmpchan->lock);
03707 ast_do_masquerade(tmpchan);
03708 ast_mutex_unlock(&tmpchan->lock);
03709 /* Start the PBX going on our stolen channel */
03710 if (ast_pbx_start(tmpchan)) {
03711 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
03712 ast_hangup(tmpchan);
03713 res = -1;
03714 }
03715 } else {
03716 res = -1;
03717 }
03718 }
03719 ast_mutex_unlock(&chan->lock);
03720 return res;
03721 }
|
|
||||||||||||||||||||
|
Definition at line 3723 of file pbx.c. References ast_async_goto(), ast_channel_walk_locked(), ast_mutex_unlock, ast_channel::lock, and ast_channel::name.
03724 {
03725 struct ast_channel *chan;
03726 int res = -1;
03727
03728 chan = ast_channel_walk_locked(NULL);
03729 while(chan) {
03730 if (!strcasecmp(channame, chan->name))
03731 break;
03732 ast_mutex_unlock(&chan->lock);
03733 chan = ast_channel_walk_locked(chan);
03734 }
03735
03736 if (chan) {
03737 res = ast_async_goto(chan, context, exten, priority);
03738 ast_mutex_unlock(&chan->lock);
03739 }
03740 return res;
03741 }
|
|
||||||||||||||||||||||||
|
Looks for a valid matching extension.
Definition at line 1745 of file pbx.c. References HELPER_CANMATCH.
01746 {
01747 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_CANMATCH);
01748 }
|
|
||||||||||||||||
|
Add an ignorepat.
Definition at line 3555 of file pbx.c. References ast_context_add_ignorepat2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
03556 {
03557 struct ast_context *c;
03558
03559 if (ast_lock_contexts()) {
03560 errno = EBUSY;
03561 return -1;
03562 }
03563
03564 c = ast_walk_contexts(NULL);
03565 while (c) {
03566 if (!strcmp(ast_get_context_name(c), con)) {
03567 int ret = ast_context_add_ignorepat2(c, value, registrar);
03568 ast_unlock_contexts();
03569 return ret;
03570 }
03571 c = ast_walk_contexts(c);
03572 }
03573
03574 ast_unlock_contexts();
03575 errno = ENOENT;
03576 return -1;
03577 }
|
|
||||||||||||||||
|
Definition at line 3579 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().
03580 {
03581 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
03582
03583 ignorepat = malloc(sizeof(struct ast_ignorepat));
03584 if (!ignorepat) {
03585 ast_log(LOG_ERROR, "Out of memory\n");
03586 errno = ENOMEM;
03587 return -1;
03588 }
03589 memset(ignorepat, 0, sizeof(struct ast_ignorepat));
03590 strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
03591 ignorepat->next = NULL;
03592 ignorepat->registrar = registrar;
03593 ast_mutex_lock(&con->lock);
03594 ignorepatc = con->ignorepats;
03595 while(ignorepatc) {
03596 ignorepatl = ignorepatc;
03597 if (!strcasecmp(ignorepatc->pattern, value)) {
03598 /* Already there */
03599 ast_mutex_unlock(&con->lock);
03600 errno = EEXIST;
03601 return -1;
03602 }
03603 ignorepatc = ignorepatc->next;
03604 }
03605 if (ignorepatl)
03606 ignorepatl->next = ignorepat;
03607 else
03608 con->ignorepats = ignorepat;
03609 ast_mutex_unlock(&con->lock);
03610 return 0;
03611
03612 }
|
|
||||||||||||||||
|
Add an include.
Definition at line 3016 of file pbx.c. References ast_context_add_include2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
03017 {
03018 struct ast_context *c;
03019
03020 if (ast_lock_contexts()) {
03021 errno = EBUSY;
03022 return -1;
03023 }
03024
03025 /* walk contexts ... */
03026 c = ast_walk_contexts(NULL);
03027 while (c) {
03028 /* ... search for the right one ... */
03029 if (!strcmp(ast_get_context_name(c), context)) {
03030 int ret = ast_context_add_include2(c, include, registrar);
03031 /* ... unlock contexts list and return */
03032 ast_unlock_contexts();
03033 return ret;
03034 }
03035 c = ast_walk_contexts(c);
03036 }
03037
03038 /* we can't find the right context */
03039 ast_unlock_contexts();
03040 errno = ENOENT;
03041 return -1;
03042 }
|
|
||||||||||||||||
|
Add an include.
Definition at line 3336 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, ast_include::registrar, ast_include::rname, and VERBOSE_PREFIX_3. Referenced by ast_context_add_include().
03338 {
03339 struct ast_include *new_include;
03340 char *c;
03341 struct ast_include *i, *il = NULL; /* include, include_last */
03342
03343 /* allocate new include structure ... */
03344 if (!(new_include = malloc(sizeof(struct ast_include)))) {
03345 ast_log(LOG_ERROR, "Out of memory\n");
03346 errno = ENOMEM;
03347 return -1;
03348 }
03349
03350 /* ... fill in this structure ... */
03351 memset(new_include, 0, sizeof(struct ast_include));
03352 strncpy(new_include->name, value, sizeof(new_include->name)-1);
03353 strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
03354 c = new_include->rname;
03355 /* Strip off timing info */
03356 while(*c && (*c != '|')) c++;
03357 /* Process if it's there */
03358 if (*c) {
03359 build_timing(new_include, c+1);
03360 *c = '\0';
03361 }
03362 new_include->next = NULL;
03363 new_include->registrar = registrar;
03364
03365 /* ... try to lock this context ... */
03366 if (ast_mutex_lock(&con->lock)) {
03367 free(new_include);
03368 errno = EBUSY;
03369 return -1;
03370 }
03371
03372 /* ... go to last include and check if context is already included too... */
03373 i = con->includes;
03374 while (i) {
03375 if (!strcasecmp(i->name, new_include->name)) {
03376 free(new_include);
03377 ast_mutex_unlock(&con->lock);
03378 errno = EEXIST;
03379 return -1;
03380 }
03381 il = i;
03382 i = i->next;
03383 }
03384
03385 /* ... include new context into context list, unlock, return */
03386 if (il)
03387 il->next = new_include;
03388 else
03389 con->includes = new_include;
03390 if (option_verbose > 2)
03391 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
03392 ast_mutex_unlock(&con->lock);
03393
03394 return 0;
03395 }
|
|
||||||||||||||||||||
|
Add a switch.
Definition at line 3402 of file pbx.c. References ast_context_add_switch2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
03403 {
03404 struct ast_context *c;
03405
03406 if (ast_lock_contexts()) {
03407 errno = EBUSY;
03408 return -1;
03409 }
03410
03411 /* walk contexts ... */
03412 c = ast_walk_contexts(NULL);
03413 while (c) {
03414 /* ... search for the right one ... */
03415 if (!strcmp(ast_get_context_name(c), context)) {
03416 int ret = ast_context_add_switch2(c, sw, data, registrar);
03417 /* ... unlock contexts list and return */
03418 ast_unlock_contexts();
03419 return ret;
03420 }
03421 c = ast_walk_contexts(c);
03422 }
03423
03424 /* we can't find the right context */
03425 ast_unlock_contexts();
03426 errno = ENOENT;
03427 return -1;
03428 }
|
|
||||||||||||||||||||
|
Adds a switch (first param is a ast_context). See ast_context_add_switch() Definition at line 3437 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, ast_sw::registrar, and VERBOSE_PREFIX_3. Referenced by ast_context_add_switch().
03439 {
03440 struct ast_sw *new_sw;
03441 struct ast_sw *i, *il = NULL; /* sw, sw_last */
03442
03443 /* allocate new sw structure ... */
03444 if (!(new_sw = malloc(sizeof(struct ast_sw)))) {
03445 ast_log(LOG_ERROR, "Out of memory\n");
03446 errno = ENOMEM;
03447 return -1;
03448 }
03449
03450 /* ... fill in this structure ... */
03451 memset(new_sw, 0, sizeof(struct ast_sw));
03452 strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
03453 if (data)
03454 strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
03455 else
03456 strncpy(new_sw->data, "", sizeof(new_sw->data)-1);
03457 new_sw->next = NULL;
03458 new_sw->registrar = registrar;
03459
03460 /* ... try to lock this context ... */
03461 if (ast_mutex_lock(&con->lock)) {
03462 free(new_sw);
03463 errno = EBUSY;
03464 return -1;
03465 }
03466
03467 /* ... go to last sw and check if context is already swd too... */
03468 i = con->alts;
03469 while (i) {
03470 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
03471 free(new_sw);
03472 ast_mutex_unlock(&con->lock);
03473 errno = EEXIST;
03474 return -1;
03475 }
03476 il = i;
03477 i = i->next;
03478 }
03479
03480 /* ... sw new context into context list, unlock, return */
03481 if (il)
03482 il->next = new_sw;
03483 else
03484 con->alts = new_sw;
03485 if (option_verbose > 2)
03486 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
03487 ast_mutex_unlock(&con->lock);
03488
03489 return 0;
03490 }
|
|
||||||||||||||||
|
Register a new context.
Definition at line 2939 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), ast_context::ignorepats, ast_context::includes, ast_context::lock, LOG_DEBUG, LOG_ERROR, LOG_WARNING, malloc, ast_context::name, ast_context::next, ast_context::registrar, ast_context::root, and VERBOSE_PREFIX_3.
02940 {
02941 struct ast_context *tmp, **local_contexts;
02942 if (!extcontexts) {
02943 local_contexts = &contexts;
02944 ast_mutex_lock(&conlock);
02945 } else
02946 local_contexts = extcontexts;
02947
02948 tmp = *local_contexts;
02949 while(tmp) {
02950 if (!strcasecmp(tmp->name, name)) {
02951 ast_mutex_unlock(&conlock);
02952 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
02953 if (!extcontexts)
02954 ast_mutex_unlock(&conlock);
02955 return NULL;
02956 }
02957 tmp = tmp->next;
02958 }
02959 tmp = malloc(sizeof(struct ast_context));
02960 if (tmp) {
02961 memset(tmp, 0, sizeof(struct ast_context));
02962 ast_mutex_init(&tmp->lock);
02963 strncpy(tmp->name, name, sizeof(tmp->name)-1);
02964 tmp->root = NULL;
02965 tmp->registrar = registrar;
02966 tmp->next = *local_contexts;
02967 tmp->includes = NULL;
02968 tmp->ignorepats = NULL;
02969 *local_contexts = tmp;
02970 if (option_debug)
02971 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
02972 else if (option_verbose > 2)
02973 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
02974 } else
02975 ast_log(LOG_ERROR, "Out of memory\n");
02976
02977 if (!extcontexts)
02978 ast_mutex_unlock(&conlock);
02979 return tmp;
02980 }
|
|
||||||||||||
|
Destroy a context (matches the specified context (or ANY context if NULL).
Definition at line 4325 of file pbx.c. References __ast_context_destroy().
04326 {
04327 __ast_context_destroy(con,registrar);
04328 }
|
|
|
Find a context.
Definition at line 675 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().
00676 {
00677 struct ast_context *tmp;
00678 ast_mutex_lock(&conlock);
00679 if (name) {
00680 tmp = contexts;
00681 while(tmp) {
00682 if (!strcasecmp(name, tmp->name))
00683 break;
00684 tmp = tmp->next;
00685 }
00686 } else
00687 tmp = contexts;
00688 ast_mutex_unlock(&conlock);
00689 return tmp;
00690 }
|
|
||||||||||||||||||||
|
Simply remove extension from context.
Definition at line 2153 of file pbx.c. References ast_context_remove_extension2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
02154 {
02155 struct ast_context *c;
02156
02157 if (ast_lock_contexts()) return -1;
02158
02159 /* walk contexts ... */
02160 c = ast_walk_contexts(NULL);
02161 while (c) {
02162 /* ... search for the right one ... */
02163 if (!strcmp(ast_get_context_name(c), context)) {
02164 /* ... remove extension ... */
02165 int ret = ast_context_remove_extension2(c, extension, priority,
02166 registrar);
02167 /* ... unlock contexts list and return */
02168 ast_unlock_contexts();
02169 return ret;
02170 }
02171 c = ast_walk_contexts(c);
02172 }
02173
02174 /* we can't find the right context */
02175 ast_unlock_contexts();
02176 return -1;
02177 }
|
|
||||||||||||||||||||
|
Definition at line 2189 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, ast_exten::data, ast_exten::datad, 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().
02190 {
02191 struct ast_exten *exten, *prev_exten = NULL;
02192
02193 if (ast_mutex_lock(&con->lock)) return -1;
02194
02195 /* go through all extensions in context and search the right one ... */
02196 exten = con->root;
02197 while (exten) {
02198
02199 /* look for right extension */
02200 if (!strcmp(exten->exten, extension) &&
02201 (!registrar || !strcmp(exten->registrar, registrar))) {
02202 struct ast_exten *peer;
02203
02204 /* should we free all peers in this extension? (priority == 0)? */
02205 if (priority == 0) {
02206 /* remove this extension from context list */
02207 if (prev_exten)
02208 prev_exten->next = exten->next;
02209 else
02210 con->root = exten->next;
02211
02212 /* fire out all peers */
02213 peer = exten;
02214 while (peer) {
02215 exten = peer->peer;
02216
02217 if (!peer->priority==PRIORITY_HINT)
02218 ast_remove_hint(peer);
02219
02220 peer->datad(peer->data);
02221 free(peer);
02222
02223 peer = exten;
02224 }
02225
02226 ast_mutex_unlock(&con->lock);
02227 return 0;
02228 } else {
02229 /* remove only extension with exten->priority == priority */
02230 struct ast_exten *previous_peer = NULL;
02231
02232 peer = exten;
02233 while (peer) {
02234 /* is this our extension? */
02235 if (peer->priority == priority &&
02236 (!registrar || !strcmp(peer->registrar, registrar) )) {
02237 /* we are first priority extension? */
02238 if (!previous_peer) {
02239 /* exists previous extension here? */
02240 if (prev_exten) {
02241 /* yes, so we must change next pointer in
02242 * previous connection to next peer
02243 */
02244 if (peer->peer) {
02245 prev_exten->next = peer->peer;
02246 peer->peer->next = exten->next;
02247 } else
02248 prev_exten->next = exten->next;
02249 } else {
02250 /* no previous extension, we are first
02251 * extension, so change con->root ...
02252 */
02253 if (peer->peer)
02254 con->root = peer->peer;
02255 else
02256 con->root = exten->next;
02257 }
02258 } else {
02259 /* we are not first priority in extension */
02260 previous_peer->peer = peer->peer;
02261 }
02262
02263 /* now, free whole priority extension */
02264 if (peer->priority==PRIORITY_HINT)
02265 ast_remove_hint(peer);
02266 peer->datad(peer->data);
02267 free(peer);
02268
02269 ast_mutex_unlock(&con->lock);
02270 return 0;
02271 } else {
02272 /* this is not right extension, skip to next peer */
02273 previous_peer = peer;
02274 peer = peer->peer;
02275 }
02276 }
02277
02278 ast_mutex_unlock(&con->lock);
02279 return -1;
02280 }
02281 }
02282
02283 prev_exten = exten;
02284 exten = exten->next;
02285 }
02286
02287 /* we can't find right extension */
02288 ast_mutex_unlock(&con->lock);
02289 return -1;
02290 }
|
|
||||||||||||||||
|
Definition at line 3496 of file pbx.c. References ast_context_remove_ignorepat2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
03497 {
03498 struct ast_context *c;
03499
03500 if (ast_lock_contexts()) {
03501 errno = EBUSY;
03502 return -1;
03503 }
03504
03505 c = ast_walk_contexts(NULL);
03506 while (c) {
03507 if (!strcmp(ast_get_context_name(c), context)) {
03508 int ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
03509 ast_unlock_contexts();
03510 return ret;
03511 }
03512 c = ast_walk_contexts(c);
03513 }
03514
03515 ast_unlock_contexts();
03516 errno = ENOENT;
03517 return -1;
03518 }
|
|
||||||||||||||||
|
Definition at line 3520 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().
03521 {
03522 struct ast_ignorepat *ip, *ipl = NULL;
03523
03524 if (ast_mutex_lock(&con->lock)) {
03525 errno = EBUSY;
03526 return -1;
03527 }
03528
03529 ip = con->ignorepats;
03530 while (ip) {
03531 if (!strcmp(ip->pattern, ignorepat) &&
03532 (!registrar || (registrar == ip->registrar))) {
03533 if (ipl) {
03534 ipl->next = ip->next;
03535 free(ip);
03536 } else {
03537 con->ignorepats = ip->next;
03538 free(ip);
03539 }
03540 ast_mutex_unlock(&con->lock);
03541 return 0;
03542 }
03543 ipl = ip; ip = ip->next;
03544 }
03545
03546 ast_mutex_unlock(&con->lock);
03547 errno = EINVAL;
03548 return -1;
03549 }
|
|
||||||||||||||||
|
Removes an include. See add_include Definition at line 2009 of file pbx.c. References ast_context_remove_include2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
02010 {
02011 struct ast_context *c;
02012
02013 if (ast_lock_contexts()) return -1;
02014
02015 /* walk contexts and search for the right one ...*/
02016 c = ast_walk_contexts(NULL);
02017 while (c) {
02018 /* we found one ... */
02019 if (!strcmp(ast_get_context_name(c), context)) {
02020 int ret;
02021 /* remove include from this context ... */
02022 ret = ast_context_remove_include2(c, include, registrar);
02023
02024 ast_unlock_contexts();
02025
02026 /* ... return results */
02027 return ret;
02028 }
02029 c = ast_walk_contexts(c);
02030 }
02031
02032 /* we can't find the right one context */
02033 ast_unlock_contexts();
02034 return -1;
02035 }
|
|
||||||||||||||||
|
Removes an include by an ast_context structure. See add_include2 Definition at line 2045 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().
02046 {
02047 struct ast_include *i, *pi = NULL;
02048
02049 if (ast_mutex_lock(&con->lock)) return -1;
02050
02051 /* walk includes */
02052 i = con->includes;
02053 while (i) {
02054 /* find our include */
02055 if (!strcmp(i->name, include) &&
02056 (!registrar || !strcmp(i->registrar, registrar))) {
02057 /* remove from list */
02058 if (pi)
02059 pi->next = i->next;
02060 else
02061 con->includes = i->next;
02062 /* free include and return */
02063 free(i);
02064 ast_mutex_unlock(&con->lock);
02065 return 0;
02066 }
02067 pi = i;
02068 i = i->next;
02069 }
02070
02071 /* we can't find the right include */
02072 ast_mutex_unlock(&con->lock);
02073 return -1;
02074 }
|
|
||||||||||||||||||||
|
Remove a switch. Removes a switch with the given parameters Returns 0 on success, -1 on failure Definition at line 2081 of file pbx.c. References ast_context_remove_switch2(), ast_get_context_name(), ast_lock_contexts(), ast_unlock_contexts(), and ast_walk_contexts().
02082 {
02083 struct ast_context *c;
02084
02085 if (ast_lock_contexts()) return -1;
02086
02087 /* walk contexts and search for the right one ...*/
02088 c = ast_walk_contexts(NULL);
02089 while (c) {
02090 /* we found one ... */
02091 if (!strcmp(ast_get_context_name(c), context)) {
02092 int ret;
02093 /* remove switch from this context ... */
02094 ret = ast_context_remove_switch2(c, sw, data, registrar);
02095
02096 ast_unlock_contexts();
02097
02098 /* ... return results */
02099 return ret;
02100 }
02101 c = ast_walk_contexts(c);
02102 }
02103
02104 /* we can't find the right one context */
02105 ast_unlock_contexts();
02106 return -1;
02107 }
|
|
||||||||||||||||||||
|
Definition at line 2117 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().
02118 {
02119 struct ast_sw *i, *pi = NULL;
02120
02121 if (ast_mutex_lock(&con->lock)) return -1;
02122
02123 /* walk switchs */
02124 i = con->alts;
02125 while (i) {
02126 /* find our switch */
02127 if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
02128 (!registrar || !strcmp(i->registrar, registrar))) {
02129 /* remove from list */
02130 if (pi)
02131 pi->next = i->next;
02132 else
02133 con->alts = i->next;
02134 /* free switch and return */
02135 free(i);
02136 ast_mutex_unlock(&con->lock);
02137 return 0;
02138 }
02139 pi = i;
02140 i = i->next;
02141 }
02142
02143 /* we can't find the right switch */
02144 ast_mutex_unlock(&con->lock);
02145 return -1;
02146 }
|
|
|
Verifies includes in an ast_contect structure.
Definition at line 5043 of file pbx.c. References ast_context_find(), ast_get_context_name(), ast_log(), ast_walk_context_includes(), LOG_WARNING, and ast_include::rname.
05044 {
05045 struct ast_include *inc;
05046 int res = 0;
05047
05048 for (inc = ast_walk_context_includes(con, NULL); inc; inc = ast_walk_context_includes(con, inc))
05049 if (!ast_context_find(inc->rname)) {
05050 res = -1;
05051 ast_log(LOG_WARNING, "Context '%s' tries includes non-existant context '%s'\n",
05052 ast_get_context_name(con), inc->rname);
05053 }
05054 return res;
05055 }
|
|
||||||||||||
|
Tells Asterisk the State for Device is changed.
Referenced by ast_channel_free(), and ast_setstate(). |
|
||||||||||||||||||||||||
|
Execute an extension.
|
|
||||||||||||||||||||||||
|
If an extension exists, return non-zero.
Definition at line 1740 of file pbx.c. References HELPER_EXISTS. Referenced by ast_pbx_outgoing_exten(), and ast_pbx_run().
01741 {
01742 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
01743 }
|
|
||||||||||||
|
Determine if a given extension matches a given pattern (in NXX format).
Definition at line 642 of file pbx.c. References EXTENSION_MATCH_CORE. Referenced by ast_ignore_pattern().
00643 {
00644 int match;
00645 /* If they're the same return */
00646 if (!strcmp(pattern, data))
00647 return 1;
00648 EXTENSION_MATCH_CORE(data,pattern,match);
00649 /* Must be at the end of both */
00650 if (*data || (*pattern && (*pattern != '/')))
00651 match = 0;
00652 return match;
00653 }
|
|
||||||||||||
|
|
|
||||||||||||||||
|
Uses hint and devicestate callback to get the state of an extension.
Definition at line 1414 of file pbx.c.
01415 {
01416 struct ast_exten *e;
01417
01418 e = ast_hint_extension(c, context, exten);
01419 if (!e)
01420 return -1;
01421
01422 return ast_extension_state2(e);
01423 }
|
|
||||||||||||||||||||
|
Registers a state change callback.
Definition at line 1490 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, ast_state_cb_type, 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().
01492 {
01493 struct ast_hint *list;
01494 struct ast_state_cb *cblist;
01495 struct ast_exten *e;
01496
01497 /* No context and extension add callback to statecbs list */
01498 if (!context && !exten) {
01499 ast_mutex_lock(&hintlock);
01500
01501 cblist = statecbs;
01502 while (cblist) {
01503 if (cblist->callback == callback) {
01504 cblist->data = data;
01505 ast_mutex_unlock(&hintlock);
01506 }
01507 cblist = cblist->next;
01508 }
01509
01510 /* Now inserts the callback */
01511 cblist = malloc(sizeof(struct ast_state_cb));
01512 if (!cblist) {
01513 ast_mutex_unlock(&hintlock);
01514 return -1;
01515 }
01516 memset(cblist, 0, sizeof(struct ast_state_cb));
01517 cblist->id = 0;
01518 cblist->callback = callback;
01519 cblist->data = data;
01520
01521 cblist->next = statecbs;
01522 statecbs = cblist;
01523
01524 ast_mutex_unlock(&hintlock);
01525 return 0;
01526 }
01527
01528 if (!context || !exten)
01529 return -1;
01530
01531 /* This callback type is for only one hint */
01532 e = ast_hint_extension(NULL, context, exten);
01533 if (!e) {
01534 return -1;
01535 }
01536
01537 ast_mutex_lock(&hintlock);
01538 list = hints;
01539
01540 while (list) {
01541 if (list->exten == e)
01542 break;
01543 list = list->next;
01544 }
01545
01546 if (!list) {
01547 ast_mutex_unlock(&hintlock);
01548 return -1;
01549 }
01550
01551 /* Now inserts the callback */
01552 cblist = malloc(sizeof(struct ast_state_cb));
01553 if (!cblist) {
01554 ast_mutex_unlock(&hintlock);
01555 return -1;
01556 }
01557 memset(cblist, 0, sizeof(struct ast_state_cb));
01558 cblist->id = stateid++;
01559 cblist->callback = callback;
01560 cblist->data = data;
01561
01562 cblist->next = list->callbacks;
01563 list->callbacks = cblist;
01564
01565 ast_mutex_unlock(&hintlock);
01566 return cblist->id;
01567 }
|
|
||||||||||||
|
Deletes a registered state change callback by ID.
Definition at line 1569 of file pbx.c. References ast_mutex_lock, ast_mutex_unlock, ast_state_cb_type, ast_state_cb::callback, ast_hint::callbacks, free, ast_state_cb::id, ast_hint::next, and ast_state_cb::next.
01570 {
01571 struct ast_hint *list;
01572 struct ast_state_cb *cblist, *cbprev;
01573
01574 if (!id && !callback)
01575 return -1;
01576
01577 ast_mutex_lock(&hintlock);
01578
01579 /* id is zero is a callback without extension */
01580 if (!id) {
01581 cbprev = NULL;
01582 cblist = statecbs;
01583 while (cblist) {
01584 if (cblist->callback == callback) {
01585 if (!cbprev)
01586 statecbs = cblist->next;
01587 else
01588 cbprev->next = cblist->next;
01589
01590 free(cblist);
01591
01592 ast_mutex_unlock(&hintlock);
01593 return 0;
01594 }
01595 cbprev = cblist;
01596 cblist = cblist->next;
01597 }
01598
01599 ast_mutex_lock(&hintlock);
01600 return -1;
01601 }
01602
01603 /* id greater than zero is a callback with extension */
01604 list = hints;
01605 while (list) {
01606 cblist = list->callbacks;
01607 cbprev = NULL;
01608 while (cblist) {
01609 if (cblist->id==id) {
01610 if (!cbprev)
01611 list->callbacks = cblist->next;
01612 else
01613 cbprev->next = cblist->next;
01614
01615 free(cblist);
01616
01617 ast_mutex_unlock(&hintlock);
01618 return 0;
01619 }
01620 cbprev = cblist;
01621 cblist = cblist->next;
01622 }
01623 list = list->next;
01624 }
01625
01626 ast_mutex_unlock(&hintlock);
01627 return -1;
01628 }
|
|
|
Definition at line 4904 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().
04905 {
04906 return con ? con->name : NULL;
04907 }
|
|
|
Definition at line 4932 of file pbx.c. References ast_context::registrar.
04933 {
04934 return c ? c->registrar : NULL;
04935 }
|
|
|
Definition at line 4962 of file pbx.c. References ast_exten::app. Referenced by ast_device_state_changed(), and ast_get_hint().
04963 {
04964 return e ? e->app : NULL;
04965 }
|
|
|
Definition at line 4967 of file pbx.c. References ast_exten::data.
04968 {
04969 return e ? e->data : NULL;
04970 }
|
|
|
Definition at line 4957 of file pbx.c. References ast_exten::cidmatch.
04958 {
04959 return e ? e->cidmatch : NULL;
04960 }
|
|
|
Definition at line 4952 of file pbx.c. References ast_exten::matchcid.
04953 {
04954 return e ? e->matchcid : 0;
04955 }
|
|
|
Definition at line 4909 of file pbx.c. References ast_exten::exten.
04910 {
04911 return exten ? exten->exten : NULL;
04912 }
|
|
|
Definition at line 4924 of file pbx.c. References ast_exten::priority.
04925 {
04926 return exten ? exten->priority : -1;
04927 }
|
|
|
Definition at line 4937 of file pbx.c. References ast_exten::registrar.
04938 {
04939 return e ? e->registrar : NULL;
04940 }
|
|
||||||||||||||||||||||||
|
If an extension exists, return non-zero.
Definition at line 1729 of file pbx.c. References ast_get_extension_app().
01730 {
01731 struct ast_exten *e;
01732 e = ast_hint_extension(c, context, exten);
01733 if (e) {
01734 strncpy(hint, ast_get_extension_app(e), hintsize - 1);
01735 return -1;
01736 }
01737 return 0;
01738 }
|
|
|
Definition at line 4919 of file pbx.c. References ast_ignorepat::pattern.
04920 {
04921 return ip ? ip->pattern : NULL;
04922 }
|
|
|
Definition at line 4947 of file pbx.c. References ast_ignorepat::registrar.
04948 {
04949 return ip ? ip->registrar : NULL;
04950 }
|
|
|
Definition at line 4914 of file pbx.c. References ast_include::name.
04915 {
04916 return inc ? inc->name : NULL;
04917 }
|
|
|
Definition at line 4942 of file pbx.c. References ast_include::registrar.
04943 {
04944 return i ? i->registrar : NULL;
04945 }
|
|
|
Definition at line 4977 of file pbx.c. References ast_sw::data.
04978 {
04979 return sw ? sw->data : NULL;
04980 }
|
|
|
Definition at line 4972 of file pbx.c. References ast_sw::name.
04973 {
04974 return sw ? sw->name : NULL;
04975 }
|
|
|
Definition at line 4982 of file pbx.c. References ast_sw::registrar.
04983 {
04984 return sw ? sw->registrar : NULL;
04985 }
|
|
||||||||||||
|
Checks to see if a number should be ignored.
Definition at line 3614 of file pbx.c. References ast_context_find(), ast_extension_match(), ast_context::ignorepats, ast_ignorepat::next, and ast_ignorepat::pattern.
03615 {
03616 struct ast_context *con;
03617 struct ast_ignorepat *pat;
03618
03619 con = ast_context_find(context);
03620 if (con) {
03621 pat = con->ignorepats;
03622 while (pat) {
03623 if (ast_extension_match(pat->pattern, pattern))
03624 return 1;
03625 pat = pat->next;
03626 }
03627 }
03628 return 0;
03629 }
|
|
|
Locks a given context.
Definition at line 4891 of file pbx.c. References ast_mutex_lock, and ast_context::lock.
04892 {
04893 return ast_mutex_lock(&con->lock);
04894 }
|
|
|
Locks the contexts. Locks the context list Returns 0 on success, -1 on error Definition at line 4878 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().
04879 {
04880 return ast_mutex_lock(&conlock);
04881 }
|
|
||||||||||||||||||||||||
|
Looks to see if adding anything to this extension might match something. (exists ^ canmatch).
Definition at line 1750 of file pbx.c. References HELPER_MATCHMORE. Referenced by ast_pbx_run().
01751 {
01752 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_MATCHMORE);
01753 }
|
|
||||||||||||
|
Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
Definition at line 2984 of file pbx.c. References __ast_context_destroy(), ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_WARNING, ast_context::next, and ast_context::registrar.
02984 {
02985 struct ast_context *tmp, *lasttmp = NULL;
02986 tmp = *extcontexts;
02987 ast_mutex_lock(&conlock);
02988 if (registrar) {
02989 __ast_context_destroy(NULL,registrar);
02990 while (tmp) {
02991 lasttmp = tmp;
02992 tmp = tmp->next;
02993 }
02994 } else {
02995 while (tmp) {
02996 __ast_context_destroy(tmp,tmp->registrar);
02997 lasttmp = tmp;
02998 tmp = tmp->next;
02999 }
03000 }
03001 if (lasttmp) {
03002 lasttmp->next = contexts;
03003 contexts = *extcontexts;
03004 *extcontexts = NULL;
03005 } else
03006 ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
03007 ast_mutex_unlock(&conlock);
03008 return;
03009 }
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
Definition at line 4154 of file pbx.c. References ast_channel::_state, async_stat::app, app_tmp::app, async_stat::appdata, ast_hangup(), ast_log(), ast_pthread_create(), ast_request_and_dial(), AST_STATE_UP, ast_verbose(), async_stat::chan, app_tmp::chan, app_tmp::data, free, LOG_ERROR, LOG_WARNING, malloc, ast_channel::name, async_stat::p, pbx_builtin_setvar(), app_tmp::t, async_stat::timeout, timeout, type, and VERBOSE_PREFIX_4.
04155 {
04156 struct ast_channel *chan;
04157 struct async_stat *as;
04158 struct app_tmp *tmp;
04159 char *var, *vartmp;
04160 int res = -1;
04161 pthread_attr_t attr;
04162
04163 if (!app || ast_strlen_zero(app))
04164 return -1;
04165 if (sync) {
04166 chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
04167 if (chan) {
04168 pbx_builtin_setaccount(chan, account);
04169 if (variable) {
04170 vartmp = ast_strdupa(variable);
04171 for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp)) {
04172 pbx_builtin_setvar( chan, var );
04173 }
04174 }
04175 if (chan->_state == AST_STATE_UP) {
04176 res = 0;
04177 if (option_verbose > 3)
04178 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
04179 tmp = malloc(sizeof(struct app_tmp));
04180 if (tmp) {
04181 memset(tmp, 0, sizeof(struct app_tmp));
04182 strncpy(tmp->app, app, sizeof(tmp->app) - 1);
04183 strncpy(tmp->data, appdata, sizeof(tmp->data) - 1);
04184 tmp->chan = chan;
04185 if (sync > 1) {
04186 ast_pbx_run_app(tmp);
04187 } else {
04188 pthread_attr_init(&attr);
04189 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04190 if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
04191 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
04192 free(tmp);
04193 ast_hangup(chan);
04194 res = -1;
04195 }
04196 }
04197 } else {
04198 ast_log(LOG_ERROR, "Out of memory :(\n");
04199 res = -1;
04200 }
04201 } else {
04202 if (option_verbose > 3)
04203 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
04204 ast_hangup(chan);
04205 }
04206 }
04207 } else {
04208 as = malloc(sizeof(struct async_stat));
04209 if (!as)
04210 return -1;
04211 memset(as, 0, sizeof(struct async_stat));
04212 chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
04213 if (!chan) {
04214 free(as);
04215 return -1;
04216 }
04217 pbx_builtin_setaccount(chan, account);
04218 as->chan = chan;
04219 strncpy(as->app, app, sizeof(as->app) - 1);
04220 if (appdata)
04221 strncpy(as->appdata, appdata, sizeof(as->appdata) - 1);
04222 as->timeout = timeout;
04223 if (variable) {
04224 vartmp = ast_strdupa(variable);
04225 for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp))
04226 pbx_builtin_setvar( chan, var );
04227 }
04228 /* Start a new thread, and get something handling this channel. */
04229 pthread_attr_init(&attr);
04230 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04231 if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
04232 ast_log(LOG_WARNING, "Failed to start async wait\n");
04233 free(as);
04234 ast_hangup(chan);
04235 return -1;
04236 }
04237 res = 0;
04238 }
04239 return res;
04240 }
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Definition at line 4036 of file pbx.c. References __ast_request_and_dial(), ast_channel::_state, 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(), async_stat::chan, async_stat::context, ast_channel::context, async_stat::exten, ast_channel::exten, free, LOAD_OH, LOG_ERROR, LOG_WARNING, malloc, ast_channel::name, async_stat::p, pbx_builtin_setvar(), async_stat::priority, ast_channel::priority, async_stat::timeout, timeout, type, and VERBOSE_PREFIX_4.
04037 {
04038 struct ast_channel *chan;
04039 struct async_stat *as;
04040 int res = -1;
04041 char *var, *tmp;
04042 struct outgoing_helper oh;
04043 pthread_attr_t attr;
04044
04045 if (sync) {
04046 LOAD_OH(oh);
04047 chan = __ast_request_and_dial(type, format, data, timeout, reason, callerid, &oh);
04048 if (chan) {
04049 pbx_builtin_setaccount(chan, account);
04050 if (chan->_state == AST_STATE_UP) {
04051 res = 0;
04052 if (option_verbose > 3)
04053 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
04054
04055 if (sync > 1) {
04056 if (ast_pbx_run(chan)) {
04057 ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
04058 ast_hangup(chan);
04059 res = -1;
04060 }
04061 } else {
04062 if (ast_pbx_start(chan)) {
04063 ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
04064 ast_hangup(chan);
04065 res = -1;
04066 }
04067 }
04068 } else {
04069 if (option_verbose > 3)
04070 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
04071 ast_hangup(chan);
04072 }
04073 }
04074
04075 if(res < 0) { /* the call failed for some reason */
04076 /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
04077 /* check if "failed" exists */
04078 if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
04079 chan = ast_channel_alloc(0);
04080 if (chan) {
04081 strncpy(chan->name, "OutgoingSpoolFailed", sizeof(chan->name) - 1);
04082 if (context && !ast_strlen_zero(context))
04083 strncpy(chan->context, context, sizeof(chan->context) - 1);
04084 strncpy(chan->exten, "failed", sizeof(chan->exten) - 1);
04085 chan->priority = 1;
04086 if (variable) {
04087 tmp = ast_strdupa(variable);
04088 for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp)) {
04089 pbx_builtin_setvar( chan, var );
04090 }
04091 }
04092 ast_pbx_run(chan);
04093 } else
04094 ast_log(LOG_WARNING, "Can't allocate the channel structure, skipping execution of extension 'failed'\n");
04095 }
04096 }
04097 } else {
04098 as = malloc(sizeof(struct async_stat));
04099 if (!as)
04100 return -1;
04101 memset(as, 0, sizeof(struct async_stat));
04102 chan = ast_request_and_dial(type, format, data, timeout, reason, callerid);
04103 if (!chan) {
04104 free(as);
04105 return -1;
04106 }
04107 pbx_builtin_setaccount(chan, account);
04108 as->chan = chan;
04109 strncpy(as->context, context, sizeof(as->context) - 1);
04110 strncpy(as->exten, exten, sizeof(as->exten) - 1);
04111 as->priority = priority;
04112 as->timeout = timeout;
04113 if (variable) {
04114 tmp = ast_strdupa(variable);
04115 for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp))
04116 pbx_builtin_setvar( chan, var );
04117 }
04118 pthread_attr_init(&attr);
04119 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04120 if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
04121 ast_log(LOG_WARNING, "Failed to start async wait\n");
04122 free(as);
04123 ast_hangup(chan);
04124 return -1;
04125 }
04126 res = 0;
04127 }
04128 return res;
04129 }
|
|
|
Execute the PBX in the current thread.
Definition at line 1760 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, 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().
01761 {
01762 int firstpass = 1;
01763 char digit;
01764 char exten[256];
01765 int pos;
01766 int waittime;
01767 int res=0;
01768
01769 /* A little initial setup here */
01770 if (c->pbx)
01771 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
01772 c->pbx = malloc(sizeof(struct ast_pbx));
01773 if (!c->pbx) {
01774 ast_log(LOG_ERROR, "Out of memory\n");
01775 return -1;
01776 }
01777 if (c->amaflags) {
01778 if (c->cdr) {
01779 ast_log(LOG_WARNING, "%s already has a call record??\n", c->name);
01780 } else {
01781 c->cdr = ast_cdr_alloc();
01782 if (!c->cdr) {
01783 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
01784 free(c->pbx);
01785 return -1;
01786 }
01787 ast_cdr_init(c->cdr, c);
01788 }
01789 }
01790 memset(c->pbx, 0, sizeof(struct ast_pbx));
01791 /* Set reasonable defaults */
01792 c->pbx->rtimeout = 10;
01793 c->pbx->dtimeout = 5;
01794
01795 /* Start by trying whatever the channel is set to */
01796 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01797 /* JK02: If not successfull fall back to 's' */
01798 if (option_verbose > 1)
01799 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);
01800 strncpy(c->exten, "s", sizeof(c->exten)-1);
01801 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01802 /* JK02: And finally back to default if everything else failed */
01803 if (option_verbose > 1)
01804 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);
01805 strncpy(c->context, "default", sizeof(c->context)-1);
01806 }
01807 c->priority = 1;
01808 }
01809 if (c->cdr)
01810 ast_cdr_start(c->cdr);
01811 for(;;) {
01812 pos = 0;
01813 digit = 0;
01814 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01815 memset(exten, 0, sizeof(exten));
01816 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
01817 /* Something bad happened, or a hangup has been requested. */
01818 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
01819 (res == '*') || (res == '#')) {
01820 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
01821 memset(exten, 0, sizeof(exten));
01822 pos = 0;
01823 exten[pos++] = digit = res;
01824 break;
01825 }
01826 switch(res) {
01827 case AST_PBX_KEEPALIVE:
01828 if (option_debug)
01829 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
01830 else if (option_verbose > 1)
01831 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
01832 goto out;
01833 break;
01834 default:
01835 if (option_debug)
01836 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01837 else if (option_verbose > 1)
01838 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01839 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
01840 c->_softhangup =0;
01841 break;
01842 }
01843 /* atimeout */
01844 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
01845 break;
01846 }
01847
01848 if (c->cdr) {
01849 ast_cdr_update(c);
01850 }
01851 goto out;
01852 }
01853 }
01854 if ((c->_softhangup == AST_SOFTHANGUP_TIMEOUT) && (ast_exists_extension(c,c->context,"T",1,c->callerid))) {
01855 strncpy(c->exten,"T",sizeof(c->exten) - 1);
01856 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
01857 c->whentohangup = 0;
01858 c->priority = 0;
01859 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
01860 } else if (c->_softhangup) {
01861 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
01862 c->exten, c->priority);
01863 goto out;
01864 }
01865 firstpass = 0;
01866 c->priority++;
01867 }
01868 if (!ast_exists_extension(c, c->context, c->exten, 1, c->callerid)) {
01869 /* It's not a valid extension anymore */
01870 if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
01871 if (option_verbose > 2)
01872 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
01873 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
01874 strncpy(c->exten, "i", sizeof(c->exten)-1);
01875 c->priority = 1;
01876 } else {
01877 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
01878 c->name, c->exten, c->context);
01879 goto out;
01880 }
01881 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
01882 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
01883 c->_softhangup = 0;
01884 } else {
01885 /* Done, wait for an extension */
01886 if (digit)
01887 waittime = c->pbx->dtimeout;
01888 else
01889 waittime = c->pbx->rtimeout;
01890 while (ast_matchmore_extension(c, c->context, exten, 1, c->callerid)) {
01891 /* As long as we're willing to wait, and as long as it's not defined,
01892 keep reading digits until we can't possibly get a right answer anymore. */
01893 digit = ast_waitfordigit(c, waittime * 1000);
01894 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
01895 c->_softhangup = 0;
01896 } else {
01897 if (!digit)
01898 /* No entry */
01899 break;
01900 if (digit < 0)
01901 /* Error, maybe a hangup */
01902 goto out;
01903 exten[pos++] = digit;
01904 waittime = c->pbx->dtimeout;
01905 }
01906 }
01907 if (ast_exists_extension(c, c->context, exten, 1, c->callerid)) {
01908 /* Prepare the next cycle */
01909 strncpy(c->exten, exten, sizeof(c->exten)-1);
01910 c->priority = 1;
01911 } else {
01912 /* No such extension */
01913 if (!ast_strlen_zero(exten)) {
01914 /* An invalid extension */
01915 if (ast_exists_extension(c, c->context, "i", 1, c->callerid)) {
01916 if (option_verbose > 2)
01917 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", exten, c->context, c->name);
01918 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", exten);
01919 strncpy(c->exten, "i", sizeof(c->exten)-1);
01920 c->priority = 1;
01921 } else {
01922 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", exten, c->context);
01923 goto out;
01924 }
01925 } else {
01926 /* A simple timeout */
01927 if (ast_exists_extension(c, c->context, "t", 1, c->callerid)) {
01928 if (option_verbose > 2)
01929 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
01930 strncpy(c->exten, "t", sizeof(c->exten)-1);
01931 c->priority = 1;
01932 } else {
01933 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
01934 goto out;
01935 }
01936 }
01937 }
01938 if (c->cdr) {
01939 if (option_verbose > 2)
01940 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);
01941 ast_cdr_update(c);
01942 }
01943 }
01944 }
01945 if (firstpass)
01946 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
01947 out:
01948 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->callerid)) {
01949 c->exten[0] = 'h';
01950 c->exten[1] = '\0';
01951 c->priority = 1;
01952 while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
01953 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
01954 /* Something bad happened, or a hangup has been requested. */
01955 if (option_debug)
01956 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01957 else if (option_verbose > 1)
01958 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
01959 break;
01960 }
01961 c->priority++;
01962 }
01963 }
01964
01965 pbx_destroy(c->pbx);
01966 c->pbx = NULL;
01967 if (res != AST_PBX_KEEPALIVE)
01968 ast_hangup(c);
01969 return 0;
01970 }
|
|
|
Create a new thread and start the PBX (or whatever).
Definition at line 1985 of file pbx.c. References ast_log(), ast_pthread_create(), and LOG_WARNING. Referenced by ast_async_goto(), and ast_pbx_outgoing_exten().
01986 {
01987 pthread_t t;
01988 pthread_attr_t attr;
01989 if (!c) {
01990 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
01991 return -1;
01992 }
01993
01994 /* Start a new thread, and get something handling this channel. */
01995 pthread_attr_init(&attr);
01996 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01997 if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
01998 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
01999 return -1;
02000 }
02001 return 0;
02002 }
|
|
||||||||||||||||||||
|
Add an application. The function 'execute' should return non-zero if the line needs to be hung up.
Definition at line 2293 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), COLOR_BRCYAN, ast_app::description, description(), ast_app::execute, LOG_ERROR, LOG_WARNING, malloc, ast_app::name, ast_app::next, ast_app::synopsis, term_color(), and VERBOSE_PREFIX_2. Referenced by load_pbx().
02294 {
02295 struct ast_app *tmp, *prev, *cur;
02296 char tmps[80];
02297 if (ast_mutex_lock(&applock)) {
02298 ast_log(LOG_ERROR, "Unable to lock application list\n");
02299 return -1;
02300 }
02301 tmp = apps;
02302 while(tmp) {
02303 if (!strcasecmp(app, tmp->name)) {
02304 ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
02305 ast_mutex_unlock(&applock);
02306 return -1;
02307 }
02308 tmp = tmp->next;
02309 }
02310 tmp = malloc(sizeof(struct ast_app));
02311 if (tmp) {
02312 memset(tmp, 0, sizeof(struct ast_app));
02313 strncpy(tmp->name, app, sizeof(tmp->name)-1);
02314 tmp->execute = execute;
02315 tmp->synopsis = synopsis;
02316 tmp->description = description;
02317 /* Store in alphabetical order */
02318 cur = apps;
02319 prev = NULL;
02320 while(cur) {
02321 if (strcasecmp(tmp->name, cur->name) < 0)
02322 break;
02323 prev = cur;
02324 cur = cur->next;
02325 }
02326 if (prev) {
02327 tmp->next = prev->next;
02328 prev->next = tmp;
02329 } else {
02330 tmp->next = apps;
02331 apps = tmp;
02332 }
02333 } else {
02334 ast_log(LOG_ERROR, "Out of memory\n");
02335 ast_mutex_unlock(&applock);
02336 return -1;
02337 }
02338 if (option_verbose > 1)
02339 ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
02340 ast_mutex_unlock(&applock);
02341 return 0;
02342 }
|
|
|
Register an alternative switch.
Definition at line 2344 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_ERROR, LOG_WARNING, ast_switch::name, and ast_switch::next.
02345 {
02346 struct ast_switch *tmp, *prev=NULL;
02347 if (ast_mutex_lock(&switchlock)) {
02348 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02349 return -1;
02350 }
02351 tmp = switches;
02352 while(tmp) {
02353 if (!strcasecmp(tmp->name, sw->name))
02354 break;
02355 prev = tmp;
02356 tmp = tmp->next;
02357 }
02358 if (tmp) {
02359 ast_mutex_unlock(&switchlock);
02360 ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
02361 return -1;
02362 }
02363 sw->next = NULL;
02364 if (prev)
02365 prev->next = sw;
02366 else
02367 switches = sw;
02368 ast_mutex_unlock(&switchlock);
02369 return 0;
02370 }
|
|
||||||||||||||||||||||||
|
Launch a new extension (i.e. new stack).
Definition at line 1755 of file pbx.c. References HELPER_SPAWN. Referenced by ast_pbx_run().
01756 {
01757 return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_SPAWN);
01758 }
|
|
|
Unlocks the given context.
Definition at line 4896 of file pbx.c. References ast_mutex_unlock, and ast_context::lock.
04897 {
04898 return ast_mutex_unlock(&con->lock);
04899 }
|
|
|
Unlocks contexts. Returns 0 on success, -1 on failure Definition at line 4883 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().
04884 {
04885 return ast_mutex_unlock(&conlock);
04886 }
|
|
|
Remove an application.
Definition at line 2913 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), free, LOG_ERROR, ast_app::name, ast_app::next, and VERBOSE_PREFIX_2.
02913 {
02914 struct ast_app *tmp, *tmpl = NULL;
02915 if (ast_mutex_lock(&applock)) {
02916 ast_log(LOG_ERROR, "Unable to lock application list\n");
02917 return -1;
02918 }
02919 tmp = apps;
02920 while(tmp) {
02921 if (!strcasecmp(app, tmp->name)) {
02922 if (tmpl)
02923 tmpl->next = tmp->next;
02924 else
02925 apps = tmp->next;
02926 if (option_verbose > 1)
02927 ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
02928 free(tmp);
02929 ast_mutex_unlock(&applock);
02930 return 0;
02931 }
02932 tmpl = tmp;
02933 tmp = tmp->next;
02934 }
02935 ast_mutex_unlock(&applock);
02936 return -1;
02937 }
|
|
|
Unregister an alternative switch.
Definition at line 2372 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_ERROR, and ast_switch::next.
02373 {
02374 struct ast_switch *tmp, *prev=NULL;
02375 if (ast_mutex_lock(&switchlock)) {
02376 ast_log(LOG_ERROR, "Unable to lock switch lock\n");
02377 return;
02378 }
02379 tmp = switches;
02380 while(tmp) {
02381 if (tmp == sw) {
02382 if (prev)
02383 prev->next = tmp->next;
02384 else
02385 switches = tmp->next;
02386 tmp->next = NULL;
02387 break;
02388 }
02389 prev = tmp;
02390 tmp = tmp->next;
02391 }
02392 ast_mutex_unlock(&switchlock);
02393 }
|
|
||||||||||||
|
Definition at line 4998 of file pbx.c. References ast_exten::next.
|
|
||||||||||||
|
Definition at line 5034 of file pbx.c. References ast_ignorepat::next.
05036 {
05037 if (!ip)
05038 return con ? con->ignorepats : NULL;
05039 else
05040 return ip->next;
05041 }
|
|
||||||||||||
|
Definition at line 5025 of file pbx.c. References ast_include::next. Referenced by ast_context_verify_includes().
|
|
||||||||||||
|
Definition at line 5007 of file pbx.c. References ast_sw::next.
|
|
|
Definition at line 4990 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().
04991 {
04992 if (!con)
04993 return contexts;
04994 else
04995 return con->next;
04996 }
|
|
||||||||||||
|
Definition at line 5016 of file pbx.c. References ast_exten::peer.
05018 {
05019 if (!priority)
05020 return exten;
05021 else
05022 return priority->peer;
05023 }
|
|
|
Definition at line 4751 of file pbx.c. References AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_REMOVE_HEAD, and ast_var_delete().
04752 {
04753 struct ast_var_t *vardata;
04754 while (!AST_LIST_EMPTY(&globals)) {
04755 vardata = AST_LIST_FIRST(&globals);
04756 AST_LIST_REMOVE_HEAD(&globals, entries);
04757 ast_var_delete(vardata);
04758 }
04759 }
|
|
||||||||||||
|
|
|
||||||||||||
|
Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten(). |
|
||||||||||||||||
|
Referenced by ast_pbx_run(), and pbx_builtin_setvar(). |
|
||||||||||||||||||||
|
executes an application.
Definition at line 425 of file pbx.c. References ast_cdr_setapp(), AST_CHANNEL_MAX_STACK, ast_log(), and LOG_WARNING.
00429 {
00430 /* This function is special. It saves the stack so that no matter
00431 how many times it is called, it returns to the same place */
00432 int res;
00433
00434 char *saved_c_appl;
00435 char *saved_c_data;
00436
00437 int stack = c->stack;
00438 int (*execute)(struct ast_channel *chan, void *data) = app->execute;
00439
00440 if (newstack && stack > AST_CHANNEL_MAX_STACK - 2) {
00441 /* Don't allow us to go over the max number of stacks we
00442 permit saving. */
00443 ast_log(LOG_WARNING, "Stack overflow, cannot create another stack\n");
00444 return -1;
00445 }
00446 if (newstack && (res = setjmp(c->jmp[++c->stack]))) {
00447 /* Okay, here's where it gets weird. If newstack is non-zero,
00448 then we increase the stack increment, but setjmp is not going
00449 to return until longjmp is called -- when the application
00450 exec'd is finished running. */
00451 if (res == 1)
00452 res = 0;
00453 if (c->stack != stack + 1)
00454 ast_log(LOG_WARNING, "Stack returned to an unexpected place!\n");
00455 else if (c->app[c->stack])
00456 ast_log(LOG_WARNING, "Application may have forgotten to free its memory\n");
00457 c->stack = stack;
00458 return res;
00459 } else {
00460 if (c->cdr)
00461 ast_cdr_setapp(c->cdr, app->name, data);
00462
00463 /* save channel values */
00464 saved_c_appl= c->appl;
00465 saved_c_data= c->data;
00466
00467 c->appl = app->name;
00468 c->data = data;
00469 res = execute(c, data);
00470 /* restore channel values */
00471 c->appl= saved_c_appl;
00472 c->data= saved_c_data;
00473
00474 /* Any application that returns, we longjmp back, just in case. */
00475 if (c->stack != stack + 1)
00476 ast_log(LOG_WARNING, "Stack is not at expected value\n");
00477 longjmp(c->jmp[stack+1], res);
00478 /* Never returns */
00479 }
00480 }
|
|
|
Look up an application.
Definition at line 492 of file pbx.c. References ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_WARNING, ast_app::name, and ast_app::next.
00493 {
00494 struct ast_app *tmp;
00495
00496 if (ast_mutex_lock(&applock)) {
00497 ast_log(LOG_WARNING, "Unable to obtain application lock\n");
00498 return NULL;
00499 }
00500 tmp = apps;
00501 while(tmp) {
00502 if (!strcasecmp(tmp->name, app))
00503 break;
00504 tmp = tmp->next;
00505 }
00506 ast_mutex_unlock(&applock);
00507 return tmp;
00508 }
|
|
||||||||||||||||||||
|
Definition at line 1031 of file pbx.c. References ast_expr(), ast_log(), free, LOG_DEBUG, and LOG_NOTICE.
01032 {
01033 char *cp4;
01034 const char *tmp, *whereweare;
01035 int length;
01036 char workspace[4096];
01037 char ltmp[4096], var[4096];
01038 char *nextvar, *nextexp;
01039 char *vars, *vare;
01040 int pos, brackets, needsub, len;
01041
01042 /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
01043 zero-filled */
01044 whereweare=tmp=cp1;
01045 while(!ast_strlen_zero(whereweare) && count) {
01046 /* Assume we're copying the whole remaining string */
01047 pos = strlen(whereweare);
01048
01049 /* Look for a variable */
01050 nextvar = strstr(whereweare, "${");
01051
01052 /* Look for an expression */
01053 nextexp = strstr(whereweare, "$[");
01054
01055 /* Pick the first one only */
01056 if (nextvar && nextexp) {
01057 if (nextvar < nextexp)
01058 nextexp = NULL;
01059 else
01060 nextvar = NULL;
01061 }
01062
01063 /* If there is one, we only go that far */
01064 if (nextvar)
01065 pos = nextvar - whereweare;
01066 else if (nextexp)
01067 pos = nextexp - whereweare;
01068
01069 /* Can't copy more than 'count' bytes */
01070 if (pos > count)
01071 pos = count;
01072
01073 /* Copy that many bytes */
01074 memcpy(cp2, whereweare, pos);
01075
01076 count -= pos;
01077 cp2 += pos;
01078 whereweare += pos;
01079
01080 if (nextvar) {
01081 /* We have a variable. Find the start and end, and determine
01082 if we are going to have to recursively call ourselves on the
01083 contents */
01084 vars = vare = nextvar + 2;
01085 brackets = 1;
01086 needsub = 0;
01087
01088 /* Find the end of it */
01089 while(brackets && *vare) {
01090 if ((vare[0] == '$') && (vare[1] == '{')) {
01091 needsub++;
01092 brackets++;
01093 } else if (vare[0] == '}') {
01094 brackets--;
01095 } else if ((vare[0] == '$') && (vare[1] == '['))
01096 needsub++;
01097 vare++;
01098 }
01099 if (brackets)
01100 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
01101 len = vare - vars - 1;
01102
01103 /* Skip totally over variable name */
01104 whereweare += ( len + 3);
01105
01106 /* Store variable name (and truncate) */
01107 memset(var, 0, sizeof(var));
01108 strncpy(var, vars, sizeof(var) - 1);
01109 var[len] = '\0';
01110
01111 /* Substitute if necessary */
01112 if (needsub) {
01113 memset(ltmp, 0, sizeof(ltmp));
01114 pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
01115 vars = ltmp;
01116 } else {
01117 vars = var;
01118 }
01119
01120 /* Retrieve variable value */
01121 workspace[0] = '\0';
01122 pbx_substitute_variables_temp(c,vars,&cp4, workspace, sizeof(workspace));
01123 if (cp4) {
01124 length = strlen(cp4);
01125 if (length > count)
01126 length = count;
01127 memcpy(cp2, cp4, length);
01128 count -= length;
01129 cp2 += length;
01130 }
01131
01132 } else if (nextexp) {
01133 /* We have an expression. Find the start and end, and determine
01134 if we are going to have to recursively call ourselves on the
01135 contents */
01136 vars = vare = nextexp + 2;
01137 brackets = 1;
01138 needsub = 0;
01139
01140 /* Find the end of it */
01141 while(brackets && *vare) {
01142 if ((vare[0] == '$') && (vare[1] == '[')) {
01143 needsub++;
01144 brackets++;
01145 vare++;
01146 } else if (vare[0] == '[') {
01147 brackets++;
01148 } else if (vare[0] == ']') {
01149 brackets--;
01150 } else if ((vare[0] == '$') && (vare[1] == '{')) {
01151 needsub++;
01152 vare++;
01153 }
01154 vare++;
01155 }
01156 if (brackets)
01157 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
01158 len = vare - vars - 1;
01159
01160 /* Skip totally over variable name */
01161 whereweare += ( len + 3);
01162
01163 /* Store variable name (and truncate) */
01164 memset(var, 0, sizeof(var));
01165 strncpy(var, vars, sizeof(var) - 1);
01166 var[len] = '\0';
01167
01168 /* Substitute if necessary */
01169 if (needsub) {
01170 memset(ltmp, 0, sizeof(ltmp));
01171 pbx_substitute_variables_helper(c, var, ltmp, sizeof(ltmp) - 1);
01172 vars = ltmp;
01173 } else {
01174 vars = var;
01175 }
01176
01177 /* Evaluate expression */
01178 cp4 = ast_expr(vars);
01179
01180 ast_log(LOG_DEBUG, "Expression is '%s'\n", cp4);
01181
01182 if (cp4) {
01183 length = strlen(cp4);
01184 if (length > count)
01185 length = count;
01186 memcpy(cp2, cp4, length);
01187 count -= length;
01188 cp2 += length;
01189 free(cp4);
01190 }
01191
01192 } else
01193 break;
01194 }
01195 }
|
1.2.15