![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
pbx.c File Reference
Definition in file pbx.c.
#include "asterisk.h"
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <limits.h>
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
#include "asterisk/options.h"
#include "asterisk/logger.h"
#include "asterisk/file.h"
#include "asterisk/callerid.h"
#include "asterisk/cdr.h"
#include "asterisk/config.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/ast_expr.h"
#include "asterisk/linkedlists.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
Include dependency graph for pbx.c:

Go to the source code of this file.
Data Structures | |
| struct | app_tmp |
| struct | ast_app |
| ast_app: A registered application More... | |
| struct | ast_context |
| ast_context: An extension context More... | |
| struct | ast_exten |
| ast_exten: An extension The dialplan is saved as a linked list with each context having it's own linked list of extensions - one item per priority. More... | |
| struct | ast_hint |
| Structure for dial plan hints. More... | |
| struct | ast_ignorepat |
| ast_ignorepat: Ignore patterns in dial plan More... | |
| struct | ast_include |
| ast_include: include= support in extensions.conf More... | |
| struct | ast_state_cb |
| ast_state_cb: An extension state notify register item More... | |
| struct | ast_sw |
| ast_sw: Switch statement in extensions.conf More... | |
| struct | async_stat |
| struct | cfextension_states |
| struct | dialplan_counters |
| Counters for the show dialplan manager command. More... | |
| struct | pbx_builtin |
| Declaration of builtin applications. More... | |
| struct | pbx_find_info |
| struct | store_hint |
Defines | |
| #define | AST_PBX_MAX_STACK 128 |
| #define | BACKGROUND_MATCHEXTEN (1 << 2) |
| #define | BACKGROUND_NOANSWER (1 << 1) |
| #define | BACKGROUND_PLAYBACK (1 << 3) |
| #define | BACKGROUND_SKIP (1 << 0) |
| #define | EXT_DATA_SIZE 8192 |
| #define | SAY_STUBS |
| #define | STATUS_NO_CONTEXT 1 |
| #define | STATUS_NO_EXTENSION 2 |
| #define | STATUS_NO_LABEL 4 |
| #define | STATUS_NO_PRIORITY 3 |
| #define | STATUS_SUCCESS 5 |
| #define | SWITCH_DATA_LENGTH 256 |
| #define | VAR_BUF_SIZE 4096 |
| #define | VAR_HARDTRAN 3 |
| #define | VAR_NORMAL 1 |
| #define | VAR_SOFTTRAN 2 |
| #define | WAITEXTEN_MOH (1 << 0) |
Enumerations | |
| enum | ext_match_t { E_MATCHMORE = 0x00, E_CANMATCH = 0x01, E_MATCH = 0x02, E_MATCH_MASK = 0x03, E_SPAWN = 0x12, E_FINDLABEL = 0x22 } |
Functions | |
| static struct ast_context * | __ast_context_create (struct ast_context **extcontexts, const char *name, const char *registrar, int existsokay) |
| void | __ast_context_destroy (struct ast_context *con, const char *registrar) |
| static int | __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async) |
| static int | __ast_pbx_run (struct ast_channel *c) |
| static int | _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
| static int | add_pri (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace) |
| add the extension in the priority chain. returns 0 on success, -1 on failure | |
| int | ast_active_calls (void) |
| Retrieve the number of active calls. | |
| int | ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
| Add and extension to an extension context. | |
| int | ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar) |
| Add an extension to an extension context, this time with an ast_context *. | |
| static int | ast_add_hint (struct ast_exten *e) |
| ast_add_hint: Add hint to hint list, check initial extension state | |
| AST_APP_OPTIONS (resetcdr_opts,{AST_APP_OPTION('w', AST_CDR_FLAG_POSTED), AST_APP_OPTION('a', AST_CDR_FLAG_LOCKED), AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS),}) | |
| AST_APP_OPTIONS (waitexten_opts,{AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 0),}) | |
| AST_APP_OPTIONS (background_opts,{AST_APP_OPTION('s', BACKGROUND_SKIP), AST_APP_OPTION('n', BACKGROUND_NOANSWER), AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN), AST_APP_OPTION('p', BACKGROUND_PLAYBACK),}) | |
| int | ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority) |
| int | ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_build_timing (struct ast_timing *i, const char *info_in) |
| int | ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Looks for a valid matching extension. | |
| static int | ast_change_hint (struct ast_exten *oe, struct ast_exten *ne) |
| ast_change_hint: Change hint for an extension | |
| int | ast_check_timing (const struct ast_timing *i) |
| int | ast_context_add_ignorepat (const char *context, const char *value, const char *registrar) |
| Add an ignorepat. | |
| int | ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar) |
| int | ast_context_add_include (const char *context, const char *include, const char *registrar) |
| Add a context include. | |
| int | ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar) |
| Add a context include. | |
| int | ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar) |
| Add a switch. | |
| int | ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar) |
| Adds a switch (first param is a ast_context). | |
| ast_context * | ast_context_create (struct ast_context **extcontexts, const char *name, const char *registrar) |
| Register a new context. | |
| void | ast_context_destroy (struct ast_context *con, const char *registrar) |
| Destroy a context (matches the specified context (or ANY context if NULL). | |
| ast_context * | ast_context_find (const char *name) |
| Find a context. | |
| ast_context * | ast_context_find_or_create (struct ast_context **extcontexts, const char *name, const char *registrar) |
| Register a new context or find an existing one. | |
| int | ast_context_lockmacro (const char *context) |
| locks the macrolock in the given given context | |
| int | ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar) |
| Simply remove extension from context. | |
| int | ast_context_remove_extension2 (struct ast_context *con, const char *extension, int priority, const char *registrar) |
| This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return. | |
| int | ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar) |
| int | ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar) |
| int | ast_context_remove_include (const char *context, const char *include, const char *registrar) |
| Remove a context include. | |
| int | ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar) |
| Removes an include by an ast_context structure. | |
| int | ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar) |
| Remove a switch. | |
| int | ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar) |
| This function locks given context, removes switch, unlock context and return. | |
| int | ast_context_unlockmacro (const char *context) |
| Unlocks the macrolock in the given context. | |
| int | ast_context_verify_includes (struct ast_context *con) |
| Verifies includes in an ast_contect structure. | |
| ast_custom_function * | ast_custom_function_find (const char *name) |
| int | ast_custom_function_register (struct ast_custom_function *acf) |
| Reigster a custom function. | |
| int | ast_custom_function_unregister (struct ast_custom_function *acf) |
| Unregister a custom function. | |
| int | ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Determine whether an extension exists. | |
| int | ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| int | ast_extension_close (const char *pattern, const char *data, int needmore) |
| int | ast_extension_match (const char *pattern, const char *data) |
| Determine if a given extension matches a given pattern (in NXX format). | |
| int | ast_extension_state (struct ast_channel *c, const char *context, const char *exten) |
| Uses hint and devicestate callback to get the state of an extension. | |
| static int | ast_extension_state2 (struct ast_exten *e) |
| ast_extensions_state2: Check state of extension by using hints | |
| const char * | ast_extension_state2str (int extension_state) |
| Return string representation of the state of an extension. | |
| int | ast_extension_state_add (const char *context, const 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_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid) |
| Find the priority of an extension that has the specified label. | |
| int | ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid) |
| Find the priority of an extension that has the specified label. | |
| int | ast_func_read (struct ast_channel *chan, const char *function, char *workspace, size_t len) |
| executes a read operation on a function | |
| int | ast_func_write (struct ast_channel *chan, const char *function, const char *value) |
| executes a write operation on a function | |
| const char * | ast_get_context_name (struct ast_context *con) |
| const char * | ast_get_context_registrar (struct ast_context *c) |
| const char * | ast_get_extension_app (struct ast_exten *e) |
| void * | ast_get_extension_app_data (struct ast_exten *e) |
| const char * | ast_get_extension_cidmatch (struct ast_exten *e) |
| ast_context * | ast_get_extension_context (struct ast_exten *exten) |
| const char * | ast_get_extension_label (struct ast_exten *exten) |
| int | ast_get_extension_matchcid (struct ast_exten *e) |
| const char * | ast_get_extension_name (struct ast_exten *exten) |
| int | ast_get_extension_priority (struct ast_exten *exten) |
| const char * | ast_get_extension_registrar (struct ast_exten *e) |
| int | ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten) |
| If an extension hint exists, return non-zero. | |
| const char * | ast_get_ignorepat_name (struct ast_ignorepat *ip) |
| const char * | ast_get_ignorepat_registrar (struct ast_ignorepat *ip) |
| const char * | ast_get_include_name (struct ast_include *inc) |
| const char * | ast_get_include_registrar (struct ast_include *i) |
| const char * | ast_get_switch_data (struct ast_sw *sw) |
| const char * | ast_get_switch_name (struct ast_sw *sw) |
| const char * | ast_get_switch_registrar (struct ast_sw *sw) |
| int | ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority) |
| static struct ast_exten * | ast_hint_extension (struct ast_channel *c, const char *context, const char *exten) |
| ast_hint_extension: Find hint for given extension in context | |
| void | ast_hint_state_changed (const char *device) |
| int | ast_ignore_pattern (const char *context, const char *pattern) |
| Checks to see if a number should be ignored. | |
| AST_LIST_HEAD (store_hints, store_hint) | |
| int | ast_lock_context (struct ast_context *con) |
| Locks a given context. | |
| int | ast_lock_contexts () |
| Locks the context list. | |
| int | ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Looks to see if adding anything to this extension might match something. (exists ^ canmatch). | |
| void | ast_merge_contexts_and_delete (struct ast_context **extcontexts, const char *registrar) |
| Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added. | |
| AST_MUTEX_DEFINE_STATIC (conlock) | |
| AST_MUTEX_DEFINE_STATIC (maxcalllock) | |
| int | ast_parseable_goto (struct ast_channel *chan, const char *goto_string) |
| int | ast_pbx_outgoing_app (const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel) |
| static int | ast_pbx_outgoing_cdr_failed (void) |
| int | ast_pbx_outgoing_exten (const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel) |
| enum ast_pbx_result | ast_pbx_run (struct ast_channel *c) |
| Execute the PBX in the current thread. | |
| static void * | ast_pbx_run_app (void *data) |
| run the application and free the descriptor once done | |
| enum ast_pbx_result | ast_pbx_start (struct ast_channel *c) |
| Create a new thread and start the PBX. | |
| int | ast_register_application (const char *app, int(*execute)(struct ast_channel *, void *), const char *synopsis, const char *description) |
| Register an application. | |
| int | ast_register_switch (struct ast_switch *sw) |
| Register an alternative dialplan switch. | |
| static int | ast_remove_hint (struct ast_exten *e) |
| ast_remove_hint: Remove hint from extension | |
| static | AST_RWLIST_HEAD_STATIC (hints, ast_hint) |
| static | AST_RWLIST_HEAD_STATIC (switches, ast_switch) |
| static | AST_RWLIST_HEAD_STATIC (apps, ast_app) |
| static | AST_RWLIST_HEAD_STATIC (acf_root, ast_custom_function) |
| AST_RWLOCK_DEFINE_STATIC (globalslock) | |
| int | ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid) |
| Launch a new extension (i.e. new stack). | |
| int | ast_unlock_context (struct ast_context *con) |
| int | ast_unlock_contexts () |
| Unlocks contexts. | |
| int | ast_unregister_application (const char *app) |
| Unregister an application. | |
| void | ast_unregister_switch (struct ast_switch *sw) |
| Unregister an alternative switch. | |
| ast_exten * | ast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten) |
| ast_ignorepat * | ast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip) |
| ast_include * | ast_walk_context_includes (struct ast_context *con, struct ast_include *inc) |
| ast_sw * | ast_walk_context_switches (struct ast_context *con, struct ast_sw *sw) |
| ast_context * | ast_walk_contexts (struct ast_context *con) |
| ast_exten * | ast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority) |
| static void * | async_wait (void *data) |
| static int | collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos) |
| collect digits from the channel into the buffer, return -1 on error, 0 on timeout or done. | |
| static char * | complete_show_application (const char *line, const char *word, int pos, int state) |
| static char * | complete_show_applications (const char *line, const char *word, int pos, int state) |
| static char * | complete_show_dialplan_context (const char *line, const char *word, int pos, int state) |
| static char * | complete_show_function (const char *line, const char *word, int pos, int state) |
| static void | decrease_call_count (void) |
| static void | destroy_exten (struct ast_exten *e) |
| static int | ext_cmp (const char *a, const char *b) |
| the full routine to compare extensions in rules. | |
| static int | ext_cmp1 (const char **p) |
| helper functions to sort extensions and patterns in the desired way, so that more specific patterns appear first. | |
| static int | ext_strncpy (char *dst, const char *src, int len) |
| copy a string skipping whitespace | |
| static int | extension_match_core (const char *pattern, const char *data, enum ext_match_t mode) |
| static struct ast_context * | find_context_locked (const char *context) |
| static char * | func_args (char *function) |
| return a pointer to the arguments of the function, and terminates the function name with '\0' | |
| static unsigned | get_range (char *src, int max, char *const names[], const char *msg) |
| helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers. | |
| static void | get_timerange (struct ast_timing *i, char *times) |
| store a bitmask of valid times, one bit each 2 minute | |
| static int | handle_set_global (int fd, int argc, char *argv[]) |
| static int | handle_show_application (int fd, int argc, char *argv[]) |
| static int | handle_show_applications (int fd, int argc, char *argv[]) |
| static int | handle_show_dialplan (int fd, int argc, char *argv[]) |
| static int | handle_show_function (int fd, int argc, char *argv[]) |
| static int | handle_show_functions (int fd, int argc, char *argv[]) |
| static int | handle_show_globals (int fd, int argc, char *argv[]) |
| CLI support for listing global variables in a parseable way. | |
| static int | handle_show_hints (int fd, int argc, char *argv[]) |
| handle_show_hints: CLI support for listing registered dial plan hints | |
| static int | handle_show_switches (int fd, int argc, char *argv[]) |
| handle_show_switches: CLI support for listing registered dial plan switches | |
| static int | include_valid (struct ast_include *i) |
| static int | increase_call_count (const struct ast_channel *c) |
| int | load_pbx (void) |
| static int | lookup_name (const char *s, char *const names[], int max) |
| Helper for get_range. return the index of the matching entry, starting from 1. If names is not supplied, try numeric values. | |
| static void | manager_dpsendack (struct mansession *s, const struct message *m) |
| Send ack once. | |
| static int | manager_show_dialplan (struct mansession *s, const struct message *m) |
| Manager listing of dial plan. | |
| static int | manager_show_dialplan_helper (struct mansession *s, const struct message *m, const char *actionidtext, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude) |
| Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dialplan. Must check whether the difference is intentional or not. | |
| static int | matchcid (const char *cidpattern, const char *callerid) |
| static int | parse_variable_name (char *var, int *offset, int *length, int *isfunc) |
| extract offset:length from variable name. Returns 1 if there is a offset:length part, which is trimmed off (values go into variables) | |
| static int | pbx_builtin_answer (struct ast_channel *, void *) |
| static int | pbx_builtin_background (struct ast_channel *, void *) |
| static int | pbx_builtin_busy (struct ast_channel *, void *) |
| void | pbx_builtin_clear_globals (void) |
| static int | pbx_builtin_congestion (struct ast_channel *, void *) |
| static int | pbx_builtin_execiftime (struct ast_channel *, void *) |
| const char * | pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name) |
| static int | pbx_builtin_goto (struct ast_channel *, void *) |
| static int | pbx_builtin_gotoif (struct ast_channel *, void *) |
| static int | pbx_builtin_gotoiftime (struct ast_channel *, void *) |
| static int | pbx_builtin_hangup (struct ast_channel *, void *) |
| static int | pbx_builtin_importvar (struct ast_channel *, void *) |
| static int | pbx_builtin_noop (struct ast_channel *, void *) |
| static int | pbx_builtin_progress (struct ast_channel *, void *) |
| void | pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value) |
| static int | pbx_builtin_resetcdr (struct ast_channel *, void *) |
| static int | pbx_builtin_ringing (struct ast_channel *, void *) |
| static int | pbx_builtin_saycharacters (struct ast_channel *, void *) |
| static int | pbx_builtin_saydigits (struct ast_channel *, void *) |
| static int | pbx_builtin_saynumber (struct ast_channel *, void *) |
| static int | pbx_builtin_sayphonetic (struct ast_channel *, void *) |
| int | pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf) |
| static int | pbx_builtin_setamaflags (struct ast_channel *, void *) |
| int | pbx_builtin_setvar (struct ast_channel *, void *) |
| void | pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value) |
| static int | pbx_builtin_wait (struct ast_channel *, void *) |
| static int | pbx_builtin_waitexten (struct ast_channel *, void *) |
| int | pbx_checkcondition (const char *condition) |
| Evaluate a condition. | |
| static void | pbx_destroy (struct ast_pbx *p) |
| int | pbx_exec (struct ast_channel *c, struct ast_app *app, void *data) |
| Execute an application. | |
| static int | pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action) |
| The return value depends on the action:. | |
| static struct ast_exten * | pbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action) |
| ast_app * | pbx_findapp (const char *app) |
| Look up an application. | |
| static struct ast_switch * | pbx_findswitch (const char *sw) |
| void | pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp) |
| Support for Asterisk built-in variables in the dialplan. | |
| int | pbx_set_autofallthrough (int newval) |
| static void | pbx_substitute_variables (char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e) |
| void | pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count) |
| static void | pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count) |
| void | pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count) |
| static void * | pbx_thread (void *data) |
| static void | print_ext (struct ast_exten *e, char *buf, int buflen) |
| helper function to print an extension | |
| static void | set_ext_pri (struct ast_channel *c, const char *exten, int pri) |
| static int | show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[]) |
| static char * | substring (const char *value, int offset, int length, char *workspace, size_t workspace_len) |
| takes a substring. It is ok to call with value == workspace. | |
| static void | unreference_cached_app (struct ast_app *app) |
| static void | wait_for_hangup (struct ast_channel *chan, void *data) |
Variables | |
| static int | autofallthrough = 1 |
| static struct pbx_builtin | builtins [] |
| Declaration of builtin applications. | |
| static struct ast_context * | contexts |
| static int | countcalls |
| static char * | days [] |
| static const struct cfextension_states | extension_states [] |
| static struct varshead | globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE |
| static char | mandescr_show_dialplan [] |
| static char * | months [] |
| static struct ast_cli_entry | pbx_cli [] |
| static char | set_global_help [] |
| static char | show_application_help [] |
| static char | show_applications_help [] |
| static char | show_dialplan_help [] |
| static char | show_function_help [] |
| static char | show_functions_help [] |
| static char | show_globals_help [] |
| static char | show_hints_help [] |
| static char | show_switches_help [] |
| ast_state_cb * | statecbs |
| static int | stateid = 1 |
|
|
Go no deeper than this through includes (not counting loops) Definition at line 518 of file pbx.c. Referenced by handle_show_dialplan(), pbx_find_extension(), and show_dialplan_helper(). |
|
|
Definition at line 90 of file pbx.c. Referenced by pbx_builtin_background(). |
|
|
Definition at line 89 of file pbx.c. Referenced by pbx_builtin_background(). |
|
|
Definition at line 91 of file pbx.c. Referenced by pbx_builtin_background(). |
|
|
Definition at line 88 of file pbx.c. Referenced by pbx_builtin_background(). |
|
|
Definition at line 77 of file pbx.c. Referenced by pbx_extension_helper(), and realtime_exec(). |
|
|
|
|
|
Definition at line 876 of file pbx.c. Referenced by pbx_extension_helper(), and pbx_find_extension(). |
|
|
Definition at line 877 of file pbx.c. Referenced by pbx_extension_helper(). |
|
|
Definition at line 879 of file pbx.c. Referenced by pbx_extension_helper(). |
|
|
Definition at line 878 of file pbx.c. Referenced by pbx_extension_helper(). |
|
|
|
|
|
Definition at line 80 of file pbx.c. Referenced by ast_context_add_switch2(). |
|
|
Definition at line 82 of file pbx.c. Referenced by ast_add_extension2(), pbx_builtin_importvar(), and pbx_substitute_variables_helper_full(). |
|
|
|
|
|
|
|
|
|
|
|
Definition at line 100 of file pbx.c. Referenced by pbx_builtin_waitexten(). |
|
|
When looking up extensions, we can have different requests identified by the 'action' argument, as follows. Note that the coding is such that the low 4 bits are the third argument to extension_match_core. Definition at line 723 of file pbx.c. 00723 { 00724 E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */ 00725 E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */ 00726 E_MATCH = 0x02, /* extension is an exact match */ 00727 E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */ 00728 E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */ 00729 E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */ 00730 };
|
|
||||||||||||||||||||
|
Definition at line 3758 of file pbx.c. References ast_log(), ast_mutex_lock(), contexts, local_contexts, LOG_WARNING, name, and ast_context::next. Referenced by ast_context_create(), and ast_context_find_or_create(). 03759 { 03760 struct ast_context *tmp, **local_contexts; 03761 int length = sizeof(struct ast_context) + strlen(name) + 1; 03762 03763 if (!extcontexts) { 03764 ast_mutex_lock(&conlock); 03765 local_contexts = &contexts; 03766 } else 03767 local_contexts = extcontexts; 03768 03769 for (tmp = *local_contexts; tmp; tmp = tmp->next) { 03770 if (!strcasecmp(tmp->name, name)) { 03771 if (!existsokay) { 03772 ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name); 03773 tmp = NULL; 03774 } 03775 if (!extcontexts) 03776 ast_mutex_unlock(&conlock); 03777 return tmp; 03778 } 03779 } 03780 if ((tmp = ast_calloc(1, length))) { 03781 ast_mutex_init(&tmp->lock); 03782 ast_mutex_init(&tmp->macrolock); 03783 strcpy(tmp->name, name); 03784 tmp->root = NULL; 03785 tmp->registrar = registrar; 03786 tmp->next = *local_contexts; 03787 tmp->includes = NULL; 03788 tmp->ignorepats = NULL; 03789 *local_contexts = tmp; 03790 if (option_debug) 03791 ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name); 03792 if (option_verbose > 2) 03793 ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name); 03794 } 03795 03796 if (!extcontexts) 03797 ast_mutex_unlock(&conlock); 03798 return tmp; 03799 }
|
|
||||||||||||
|
Definition at line 5198 of file pbx.c. References ast_log(), ast_mutex_lock(), contexts, el, ast_context::next, and ast_ignorepat::next. Referenced by ast_context_destroy(), and ast_merge_contexts_and_delete(). 05199 { 05200 struct ast_context *tmp, *tmpl=NULL; 05201 struct ast_include *tmpi; 05202 struct ast_sw *sw; 05203 struct ast_exten *e, *el, *en; 05204 struct ast_ignorepat *ipi; 05205 05206 ast_mutex_lock(&conlock); 05207 for (tmp = contexts; tmp; ) { 05208 struct ast_context *next; /* next starting point */ 05209 for (; tmp; tmpl = tmp, tmp = tmp->next) { 05210 if (option_debug) 05211 ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar); 05212 if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) && 05213 (!con || !strcasecmp(tmp->name, con->name)) ) 05214 break; /* found it */ 05215 } 05216 if (!tmp) /* not found, we are done */ 05217 break; 05218 ast_mutex_lock(&tmp->lock); 05219 if (option_debug) 05220 ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar); 05221 next = tmp->next; 05222 if (tmpl) 05223 tmpl->next = next; 05224 else 05225 contexts = next; 05226 /* Okay, now we're safe to let it go -- in a sense, we were 05227 ready to let it go as soon as we locked it. */ 05228 ast_mutex_unlock(&tmp->lock); 05229 for (tmpi = tmp->includes; tmpi; ) { /* Free includes */ 05230 struct ast_include *tmpil = tmpi; 05231 tmpi = tmpi->next; 05232 free(tmpil); 05233 } 05234 for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */ 05235 struct ast_ignorepat *ipl = ipi; 05236 ipi = ipi->next; 05237 free(ipl); 05238 } 05239 while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list))) 05240 free(sw); 05241 for (e = tmp->root; e;) { 05242 for (en = e->peer; en;) { 05243 el = en; 05244 en = en->peer; 05245 destroy_exten(el); 05246 } 05247 el = e; 05248 e = e->next; 05249 destroy_exten(el); 05250 } 05251 ast_mutex_destroy(&tmp->lock); 05252 free(tmp); 05253 /* if we have a specific match, we are done, otherwise continue */ 05254 tmp = con ? NULL : next; 05255 } 05256 ast_mutex_unlock(&conlock); 05257 }
|
|
||||||||||||||||||||||||
|
Definition at line 6161 of file pbx.c. References ast_async_goto(), ast_exists_extension(), ast_explicit_goto(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, and ast_channel::exten. Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists(). 06162 { 06163 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority); 06164 06165 if (!chan) 06166 return -2; 06167 06168 if (context == NULL) 06169 context = chan->context; 06170 if (exten == NULL) 06171 exten = chan->exten; 06172 06173 goto_func = (async) ? ast_async_goto : ast_explicit_goto; 06174 if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num)) 06175 return goto_func(chan, context, exten, priority); 06176 else 06177 return -3; 06178 }
|
|
|
Definition at line 2210 of file pbx.c. References ast_channel::amaflags, ast_calloc, ast_cdr_alloc(), ast_cdr_init(), ast_cdr_start(), ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_log(), ast_set_flag, ast_spawn_extension(), ast_test_flag, ast_verbose(), ast_channel::cdr, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_pbx::dtimeout, error(), ast_channel::exten, free, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, ast_channel::pbx, ast_channel::priority, ast_pbx::rtimeout, set_ext_pri(), ast_cdr::start, and VERBOSE_PREFIX_2. Referenced by ast_pbx_run(), and pbx_thread(). 02211 { 02212 int found = 0; /* set if we find at least one match */ 02213 int res = 0; 02214 int autoloopflag; 02215 int error = 0; /* set an error conditions */ 02216 02217 /* A little initial setup here */ 02218 if (c->pbx) { 02219 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name); 02220 /* XXX and now what ? */ 02221 free(c->pbx); 02222 } 02223 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) 02224 return -1; 02225 if (c->amaflags) { 02226 if (!c->cdr) { 02227 c->cdr = ast_cdr_alloc(); 02228 if (!c->cdr) { 02229 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n"); 02230 free(c->pbx); 02231 return -1; 02232 } 02233 ast_cdr_init(c->cdr, c); 02234 } 02235 } 02236 /* Set reasonable defaults */ 02237 c->pbx->rtimeout = 10; 02238 c->pbx->dtimeout = 5; 02239 02240 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */ 02241 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP); 02242 02243 /* Start by trying whatever the channel is set to */ 02244 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02245 /* If not successful fall back to 's' */ 02246 if (option_verbose > 1) 02247 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); 02248 /* XXX the original code used the existing priority in the call to 02249 * ast_exists_extension(), and reset it to 1 afterwards. 02250 * I believe the correct thing is to set it to 1 immediately. 02251 */ 02252 set_ext_pri(c, "s", 1); 02253 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02254 /* JK02: And finally back to default if everything else failed */ 02255 if (option_verbose > 1) 02256 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); 02257 ast_copy_string(c->context, "default", sizeof(c->context)); 02258 } 02259 } 02260 if (c->cdr && ast_tvzero(c->cdr->start)) 02261 ast_cdr_start(c->cdr); 02262 for (;;) { 02263 char dst_exten[256]; /* buffer to accumulate digits */ 02264 int pos = 0; /* XXX should check bounds */ 02265 int digit = 0; 02266 02267 /* loop on priorities in this context/exten */ 02268 while (ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02269 found = 1; 02270 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) { 02271 /* Something bad happened, or a hangup has been requested. */ 02272 if (strchr("0123456789ABCDEF*#", res)) { 02273 if (option_debug) 02274 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res); 02275 pos = 0; 02276 dst_exten[pos++] = digit = res; 02277 dst_exten[pos] = '\0'; 02278 break; 02279 } 02280 if (res == AST_PBX_KEEPALIVE) { 02281 if (option_debug) 02282 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 02283 if (option_verbose > 1) 02284 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name); 02285 error = 1; 02286 break; 02287 } 02288 if (option_debug) 02289 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02290 if (option_verbose > 1) 02291 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02292 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) { 02293 c->_softhangup =0; 02294 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 02295 /* atimeout, nothing bad */ 02296 } else { 02297 if (c->cdr) 02298 ast_cdr_update(c); 02299 error = 1; 02300 break; 02301 } 02302 } 02303 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c,c->context,"T",1,c->cid.cid_num)) { 02304 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */ 02305 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ 02306 c->whentohangup = 0; 02307 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT; 02308 } else if (c->_softhangup) { 02309 if (option_debug) 02310 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n", 02311 c->exten, c->priority); 02312 error = 1; 02313 break; 02314 } 02315 c->priority++; 02316 } /* end while - from here on we can use 'break' to go out */ 02317 if (error) 02318 break; 02319 02320 /* XXX we get here on non-existing extension or a keypress or hangup ? */ 02321 02322 if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) { 02323 /* If there is no match at priority 1, it is not a valid extension anymore. 02324 * Try to continue at "i", 1 or exit if the latter does not exist. 02325 */ 02326 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 02327 if (option_verbose > 2) 02328 ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name); 02329 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten); 02330 set_ext_pri(c, "i", 1); 02331 } else { 02332 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", 02333 c->name, c->exten, c->context); 02334 error = 1; /* we know what to do with it */ 02335 break; 02336 } 02337 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) { 02338 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ 02339 c->_softhangup = 0; 02340 } else { /* keypress received, get more digits for a full extension */ 02341 int waittime = 0; 02342 if (digit) 02343 waittime = c->pbx->dtimeout; 02344 else if (!autofallthrough) 02345 waittime = c->pbx->rtimeout; 02346 if (!waittime) { 02347 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 02348 if (!status) 02349 status = "UNKNOWN"; 02350 if (option_verbose > 2) 02351 ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status); 02352 if (!strcasecmp(status, "CONGESTION")) 02353 res = pbx_builtin_congestion(c, "10"); 02354 else if (!strcasecmp(status, "CHANUNAVAIL")) 02355 res = pbx_builtin_congestion(c, "10"); 02356 else if (!strcasecmp(status, "BUSY")) 02357 res = pbx_builtin_busy(c, "10"); 02358 error = 1; /* XXX disable message */ 02359 break; /* exit from the 'for' loop */ 02360 } 02361 02362 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos)) 02363 break; 02364 if (ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */ 02365 set_ext_pri(c, dst_exten, 1); 02366 else { 02367 /* No such extension */ 02368 if (!ast_strlen_zero(dst_exten)) { 02369 /* An invalid extension */ 02370 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) { 02371 if (option_verbose > 2) 02372 ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name); 02373 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten); 02374 set_ext_pri(c, "i", 1); 02375 } else { 02376 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context); 02377 found = 1; /* XXX disable message */ 02378 break; 02379 } 02380 } else { 02381 /* A simple timeout */ 02382 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) { 02383 if (option_verbose > 2) 02384 ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name); 02385 set_ext_pri(c, "t", 1); 02386 } else { 02387 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); 02388 found = 1; /* XXX disable message */ 02389 break; 02390 } 02391 } 02392 } 02393 if (c->cdr) { 02394 if (option_verbose > 2) 02395 ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name); 02396 ast_cdr_update(c); 02397 } 02398 } 02399 } 02400 if (!found && !error) 02401 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name); 02402 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) { 02403 if (c->cdr && ast_opt_end_cdr_before_h_exten) 02404 ast_cdr_end(c->cdr); 02405 set_ext_pri(c, "h", 1); 02406 while (ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) { 02407 if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) { 02408 /* Something bad happened, or a hangup has been requested. */ 02409 if (option_debug) 02410 ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02411 if (option_verbose > 1) 02412 ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name); 02413 break; 02414 } 02415 c->priority++; 02416 } 02417 } 02418 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP); 02419 02420 pbx_destroy(c->pbx); 02421 c->pbx = NULL; 02422 if (res != AST_PBX_KEEPALIVE) 02423 ast_hangup(c); 02424 return 0; 02425 }
|
|
||||||||||||||||
|
Definition at line 741 of file pbx.c. References ast_log(), E_MATCH, E_MATCH_MASK, E_MATCHMORE, and LOG_WARNING. Referenced by extension_match_core(). 00742 { 00743 mode &= E_MATCH_MASK; /* only consider the relevant bits */ 00744 00745 if ( (mode == E_MATCH) && (pattern[0] == '_') && (strcasecmp(pattern,data)==0) ) /* note: if this test is left out, then _x. will not match _x. !!! */ 00746 return 1; 00747 00748 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */ 00749 int ld = strlen(data), lp = strlen(pattern); 00750 00751 if (lp < ld) /* pattern too short, cannot match */ 00752 return 0; 00753 /* depending on the mode, accept full or partial match or both */ 00754 if (mode == E_MATCH) 00755 return !strcmp(pattern, data); /* 1 on match, 0 on fail */ 00756 if (ld == 0 || !strncasecmp(pattern, data, ld)) /* partial or full match */ 00757 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */ 00758 else 00759 return 0; 00760 } 00761 pattern++; /* skip leading _ */ 00762 /* 00763 * XXX below we stop at '/' which is a separator for the CID info. However we should 00764 * not store '/' in the pattern at all. When we insure it, we can remove the checks. 00765 */ 00766 while (*data && *pattern && *pattern != '/') { 00767 const char *end; 00768 00769 if (*data == '-') { /* skip '-' in data (just a separator) */ 00770 data++; 00771 continue; 00772 } 00773 switch (toupper(*pattern)) { 00774 case '[': /* a range */ 00775 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */ 00776 if (end == NULL) { 00777 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n"); 00778 return 0; /* unconditional failure */ 00779 } 00780 for (pattern++; pattern != end; pattern++) { 00781 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */ 00782 if (*data >= pattern[0] && *data <= pattern[2]) 00783 break; /* match found */ 00784 else { 00785 pattern += 2; /* skip a total of 3 chars */ 00786 continue; 00787 } 00788 } else if (*data == pattern[0]) 00789 break; /* match found */ 00790 } 00791 if (pattern == end) 00792 return 0; 00793 pattern = end; /* skip and continue */ 00794 break; 00795 case 'N': 00796 if (*data < '2' || *data > '9') 00797 return 0; 00798 break; 00799 case 'X': 00800 if (*data < '0' || *data > '9') 00801 return 0; 00802 break; 00803 case 'Z': 00804 if (*data < '1' || *data > '9') 00805 return 0; 00806 break; 00807 case '.': /* Must match, even with more digits */ 00808 return 1; 00809 case '!': /* Early match */ 00810 return 2; 00811 case ' ': 00812 case '-': /* Ignore these in patterns */ 00813 data--; /* compensate the final data++ */ 00814 break; 00815 default: 00816 if (*data != *pattern) 00817 return 0; 00818 } 00819 data++; 00820 pattern++; 00821 } 00822 if (*data) /* data longer than pattern, no match */ 00823 return 0; 00824 /* 00825 * match so far, but ran off the end of the data. 00826 * Depending on what is next, determine match or not. 00827 */ 00828 if (*pattern == '\0' || *pattern == '/') /* exact match */ 00829 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */ 00830 else if (*pattern == '!') /* early match */ 00831 return 2; 00832 else /* partial match */ 00833 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */ 00834 }
|
|
||||||||||||||||||||||||
|
add the extension in the priority chain. returns 0 on success, -1 on failure
Definition at line 4565 of file pbx.c. References ast_exten::peer, and ast_exten::priority. Referenced by ast_add_extension2(). 04567 { 04568 struct ast_exten *ep; 04569 04570 for (ep = NULL; e ; ep = e, e = e->peer) { 04571 if (e->priority >= tmp->priority) 04572 break; 04573 } 04574 if (!e) { /* go at the end, and ep is surely set because the list is not empty */ 04575 ep->peer = tmp; 04576 return 0; /* success */ 04577 } 04578 if (e->priority == tmp->priority) { 04579 /* Can't have something exactly the same. Is this a 04580 replacement? If so, replace, otherwise, bonk. */ 04581 if (!replace) { 04582 ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name); 04583 if (tmp->datad) 04584 tmp->datad(tmp->data); 04585 free(tmp); 04586 return -1; 04587 } 04588 /* we are replacing e, so copy the link fields and then update 04589 * whoever pointed to e to point to us 04590 */ 04591 tmp->next = e->next; /* not meaningful if we are not first in the peer list */ 04592 tmp->peer = e->peer; /* always meaningful */ 04593 if (ep) /* We're in the peer list, just insert ourselves */ 04594 ep->peer = tmp; 04595 else if (el) /* We're the first extension. Take over e's functions */ 04596 el->next = tmp; 04597 else /* We're the very first extension. */ 04598 con->root = tmp; 04599 if (tmp->priority == PRIORITY_HINT) 04600 ast_change_hint(e,tmp); 04601 /* Destroy the old one */ 04602 if (e->datad) 04603 e->datad(e->data); 04604 free(e); 04605 } else { /* Slip ourselves in just before e */ 04606 tmp->peer = e; 04607 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */ 04608 if (ep) /* Easy enough, we're just in the peer list */ 04609 ep->peer = tmp; 04610 else { /* we are the first in some peer list, so link in the ext list */ 04611 if (el) 04612 el->next = tmp; /* in the middle... */ 04613 else 04614 con->root = tmp; /* ... or at the head */ 04615 e->next = NULL; /* e is no more at the head, so e->next must be reset */ 04616 } 04617 /* And immediately return success. */ 04618 if (tmp->priority == PRIORITY_HINT) 04619 ast_add_hint(tmp); 04620 } 04621 return 0; 04622 }
|
|
|
Retrieve the number of active calls.
Definition at line 2530 of file pbx.c. References countcalls. Referenced by handle_chanlist(). 02531 { 02532 return countcalls; 02533 }
|
|
||||||||||||||||||||||||||||||||||||||||||||
|
Add and extension to an extension context.
Definition at line 4448 of file pbx.c. References ast_add_extension2(), ast_unlock_contexts(), and find_context_locked(). Referenced by handle_context_add_extension(), park_add_hints(), and register_peer_exten(). 04451 { 04452 int ret = -1; 04453 struct ast_context *c = find_context_locked(context); 04454 04455 if (c) { 04456 ret = ast_add_extension2(c, replace, extension, priority, label, callerid, 04457 application, data, datad, registrar); 04458 ast_unlock_contexts(); 04459 } 04460 return ret; 04461 }
|
|
||||||||||||||||||||||||||||||||||||||||||||
|
Add an extension to an extension context, this time with an ast_context *. We sort extensions in order of matching preference, so that we can stop the search as soon as we find a suitable match. This ordering also takes care of wildcards such as '.' (meaning "one or more of any character") and '!' (which is 'earlymatch', meaning "zero or more of any character" but also impacts the return value from CANMATCH and EARLYMATCH. The extension match rules defined in the devmeeting 2006.05.05 are quite simple: WE SELECT THE LONGEST MATCH. In detail, "longest" means the number of matched characters in the extension. In case of ties (e.g. _XXX and 333) in the length of a pattern, we give priority to entries with the smallest cardinality (e.g, [5-9] comes before [2-8] before the former has only 5 elements, while the latter has 7, etc. In case of same cardinality, the first element in the range counts. If we still have a tie, any final '!' will make this as a possibly less specific pattern. EBUSY - can't lock EEXIST - extension with the same priority exist and no replace is set Definition at line 4649 of file pbx.c. References add_pri(), ast_exten::app, ast_add_hint(), ast_calloc, AST_LIST_FIRST, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_verbose(), ast_exten::cidmatch, ast_exten::data, ast_exten::datad, el, ext_cmp(), ext_strncpy(), ast_exten::exten, ast_exten::label, ast_context::lock, ast_exten::matchcid, ast_exten::next, option_verbose, ast_exten::parent, pbx_substitute_variables_varshead(), ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, ast_context::root, ast_exten::stuff, VAR_BUF_SIZE, and VERBOSE_PREFIX_3. Referenced by add_extensions(), ast_add_extension(), and do_parking_thread(). 04653 { 04654 /* 04655 * Sort extensions (or patterns) according to the rules indicated above. 04656 * These are implemented by the function ext_cmp()). 04657 * All priorities for the same ext/pattern/cid are kept in a list, 04658 * using the 'peer' field as a link field.. 04659 */ 04660 struct ast_exten *tmp, *e, *el = NULL; 04661 int res; 04662 int length; 04663 char *p; 04664 char expand_buf[VAR_BUF_SIZE] = { 0, }; 04665 04666 /* if we are adding a hint, and there are global variables, and the hint 04667 contains variable references, then expand them 04668 */ 04669 ast_rwlock_rdlock(&globalslock); 04670 if (priority == PRIORITY_HINT && AST_LIST_FIRST(&globals) && strstr(application, "${")) { 04671 pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf)); 04672 application = expand_buf; 04673 } 04674 ast_rwlock_unlock(&globalslock); 04675 04676 length = sizeof(struct ast_exten); 04677 length += strlen(extension) + 1; 04678 length += strlen(application) + 1; 04679 if (label) 04680 length += strlen(label) + 1; 04681 if (callerid) 04682 length += strlen(callerid) + 1; 04683 else 04684 length ++; /* just the '\0' */ 04685 04686 /* Be optimistic: Build the extension structure first */ 04687 if (!(tmp = ast_calloc(1, length))) 04688 return -1; 04689 04690 /* use p as dst in assignments, as the fields are const char * */ 04691 p = tmp->stuff; 04692 if (label) { 04693 tmp->label = p; 04694 strcpy(p, label); 04695 p += strlen(label) + 1; 04696 } 04697 tmp->exten = p; 04698 p += ext_strncpy(p, extension, strlen(extension) + 1) + 1; 04699 tmp->priority = priority; 04700 tmp->cidmatch = p; /* but use p for assignments below */ 04701 if (callerid) { 04702 p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1; 04703 tmp->matchcid = 1; 04704 } else { 04705 *p++ = '\0'; 04706 tmp->matchcid = 0; 04707 } 04708 tmp->app = p; 04709 strcpy(p, application); 04710 tmp->parent = con; 04711 tmp->data = data; 04712 tmp->datad = datad; 04713 tmp->registrar = registrar; 04714 04715 ast_mutex_lock(&con->lock); 04716 res = 0; /* some compilers will think it is uninitialized otherwise */ 04717 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */ 04718 res = ext_cmp(e->exten, extension); 04719 if (res == 0) { /* extension match, now look at cidmatch */ 04720 if (!e->matchcid && !tmp->matchcid) 04721 res = 0; 04722 else if (tmp->matchcid && !e->matchcid) 04723 res = 1; 04724 else if (e->matchcid && !tmp->matchcid) 04725 res = -1; 04726 else 04727 res = strcasecmp(e->cidmatch, tmp->cidmatch); 04728 } 04729 if (res >= 0) 04730 break; 04731 } 04732 if (e && res == 0) { /* exact match, insert in the pri chain */ 04733 res = add_pri(con, tmp, el, e, replace); 04734 ast_mutex_unlock(&con->lock); 04735 if (res < 0) { 04736 errno = EEXIST; /* XXX do we care ? */ 04737 return 0; /* XXX should we return -1 maybe ? */ 04738 } 04739 } else { 04740 /* 04741 * not an exact match, this is the first entry with this pattern, 04742 * so insert in the main list right before 'e' (if any) 04743 */ 04744 tmp->next = e; 04745 if (el) 04746 el->next = tmp; 04747 else 04748 con->root = tmp; 04749 ast_mutex_unlock(&con->lock); 04750 if (tmp->priority == PRIORITY_HINT) 04751 ast_add_hint(tmp); 04752 } 04753 if (option_debug) { 04754 if (tmp->matchcid) { 04755 if (option_debug) 04756 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n", 04757 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04758 } else { 04759 if (option_debug) 04760 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n", 04761 tmp->exten, tmp->priority, con->name); 04762 } 04763 } 04764 if (option_verbose > 2) { 04765 if (tmp->matchcid) { 04766 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n", 04767 tmp->exten, tmp->priority, tmp->cidmatch, con->name); 04768 } else { 04769 ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n", 04770 tmp->exten, tmp->priority, con->name); 04771 } 04772 } 04773 return 0; 04774 }
|
|
|
ast_add_hint: Add hint to hint list, check initial extension state
Definition at line 2036 of file pbx.c. References ast_calloc, ast_extension_state2(), ast_get_extension_app(), ast_get_extension_name(), ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_hint::exten, LOG_DEBUG, and option_debug. Referenced by ast_add_extension2(). 02037 { 02038 struct ast_hint *hint; 02039 02040 if (!e) 02041 return -1; 02042 02043 AST_RWLIST_WRLOCK(&hints); 02044 02045 /* Search if hint exists, do nothing */ 02046 AST_RWLIST_TRAVERSE(&hints, hint, list) { 02047 if (hint->exten == e) { 02048 AST_RWLIST_UNLOCK(&hints); 02049 if (option_debug > 1) 02050 ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 02051 return -1; 02052 } 02053 } 02054 02055 if (option_debug > 1) 02056 ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); 02057 02058 if (!(hint = ast_calloc(1, sizeof(*hint)))) { 02059 AST_RWLIST_UNLOCK(&hints); 02060 return -1; 02061 } 02062 /* Initialize and insert new item at the top */ 02063 hint->exten = e; 02064 hint->laststate = ast_extension_state2(e); 02065 AST_RWLIST_INSERT_HEAD(&hints, hint, list); 02066 02067 AST_RWLIST_UNLOCK(&hints); 02068 return 0; 02069 }
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||
|
Definition at line 4482 of file pbx.c. References ast_channel::_state, ast_channel_alloc(), ast_channel_lock, ast_channel_masquerade(), ast_channel_unlock, ast_do_masquerade(), ast_explicit_goto(), ast_hangup(), ast_log(), ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_channel::context, ast_channel::exten, LOG_WARNING, ast_channel::pbx, ast_channel::readformat, S_OR, and ast_channel::writeformat. Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), builtin_blindtransfer(), console_transfer(), handle_request_bye(), handle_request_refer(), process_ast_dsp(), socket_process(), and zt_read(). 04483 { 04484 int res = 0; 04485 04486 ast_channel_lock(chan); 04487 04488 if (chan->pbx) { /* This channel is currently in the PBX */ 04489 ast_explicit_goto(chan, context, exten, priority); 04490 ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO); 04491 } else { 04492 /* In order to do it when the channel doesn't really exist within 04493 the PBX, we have to make a new channel, masquerade, and start the PBX 04494 at the new location */ 04495 struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, "AsyncGoto/%s", chan->name); 04496 if (!tmpchan) 04497 res = -1; 04498 else { 04499 /* Make formats okay */ 04500 tmpchan->readformat = chan->readformat; 04501 tmpchan->writeformat = chan->writeformat; 04502 /* Setup proper location */ 04503 ast_explicit_goto(tmpchan, 04504 S_OR(context, chan->context), S_OR(exten, chan->exten), priority); 04505 04506 /* Masquerade into temp channel */ 04507 ast_channel_masquerade(tmpchan, chan); 04508 04509 /* Grab the locks and get going */ 04510 ast_channel_lock(tmpchan); 04511 ast_do_masquerade(tmpchan); 04512 ast_channel_unlock(tmpchan); 04513 /* Start the PBX going on our stolen channel */ 04514 if (ast_pbx_start(tmpchan)) { 04515 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name); 04516 ast_hangup(tmpchan); 04517 res = -1; 04518 } 04519 } 04520 } 04521 ast_channel_unlock(chan); 04522 return res; 04523 }
|
|
||||||||||||||||||||
|
Definition at line 4525 of file pbx.c. References ast_async_goto(), ast_channel_unlock, and ast_get_channel_by_name_locked(). 04526 { 04527 struct ast_channel *chan; 04528 int res = -1; 04529 04530 chan = ast_get_channel_by_name_locked(channame); 04531 if (chan) { 04532 res = ast_async_goto(chan, context, exten, priority); 04533 ast_channel_unlock(chan); 04534 } 04535 return res; 04536 }
|
|
||||||||||||||||||||
|
Definition at line 6185 of file pbx.c. References __ast_goto_if_exists(). 06186 { 06187 return __ast_goto_if_exists(chan, context, exten, priority, 1); 06188 }
|
|
||||||||||||
|
Definition at line 4124 of file pbx.c. References ast_strlen_zero(), ast_timing::daymask, ast_timing::dowmask, get_range(), get_timerange(), ast_timing::monthmask, and strsep(). Referenced by ast_context_add_include2(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime(). 04125 { 04126 char info_save[256]; 04127 char *info; 04128 04129 /* Check for empty just in case */ 04130 if (ast_strlen_zero(info_in)) 04131 return 0; 04132 /* make a copy just in case we were passed a static string */ 04133 ast_copy_string(info_save, info_in, sizeof(info_save)); 04134 info = info_save; 04135 /* Assume everything except time */ 04136 i->monthmask = 0xfff; /* 12 bits */ 04137 i->daymask = 0x7fffffffU; /* 31 bits */ 04138 i->dowmask = 0x7f; /* 7 bits */ 04139 /* on each call, use strsep() to move info to the next argument */ 04140 get_timerange(i, strsep(&info, "|")); 04141 if (info) 04142 i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week"); 04143 if (info) 04144 i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day"); 04145 if (info) 04146 i->monthmask = get_range(strsep(&info, "|"), 12, months, "month"); 04147 return 1; 04148 }
|
|
||||||||||||||||||||||||
|
Looks for a valid matching extension.
Definition at line 2158 of file pbx.c. References E_CANMATCH, and pbx_extension_helper(). Referenced by cb_events(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), loopback_canmatch(), mgcp_ss(), phone_check_exception(), skinny_ss(), and ss_thread(). 02159 { 02160 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH); 02161 }
|
|
||||||||||||
|
ast_change_hint: Change hint for an extension
Definition at line 2072 of file pbx.c. References AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and ast_hint::exten. 02073 { 02074 struct ast_hint *hint; 02075 int res = -1; 02076 02077 AST_RWLIST_WRLOCK(&hints); 02078 AST_RWLIST_TRAVERSE(&hints, hint, list) { 02079 if (hint->exten == oe) { 02080 hint->exten = ne; 02081 res = 0; 02082 break; 02083 } 02084 } 02085 AST_RWLIST_UNLOCK(&hints); 02086 02087 return res; 02088 }
|
|
|
Definition at line 4150 of file pbx.c. References ast_log(), ast_timing::daymask, ast_timing::dowmask, LOG_WARNING, ast_timing::minmask, and ast_timing::monthmask. Referenced by include_valid(), pbx_builtin_execiftime(), and pbx_builtin_gotoiftime(). 04151 { 04152 struct tm tm; 04153 time_t t = time(NULL); 04154 04155 localtime_r(&t,&tm); 04156 04157 /* If it's not the right month, return */ 04158 if (!(i->monthmask & (1 << tm.tm_mon))) 04159 return 0; 04160 04161 /* If it's not that time of the month.... */ 04162 /* Warning, tm_mday has range 1..31! */ 04163 if (!(i->daymask & (1 << (tm.tm_mday-1)))) 04164 return 0; 04165 04166 /* If it's not the right day of the week */ 04167 if (!(i->dowmask & (1 << tm.tm_wday))) 04168 return 0; 04169 04170 /* Sanity check the hour just to be safe */ 04171 if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) { 04172 ast_log(LOG_WARNING, "Insane time...\n"); 04173 return 0; 04174 } 04175 04176 /* Now the tough part, we calculate if it fits 04177 in the right time based on min/hour */ 04178 if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2)))) 04179 return 0; 04180 04181 /* If we got this far, then we're good */ 04182 return 1; 04183 }
|
|
||||||||||||||||
|
Add an ignorepat.
Definition at line 4384 of file pbx.c. References ast_context_add_ignorepat2(), ast_unlock_contexts(), and find_context_locked(). Referenced by handle_context_add_ignorepat(). 04385 { 04386 int ret = -1; 04387 struct ast_context *c = find_context_locked(context); 04388 04389 if (c) { 04390 ret = ast_context_add_ignorepat2(c, value, registrar); 04391 ast_unlock_contexts(); 04392 } 04393 return ret; 04394 }
|
|
||||||||||||||||
|
Definition at line 4396 of file pbx.c. References ast_calloc, ast_mutex_lock(), ast_mutex_unlock(), ast_context::ignorepats, ast_context::lock, ast_ignorepat::next, ast_ignorepat::pattern, and ast_ignorepat::registrar. Referenced by ast_compile_ael2(), and ast_context_add_ignorepat(). 04397 { 04398 struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL; 04399 int length; 04400 length = sizeof(struct ast_ignorepat); 04401 length += strlen(value) + 1; 04402 if (!(ignorepat = ast_calloc(1, length))) 04403 return -1; 04404 /* The cast to char * is because we need to write the initial value. 04405 * The field is not supposed to be modified otherwise 04406 */ 04407 strcpy((char *)ignorepat->pattern, value); 04408 ignorepat->next = NULL; 04409 ignorepat->registrar = registrar; 04410 ast_mutex_lock(&con->lock); 04411 for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) { 04412 ignorepatl = ignorepatc; 04413 if (!strcasecmp(ignorepatc->pattern, value)) { 04414 /* Already there */ 04415 ast_mutex_unlock(&con->lock); 04416 errno = EEXIST; 04417 return -1; 04418 } 04419 } 04420 if (ignorepatl) 04421 ignorepatl->next = ignorepat; 04422 else 04423 con->ignorepats = ignorepat; 04424 ast_mutex_unlock(&con->lock); 04425 return 0; 04426 04427 }
|
|
||||||||||||||||
|
Add a context include.
Definition at line 3930 of file pbx.c. References ast_context_add_include2(), ast_unlock_contexts(), and find_context_locked(). Referenced by handle_context_add_include(). 03931 { 03932 int ret = -1; 03933 struct ast_context *c = find_context_locked(context); 03934 03935 if (c) { 03936 ret = ast_context_add_include2(c, include, registrar); 03937 ast_unlock_contexts(); 03938 } 03939 return ret; 03940 }
|
|
||||||||||||||||
|
Add a context include.
Definition at line 4192 of file pbx.c. References ast_build_timing(), ast_calloc, ast_get_context_name(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), free, ast_include::hastime, ast_context::includes, ast_context::lock, ast_include::name, ast_include::next, option_verbose, ast_include::registrar, ast_include::rname, ast_include::stuff, ast_include::timing, and VERBOSE_PREFIX_3. Referenced by ast_compile_ael2(), and ast_context_add_include(). 04194 { 04195 struct ast_include *new_include; 04196 char *c; 04197 struct ast_include *i, *il = NULL; /* include, include_last */ 04198 int length; 04199 char *p; 04200 04201 length = sizeof(struct ast_include); 04202 length += 2 * (strlen(value) + 1); 04203 04204 /* allocate new include structure ... */ 04205 if (!(new_include = ast_calloc(1, length))) 04206 return -1; 04207 /* Fill in this structure. Use 'p' for assignments, as the fields 04208 * in the structure are 'const char *' 04209 */ 04210 p = new_include->stuff; 04211 new_include->name = p; 04212 strcpy(p, value); 04213 p += strlen(value) + 1; 04214 new_include->rname = p; 04215 strcpy(p, value); 04216 /* Strip off timing info, and process if it is there */ 04217 if ( (c = strchr(p, '|')) ) { 04218 *c++ = '\0'; 04219 new_include->hastime = ast_build_timing(&(new_include->timing), c); 04220 } 04221 new_include->next = NULL; 04222 new_include->registrar = registrar; 04223 04224 ast_mutex_lock(&con->lock); 04225 04226 /* ... go to last include and check if context is already included too... */ 04227 for (i = con->includes; i; i = i->next) { 04228 if (!strcasecmp(i->name, new_include->name)) { 04229 free(new_include); 04230 ast_mutex_unlock(&con->lock); 04231 errno = EEXIST; 04232 return -1; 04233 } 04234 il = i; 04235 } 04236 04237 /* ... include new context into context list, unlock, return */ 04238 if (il) 04239 il->next = new_include; 04240 else 04241 con->includes = new_include; 04242 if (option_verbose > 2) 04243 ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con)); 04244 ast_mutex_unlock(&con->lock); 04245 04246 return 0; 04247 }
|
|
||||||||||||||||||||||||
|
Add a switch.
Definition at line 4254 of file pbx.c. References ast_context_add_switch2(), ast_unlock_contexts(), and find_context_locked(). 04255 { 04256 int ret = -1; 04257 struct ast_context *c = find_context_locked(context); 04258 04259 if (c) { /* found, add switch to this context */ 04260 ret = ast_context_add_switch2(c, sw, data, eval, registrar); 04261 ast_unlock_contexts(); 04262 } 04263 return ret; 04264 }
|
|
||||||||||||||||||||||||
|
Adds a switch (first param is a ast_context).
Definition at line 4273 of file pbx.c. References ast_calloc, ast_get_context_name(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_sw::data, ast_sw::eval, free, ast_context::lock, ast_sw::name, option_verbose, ast_sw::registrar, SWITCH_DATA_LENGTH, and VERBOSE_PREFIX_3. Referenced by ast_compile_ael2(), and ast_context_add_switch(). 04275 { 04276 struct ast_sw *new_sw; 04277 struct ast_sw *i; 04278 int length; 04279 char *p; 04280 04281 length = sizeof(struct ast_sw); 04282 length += strlen(value) + 1; 04283 if (data) 04284 length += strlen(data); 04285 length++; 04286 if (eval) { 04287 /* Create buffer for evaluation of variables */ 04288 length += SWITCH_DATA_LENGTH; 04289 length++; 04290 } 04291 04292 /* allocate new sw structure ... */ 04293 if (!(new_sw = ast_calloc(1, length))) 04294 return -1; 04295 /* ... fill in this structure ... */ 04296 p = new_sw->stuff; 04297 new_sw->name = p; 04298 strcpy(new_sw->name, value); 04299 p += strlen(value) + 1; 04300 new_sw->data = p; 04301 if (data) { 04302 strcpy(new_sw->data, data); 04303 p += strlen(data) + 1; 04304 } else { 04305 strcpy(new_sw->data, ""); 04306 p++; 04307 } 04308 if (eval) 04309 new_sw->tmpdata = p; 04310 new_sw->eval = eval; 04311 new_sw->registrar = registrar; 04312 04313 /* ... try to lock this context ... */ 04314 ast_mutex_lock(&con->lock); 04315 04316 /* ... go to last sw and check if context is already swd too... */ 04317 AST_LIST_TRAVERSE(&con->alts, i, list) { 04318 if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { 04319 free(new_sw); 04320 ast_mutex_unlock(&con->lock); 04321 errno = EEXIST; 04322 return -1; 04323 } 04324 } 04325 04326 /* ... sw new context into context list, unlock, return */ 04327 AST_LIST_INSERT_TAIL(&con->alts, new_sw, list); 04328 04329 if (option_verbose > 2) 04330 ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con)); 04331 04332 ast_mutex_unlock(&con->lock); 04333 04334 return 0; 04335 }
|
|
||||||||||||||||
|
Register a new context.
Definition at line 3801 of file pbx.c. References __ast_context_create(). Referenced by ast_compile_ael2(), do_parking_thread(), reload_config(), and set_config(). 03802 { 03803 return __ast_context_create(extcontexts, name, registrar, 0); 03804 }
|
|
||||||||||||
|
Destroy a context (matches the specified context (or ANY context if NULL).
Definition at line 5259 of file pbx.c. References __ast_context_destroy(). Referenced by cleanup_stale_contexts(), and unload_module(). 05260 { 05261 __ast_context_destroy(con,registrar); 05262 }
|
|
|
Find a context.
Definition at line 864 of file pbx.c. References ast_mutex_lock(), ast_mutex_unlock(), and ast_walk_contexts(). Referenced by ast_context_verify_includes(), ast_ignore_pattern(), cleanup_stale_contexts(), do_parking_thread(), park_exec(), register_peer_exten(), reload_config(), and set_config(). 00865 { 00866 struct ast_context *tmp = NULL; 00867 ast_mutex_lock(&conlock); 00868 while ( (tmp = ast_walk_contexts(tmp)) ) { 00869 if (!name || !strcasecmp(name, tmp->name)) 00870 break; 00871 } 00872 ast_mutex_unlock(&conlock); 00873 return tmp; 00874 }
|
|
||||||||||||||||
|
Register a new context or find an existing one.
Definition at line 3806 of file pbx.c. References __ast_context_create(). Referenced by pbx_load_users(). 03807 { 03808 return __ast_context_create(extcontexts, name, registrar, 1); 03809 }
|
|
|
locks the macrolock in the given given context
Definition at line 2767 of file pbx.c. References ast_get_context_name(), ast_lock_contexts(), ast_mutex_lock(), ast_unlock_contexts(), and ast_walk_contexts(). 02768 { 02769 struct ast_context *c = NULL; 02770 int ret = -1; 02771 02772 ast_lock_contexts(); 02773 02774 while ((c = ast_walk_contexts(c))) { 02775 if (!strcmp(ast_get_context_name(c), context)) { 02776 ret = 0; 02777 break; 02778 } 02779 } 02780 02781 ast_unlock_contexts(); 02782 02783 /* if we found context, lock macrolock */ 02784 if (ret == 0) 02785 ret = ast_mutex_lock(&c->macrolock); 02786 02787 return ret; 02788 }
|
|
||||||||||||||||||||
|
Simply remove extension from context.
Definition at line 2668 of file pbx.c. References ast_context_remove_extension2(), ast_unlock_contexts(), and find_context_locked(). Referenced by handle_context_remove_extension(), and register_peer_exten(). 02669 { 02670 int ret = -1; /* default error return */ 02671 struct ast_context *c = find_context_locked(context); 02672 02673 if (c) { /* ... remove extension ... */ 02674 ret = ast_context_remove_extension2(c, extension, priority, registrar); 02675 ast_unlock_contexts(); 02676 } 02677 return ret; 02678 }
|
|
||||||||||||||||||||
|
This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.
Definition at line 2690 of file pbx.c. References ast_mutex_lock(), ast_mutex_unlock(), destroy_exten(), exten, ast_context::lock, ast_exten::next, ast_exten::peer, and ast_context::root. Referenced by ast_context_remove_extension(), do_parking_thread(), and park_exec(). 02691 { 02692 struct ast_exten *exten, *prev_exten = NULL; 02693 struct ast_exten *peer; 02694 02695 ast_mutex_lock(&con->lock); 02696 02697 /* scan the extension list to find matching extension-registrar */ 02698 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) { 02699 if (!strcmp(exten->exten, extension) && 02700 (!registrar || !strcmp(exten->registrar, registrar))) 02701 break; 02702 } 02703 if (!exten) { 02704 /* we can't find right extension */ 02705 ast_mutex_unlock(&con->lock); 02706 return -1; 02707 } 02708 02709 /* should we free all peers in this extension? (priority == 0)? */ 02710 if (priority == 0) { 02711 /* remove this extension from context list */ 02712 if (prev_exten) 02713 prev_exten->next = exten->next; 02714 else 02715 con->root = exten->next; 02716 02717 /* fire out all peers */ 02718 while ( (peer = exten) ) { 02719 exten = peer->peer; /* prepare for next entry */ 02720 destroy_exten(peer); 02721 } 02722 } else { 02723 /* scan the priority list to remove extension with exten->priority == priority */ 02724 struct ast_exten *previous_peer = NULL; 02725 02726 for (peer = exten; peer; previous_peer = peer, peer = peer->peer) { 02727 if (peer->priority == priority && 02728 (!registrar || !strcmp(peer->registrar, registrar) )) 02729 break; /* found our priority */ 02730 } 02731 if (!peer) { /* not found */ 02732 ast_mutex_unlock(&con->lock); 02733 return -1; 02734 } 02735 /* we are first priority extension? */ 02736 if (!previous_peer) { 02737 /* 02738 * We are first in the priority chain, so must update the extension chain. 02739 * The next node is either the next priority or the next extension 02740 */ 02741 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next; 02742 02743 if (!prev_exten) /* change the root... */ 02744 con->root = next_node; 02745 else 02746 prev_exten->next = next_node; /* unlink */ 02747 if (peer->peer) /* XXX update the new head of the pri list */ 02748 peer->peer->next = peer->next; 02749 } else { /* easy, we are not first priority in extension */ 02750 previous_peer->peer = peer->peer; 02751 } 02752 02753 /* now, free whole priority extension */ 02754 destroy_exten(peer); 02755 /* XXX should we return -1 ? */ 02756 } 02757 ast_mutex_unlock(&con->lock); 02758 return 0; 02759 }
|
|
||||||||||||||||
|
Definition at line 4341 of file pbx.c. References ast_context_remove_ignorepat2(), ast_unlock_contexts(), and find_context_locked(). Referenced by handle_context_remove_ignorepat(). 04342 { 04343 int ret = -1; 04344 struct ast_context *c = find_context_locked(context); 04345 04346 if (c) { 04347 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar); 04348 ast_unlock_contexts(); 04349 } 04350 return ret; 04351 }
|
|
||||||||||||||||
|
Definition at line 4353 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(). 04354 { 04355 struct ast_ignorepat *ip, *ipl = NULL; 04356 04357 ast_mutex_lock(&con->lock); 04358 04359 for (ip = con->ignorepats; ip; ip = ip->next) { 04360 if (!strcmp(ip->pattern, ignorepat) && 04361 (!registrar || (registrar == ip->registrar))) { 04362 if (ipl) { 04363 ipl->next = ip->next; 04364 free(ip); 04365 } else { 04366 con->ignorepats = ip->next; 04367 free(ip); 04368 } 04369 ast_mutex_unlock(&con->lock); 04370 return 0; 04371 } 04372 ipl = ip; 04373 } 04374 04375 ast_mutex_unlock(&con->lock); 04376 errno = EINVAL; 04377 return -1; 04378 }
|
|
||||||||||||||||
|
Remove a context include.
Definition at line 2564 of file pbx.c. References ast_context_remove_include2(), ast_unlock_contexts(), and find_context_locked(). Referenced by handle_context_remove_include(). 02565 { 02566 int ret = -1; 02567 struct ast_context *c = find_context_locked(context); 02568 02569 if (c) { 02570 /* found, remove include from this context ... */ 02571 ret = ast_context_remove_include2(c, include, registrar); 02572 ast_unlock_contexts(); 02573 } 02574 return ret; 02575 }
|
|
||||||||||||||||
|
Removes an include by an ast_context structure.
Definition at line 2585 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(). 02586 { 02587 struct ast_include *i, *pi = NULL; 02588 int ret = -1; 02589 02590 ast_mutex_lock(&con->lock); 02591 02592 /* find our include */ 02593 for (i = con->includes; i; pi = i, i = i->next) { 02594 if (!strcmp(i->name, include) && 02595 (!registrar || !strcmp(i->registrar, registrar))) { 02596 /* remove from list */ 02597 if (pi) 02598 pi->next = i->next; 02599 else 02600 con->includes = i->next; 02601 /* free include and return */ 02602 free(i); 02603 ret = 0; 02604 break; 02605 } 02606 } 02607 02608 ast_mutex_unlock(&con->lock); 02609 return ret; 02610 }
|
|
||||||||||||||||||||
|
Remove a switch.
Definition at line 2617 of file pbx.c. References ast_context_remove_switch2(), ast_unlock_contexts(), and find_context_locked(). 02618 { 02619 int ret = -1; /* default error return */ 02620 struct ast_context *c = find_context_locked(context); 02621 02622 if (c) { 02623 /* remove switch from this context ... */ 02624 ret = ast_context_remove_switch2(c, sw, data, registrar); 02625 ast_unlock_contexts(); 02626 } 02627 return ret; 02628 }
|
|
||||||||||||||||||||
|
This function locks given context, removes switch, unlock context and return.
Definition at line 2638 of file pbx.c. References AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_lock(), ast_mutex_unlock(), ast_sw::data, free, ast_context::lock, ast_sw::name, and ast_sw::registrar. Referenced by ast_context_remove_switch(). 02639 { 02640 struct ast_sw *i; 02641 int ret = -1; 02642 02643 ast_mutex_lock(&con->lock); 02644 02645 /* walk switches */ 02646 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) { 02647 if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 02648 (!registrar || !strcmp(i->registrar, registrar))) { 02649 /* found, remove from list */ 02650 AST_LIST_REMOVE_CURRENT(&con->alts, list); 02651 free(i); /* free switch and return */ 02652 ret = 0; 02653 break; 02654 } 02655 } 02656 AST_LIST_TRAVERSE_SAFE_END 02657 02658 ast_mutex_unlock(&con->lock); 02659 02660 return ret; 02661 }
|
|
|
Unlocks the macrolock in the given context.
Definition at line 2795 of file pbx.c. References ast_get_context_name(), ast_lock_contexts(), ast_mutex_unlock(), ast_unlock_contexts(), and ast_walk_contexts(). 02796 { 02797 struct ast_context *c = NULL; 02798 int ret = -1; 02799 02800 ast_lock_contexts(); 02801 02802 while ((c = ast_walk_contexts(c))) { 02803 if (!strcmp(ast_get_context_name(c), context)) { 02804 ret = 0; 02805 break; 02806 } 02807 } 02808 02809 ast_unlock_contexts(); 02810 02811 /* if we found context, unlock macrolock */ 02812 if (ret == 0) 02813 ret = ast_mutex_unlock(&c->macrolock); 02814 02815 return ret; 02816 }
|
|
|
Verifies includes in an ast_contect structure.
Definition at line 6146 of file pbx.c. References ast_context_find(), ast_get_context_name(), ast_log(), ast_walk_context_includes(), and ast_include::rname. Referenced by pbx_load_module(). 06147 { 06148 struct ast_include *inc = NULL; 06149 int res = 0; 06150 06151 while ( (inc = ast_walk_context_includes(con, inc)) ) 06152 if (!ast_context_find(inc->rname)) { 06153 res = -1; 06154 ast_log(LOG_WARNING, "Context '%s' tries includes nonexistent context '%s'\n", 06155 ast_get_context_name(con), inc->rname); 06156 } 06157 return res; 06158 }
|
|
|
Definition at line 1319 of file pbx.c. References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and ast_custom_function::name. Referenced by ast_func_read(), ast_func_write(), and handle_show_function(). 01320 { 01321 struct ast_custom_function *acf = NULL; 01322 01323 AST_RWLIST_RDLOCK(&acf_root); 01324 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) { 01325 if (!strcmp(name, acf->name)) 01326 break; 01327 } 01328 AST_RWLIST_UNLOCK(&acf_root); 01329 01330 return acf; 01331 }
|
|
|
Reigster a custom function.
Definition at line 1355 of file pbx.c. References ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verbose(), LOG_ERROR, ast_custom_function::name, option_verbose, and VERBOSE_PREFIX_2. Referenced by load_module(). 01356 { 01357 struct ast_custom_function *cur; 01358 01359 if (!acf) 01360 return -1; 01361 01362 AST_RWLIST_WRLOCK(&acf_root); 01363 01364 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) { 01365 if (!strcmp(acf->name, cur->name)) { 01366 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); 01367 AST_RWLIST_UNLOCK(&acf_root); 01368 return -1; 01369 } 01370 } 01371 01372 /* Store in alphabetical order */ 01373 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 01374 if (strcasecmp(acf->name, cur->name) < 0) { 01375 AST_RWLIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist); 01376 break; 01377 } 01378 } 01379 AST_RWLIST_TRAVERSE_SAFE_END 01380 if (!cur) 01381 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist); 01382 01383 AST_RWLIST_UNLOCK(&acf_root); 01384 01385 if (option_verbose > 1) 01386 ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name); 01387 01388 return 0; 01389 }
|
|
|
Unregister a custom function.
Definition at line 1333 of file pbx.c. References AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verbose(), ast_custom_function::name, option_verbose, and VERBOSE_PREFIX_2. Referenced by unload_module(). 01334 { 01335 struct ast_custom_function *cur; 01336 01337 if (!acf) 01338 return -1; 01339 01340 AST_RWLIST_WRLOCK(&acf_root); 01341 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) { 01342 if (cur == acf) { 01343 AST_RWLIST_REMOVE_CURRENT(&acf_root, acflist); 01344 if (option_verbose > 1) 01345 ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name); 01346 break; 01347 } 01348 } 01349 AST_RWLIST_TRAVERSE_SAFE_END 01350 AST_RWLIST_UNLOCK(&acf_root); 01351 01352 return acf ? 0 : -1; 01353 }
|
|
||||||||||||||||||||||||
|
||||||||||||||||||||
|
Definition at line 4463 of file pbx.c. References AST_FLAG_IN_AUTOLOOP, ast_strlen_zero(), ast_test_flag, ast_channel::context, ast_channel::exten, and ast_channel::priority. Referenced by __ast_goto_if_exists(), ast_async_goto(), ast_parseable_goto(), builtin_atxfer(), and handle_setpriority(). 04464 { 04465 if (!chan) 04466 return -1; 04467 04468 if (!ast_strlen_zero(context)) 04469 ast_copy_string(chan->context, context, sizeof(chan->context)); 04470 if (!ast_strlen_zero(exten)) 04471 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 04472 if (priority > -1) { 04473 chan->priority = priority; 04474 /* see flag description in channel.h for explanation */ 04475 if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)) 04476 chan->priority--; 04477 } 04478 04479 return 0; 04480 }
|
|
||||||||||||||||
|
Definition at line 857 of file pbx.c. References ast_log(), E_CANMATCH, E_MATCHMORE, extension_match_core(), and LOG_WARNING. Referenced by realtime_switch_common(). 00858 { 00859 if (needmore != E_MATCHMORE && needmore != E_CANMATCH) 00860 ast_log(LOG_WARNING, "invalid argument %d\n", needmore); 00861 return extension_match_core(pattern, data, needmore); 00862 }
|
|
||||||||||||
|
Determine if a given extension matches a given pattern (in NXX format).
Definition at line 852 of file pbx.c. References E_MATCH, and extension_match_core(). Referenced by ast_ignore_pattern(), loopback_canmatch(), loopback_exec(), loopback_exists(), loopback_matchmore(), manager_show_dialplan_helper(), matchcid(), misdn_cfg_is_msn_valid(), realtime_switch_common(), and show_dialplan_helper(). 00853 { 00854 return extension_match_core(pattern, data, E_MATCH); 00855 }
|
|
||||||||||||||||
|
Uses hint and devicestate callback to get the state of an extension.
Definition at line 1869 of file pbx.c. References ast_extension_state2(), and ast_hint_extension(). Referenced by action_extensionstate(), and handle_request_subscribe(). 01870 { 01871 struct ast_exten *e; 01872 01873 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */ 01874 if (!e) 01875 return -1; /* No hint, return -1 */ 01876 01877 return ast_extension_state2(e); /* Check all devices in the hint */ 01878 }
|
|
|
ast_extensions_state2: Check state of extension by using hints
Definition at line 1772 of file pbx.c. References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, ast_device_state(), AST_DEVICE_UNAVAILABLE, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, AST_EXTENSION_UNAVAILABLE, ast_get_extension_app(), AST_MAX_EXTENSION, inuse, ring(), and strsep(). Referenced by ast_add_hint(), ast_extension_state(), and ast_hint_state_changed(). 01773 { 01774 char hint[AST_MAX_EXTENSION]; 01775 char *cur, *rest; 01776 int allunavailable = 1, allbusy = 1, allfree = 1, allonhold = 1; 01777 int busy = 0, inuse = 0, ring = 0; 01778 01779 if (!e) 01780 return -1; 01781 01782 ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint)); 01783 01784 rest = hint; /* One or more devices separated with a & character */ 01785 while ( (cur = strsep(&rest, "&")) ) { 01786 int res = ast_device_state(cur); 01787 switch (res) { 01788 case AST_DEVICE_NOT_INUSE: 01789 allunavailable = 0; 01790 allbusy = 0; 01791 allonhold = 0; 01792 break; 01793 case AST_DEVICE_INUSE: 01794 inuse = 1; 01795 allunavailable = 0; 01796 allfree = 0; 01797 allonhold = 0; 01798 break; 01799 case AST_DEVICE_RINGING: 01800 ring = 1; 01801 allunavailable = 0; 01802 allfree = 0; 01803 allonhold = 0; 01804 break; 01805 case AST_DEVICE_RINGINUSE: 01806 inuse = 1; 01807 ring = 1; 01808 allunavailable = 0; 01809 allfree = 0; 01810 allonhold = 0; 01811 break; 01812 case AST_DEVICE_ONHOLD: 01813 allunavailable = 0; 01814 allfree = 0; 01815 break; 01816 case AST_DEVICE_BUSY: 01817 allunavailable = 0; 01818 allfree = 0; 01819 allonhold = 0; 01820 busy = 1; 01821 break; 01822 case AST_DEVICE_UNAVAILABLE: 01823 case AST_DEVICE_INVALID: 01824 allbusy = 0; 01825 allfree = 0; 01826 allonhold = 0; 01827 break; 01828 default: 01829 allunavailable = 0; 01830 allbusy = 0; 01831 allfree = 0; 01832 allonhold = 0; 01833 } 01834 } 01835 01836 if (!inuse && ring) 01837 return AST_EXTENSION_RINGING; 01838 if (inuse && ring) 01839 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); 01840 if (inuse) 01841 return AST_EXTENSION_INUSE; 01842 if (allfree) 01843 return AST_EXTENSION_NOT_INUSE; 01844 if (allonhold) 01845 return AST_EXTENSION_ONHOLD; 01846 if (allbusy) 01847 return AST_EXTENSION_BUSY; 01848 if (allunavailable) 01849 return AST_EXTENSION_UNAVAILABLE; 01850 if (busy) 01851 return AST_EXTENSION_INUSE; 01852 01853 return AST_EXTENSION_NOT_INUSE; 01854 }
|
|
|
Return string representation of the state of an extension.
Definition at line 1857 of file pbx.c. References extension_states. Referenced by cb_extensionstate(), handle_request_subscribe(), and handle_show_hints(). 01858 { 01859 int i; 01860 01861 for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) { 01862 if (extension_states[i].extension_state == extension_state) 01863 return extension_states[i].text; 01864 } 01865 return "Unknown"; 01866 }
|
|
||||||||||||||||||||
|
Registers a state change callback.
Definition at line 1924 of file pbx.c. References AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_state_cb::callback, ast_state_cb::data, ast_state_cb::next, and statecbs. Referenced by handle_request_subscribe(), and init_manager(). 01926 { 01927 struct ast_hint *hint; 01928 struct ast_state_cb *cblist; 01929 struct ast_exten *e; 01930 01931 /* If there's no context and extension: add callback to statecbs list */ 01932 if (!context && !exten) { 01933 AST_RWLIST_WRLOCK(&hints); 01934 01935 for (cblist = statecbs; cblist; cblist = cblist->next) { 01936 if (cblist->callback == callback) { 01937 cblist->data = data; 01938 AST_RWLIST_UNLOCK(&hints); 01939 return 0; 01940 } 01941 } 01942 01943 /* Now insert the callback */ 01944 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 01945 AST_RWLIST_UNLOCK(&hints); 01946 return -1; 01947 } 01948 cblist->id = 0; 01949 cblist->callback = callback; 01950 cblist->data = data; 01951 01952 cblist->next = statecbs; 01953 statecbs = cblist; 01954 01955 AST_RWLIST_UNLOCK(&hints); 01956 return 0; 01957 } 01958 01959 if (!context || !exten) 01960 return -1; 01961 01962 /* This callback type is for only one hint, so get the hint */ 01963 e = ast_hint_extension(NULL, context, exten); 01964 if (!e) { 01965 return -1; 01966 } 01967 01968 /* Find the hint in the list of hints */ 01969 AST_RWLIST_WRLOCK(&hints); 01970 01971 AST_RWLIST_TRAVERSE(&hints, hint, list) { 01972 if (hint->exten == e) 01973 break; 01974 } 01975 01976 if (!hint) { 01977 /* We have no hint, sorry */ 01978 AST_RWLIST_UNLOCK(&hints); 01979 return -1; 01980 } 01981 01982 /* Now insert the callback in the callback list */ 01983 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) { 01984 AST_RWLIST_UNLOCK(&hints); 01985 return -1; 01986 } 01987 cblist->id = stateid++; /* Unique ID for this callback */ 01988 cblist->callback = callback; /* Pointer to callback routine */ 01989 cblist->data = data; /* Data for the callback */ 01990 01991 cblist->next = hint->callbacks; 01992 hint->callbacks = cblist; 01993 01994 AST_RWLIST_UNLOCK(&hints); 01995 return cblist->id; 01996 }
|
|
||||||||||||
|
Deletes a registered state change callback by ID.
Definition at line 1999 of file pbx.c. References AST_RWLIST_WRLOCK, ast_state_cb::next, and statecbs. Referenced by __sip_destroy(). 02000 { 02001 struct ast_state_cb **p_cur = NULL; /* address of pointer to us */ 02002 int ret = -1; 02003 02004 if (!id && !callback) 02005 return -1; 02006 02007 AST_RWLIST_WRLOCK(&hints); 02008 02009 if (!id) { /* id == 0 is a callback without extension */ 02010 for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) { 02011 if ((*p_cur)->callback == callback) 02012 break; 02013 } 02014 } else { /* callback with extension, find the callback based on ID */ 02015 struct ast_hint *hint; 02016 AST_RWLIST_TRAVERSE(&hints, hint, list) { 02017 for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) { 02018 if ((*p_cur)->id == id) 02019 break; 02020 } 02021 if (*p_cur) /* found in the inner loop */ 02022 break; 02023 } 02024 } 02025 if (p_cur && *p_cur) { 02026 struct ast_state_cb *cur = *p_cur; 02027 *p_cur = cur->next; 02028 free(cur); 02029 ret = 0; 02030 } 02031 AST_RWLIST_UNLOCK(&hints); 02032 return ret; 02033 }
|
|
||||||||||||||||||||||||
|
Find the priority of an extension that has the specified label.
Definition at line 2148 of file pbx.c. References E_FINDLABEL, and pbx_extension_helper(). Referenced by action_originate(), action_redirect(), ast_parseable_goto(), and handle_setpriority(). 02149 { 02150 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL); 02151 }
|
|
||||||||||||||||||||||||
|
Find the priority of an extension that has the specified label.
Definition at line 2153 of file pbx.c. References E_FINDLABEL, and pbx_extension_helper(). 02154 { 02155 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL); 02156 }
|
|
||||||||||||||||||||
|
executes a read operation on a function
Definition at line 1411 of file pbx.c. References ast_custom_function_find(), ast_log(), ast_strdupa, copy(), func_args(), LOG_ERROR, and ast_custom_function::read. Referenced by action_getvar(), handle_getvariable(), and pbx_substitute_variables_helper_full(). 01412 { 01413 char *copy = ast_strdupa(function); 01414 char *args = func_args(copy); 01415 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 01416 01417 if (acfptr == NULL) 01418 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 01419 else if (!acfptr->read) 01420 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy); 01421 else 01422 return acfptr->read(chan, copy, args, workspace, len); 01423 return -1; 01424 }
|
|
||||||||||||||||
|
executes a write operation on a function
Definition at line 1426 of file pbx.c. References ast_custom_function_find(), ast_log(), ast_strdupa, copy(), func_args(), LOG_ERROR, and ast_custom_function::write. Referenced by pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper(). 01427 { 01428 char *copy = ast_strdupa(function); 01429 char *args = func_args(copy); 01430 struct ast_custom_function *acfptr = ast_custom_function_find(copy); 01431 01432 if (acfptr == NULL) 01433 ast_log(LOG_ERROR, "Function %s not registered\n", copy); 01434 else if (!acfptr->write) 01435 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy); 01436 else 01437 return acfptr->write(chan, copy, args, value); 01438 01439 return -1; 01440 }
|
|
|
Definition at line 6003 of file pbx.c. Referenced by ast_context_add_include2(), ast_context_add_switch2(), ast_context_lockmacro(), ast_context_unlockmacro(), ast_context_verify_includes(), complete_context_add_extension(), complete_context_add_ignorepat(), complete_context_add_include(), complete_context_remove_extension(), complete_context_remove_include(), complete_show_dialplan_context(), dundi_precache_full(), find_context_locked(), handle_save_dialplan(), handle_show_hints(), manager_show_dialplan_helper(), and show_dialplan_helper().
|
|
|
Definition at line 6041 of file pbx.c. References ast_context::registrar. Referenced by handle_save_dialplan(), and show_dialplan_helper(). 06042 { 06043 return c ? c->registrar : NULL; 06044 }
|
|
|
Definition at line 6071 of file pbx.c. References ast_exten::app. Referenced by ast_add_hint(), ast_extension_state2(), ast_get_hint(), ast_hint_state_changed(), handle_save_dialplan(), handle_show_hints(), manager_show_dialplan_helper(), and print_ext(). 06072 { 06073 return e ? e->app : NULL; 06074 }
|
|
|
Definition at line 6076 of file pbx.c. References ast_exten::data. Referenced by ast_get_hint(), handle_save_dialplan(), manager_show_dialplan_helper(), and print_ext(). 06077 { 06078 return e ? e->data : NULL; 06079 }
|
|
|
Definition at line 6066 of file pbx.c. References ast_exten::cidmatch. Referenced by handle_save_dialplan(). 06067 { 06068 return e ? e->cidmatch : NULL; 06069 }
|
|
|
Definition at line 6008 of file pbx.c. References exten. Referenced by handle_show_hints().
|
|
|
Definition at line 6018 of file pbx.c. References exten. Referenced by handle_save_dialplan(), manager_show_dialplan_helper(), and show_dialplan_helper().
|
|
|
Definition at line 6061 of file pbx.c. References ast_exten::matchcid. Referenced by handle_save_dialplan(). 06062 { 06063 return e ? e->matchcid : 0; 06064 }
|
|
|
Definition at line 6013 of file pbx.c. References exten. Referenced by ast_add_hint(), complete_context_remove_extension(), dundi_precache_full(), handle_save_dialplan(), handle_show_hints(), manager_show_dialplan_helper(), and show_dialplan_helper().
|
|
|
Definition at line 6033 of file pbx.c. References exten. Referenced by complete_context_remove_extension(), handle_save_dialplan(), manager_show_dialplan_helper(), and print_ext().
|
|
|
Definition at line 6046 of file pbx.c. References ast_exten::registrar. Referenced by handle_save_dialplan(), manager_show_dialplan_helper(), and show_dialplan_helper(). 06047 { 06048 return e ? e->registrar : NULL; 06049 }
|
|
||||||||||||||||||||||||||||||||
|
If an extension hint exists, return non-zero.
Definition at line 2126 of file pbx.c. References ast_get_extension_app(), ast_get_extension_app_data(), and ast_hint_extension(). Referenced by action_extensionstate(), pbx_retrieve_variable(), and transmit_state_notify(). 02127 { 02128 struct ast_exten *e = ast_hint_extension(c, context, exten); 02129 02130 if (e) { 02131 if (hint) 02132 ast_copy_string(hint, ast_get_extension_app(e), hintsize); 02133 if (name) { 02134 const char *tmp = ast_get_extension_app_data(e); 02135 if (tmp) 02136 ast_copy_string(name, tmp, namesize); 02137 } 02138 return -1; 02139 } 02140 return 0; 02141 }
|
|
|
Definition at line 6028 of file pbx.c. References ast_ignorepat::pattern. Referenced by complete_context_remove_ignorepat(), lookup_c_ip(), and manager_show_dialplan_helper(). 06029 { 06030 return ip ? ip->pattern : NULL; 06031 }
|
|
|
Definition at line 6056 of file pbx.c. References ast_ignorepat::registrar. Referenced by manager_show_dialplan_helper(). 06057 { 06058 return ip ? ip->registrar : NULL; 06059 }
|
|
|
Definition at line 6023 of file pbx.c. References ast_include::name. Referenced by complete_context_remove_include(), lookup_ci(), manager_show_dialplan_helper(), and show_dialplan_helper(). 06024 { 06025 return inc ? inc->name : NULL; 06026 }
|
|
|
Definition at line 6051 of file pbx.c. References ast_include::registrar. Referenced by manager_show_dialplan_helper(). 06052 { 06053 return i ? i->registrar : NULL; 06054 }
|
|
|
Definition at line 6086 of file pbx.c. References ast_sw::data. Referenced by manager_show_dialplan_helper(). 06087 { 06088 return sw ? sw->data : NULL; 06089 }
|
|
|
Definition at line 6081 of file pbx.c. References ast_sw::name. Referenced by manager_show_dialplan_helper(). 06082 { 06083 return sw ? sw->name : NULL; 06084 }
|
|