Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:37 2007

Asterisk developer's documentation :: Codename Pineapple


pbx.c File Reference


Detailed Description

Core PBX routines.

Author:
Mark Spencer <markster@digium.com>

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_contextast_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_contextast_context_find (const char *name)
 Find a context.
ast_contextast_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_functionast_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_contextast_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_extenast_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_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
ast_contextast_walk_contexts (struct ast_context *con)
ast_extenast_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_contextfind_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_extenpbx_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_apppbx_findapp (const char *app)
 Look up an application.
static struct ast_switchpbx_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_contextcontexts
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_cbstatecbs
static int stateid = 1


Define Documentation

#define AST_PBX_MAX_STACK   128
 

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

#define BACKGROUND_MATCHEXTEN   (1 << 2)
 

Definition at line 90 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_NOANSWER   (1 << 1)
 

Definition at line 89 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_PLAYBACK   (1 << 3)
 

Definition at line 91 of file pbx.c.

Referenced by pbx_builtin_background().

#define BACKGROUND_SKIP   (1 << 0)
 

Definition at line 88 of file pbx.c.

Referenced by pbx_builtin_background().

#define EXT_DATA_SIZE   8192
 

Note:
I M P O R T A N T :
The speed of extension handling will likely be among the most important aspects of this PBX. The switching scheme as it exists right now isn't terribly bad (it's O(N+M), where N is the # of extensions and M is the avg # of priorities, but a constant search time here would be great ;-)

Definition at line 77 of file pbx.c.

Referenced by pbx_extension_helper(), and realtime_exec().

#define SAY_STUBS
 

Definition at line 55 of file pbx.c.

#define STATUS_NO_CONTEXT   1
 

Definition at line 876 of file pbx.c.

Referenced by pbx_extension_helper(), and pbx_find_extension().

#define STATUS_NO_EXTENSION   2
 

Definition at line 877 of file pbx.c.

Referenced by pbx_extension_helper().

#define STATUS_NO_LABEL   4
 

Definition at line 879 of file pbx.c.

Referenced by pbx_extension_helper().

#define STATUS_NO_PRIORITY   3
 

Definition at line 878 of file pbx.c.

Referenced by pbx_extension_helper().

#define STATUS_SUCCESS   5
 

Definition at line 880 of file pbx.c.

#define SWITCH_DATA_LENGTH   256
 

Definition at line 80 of file pbx.c.

Referenced by ast_context_add_switch2().

#define VAR_BUF_SIZE   4096
 

Definition at line 82 of file pbx.c.

Referenced by ast_add_extension2(), pbx_builtin_importvar(), and pbx_substitute_variables_helper_full().

#define VAR_HARDTRAN   3
 

Definition at line 86 of file pbx.c.

#define VAR_NORMAL   1
 

Definition at line 84 of file pbx.c.

#define VAR_SOFTTRAN   2
 

Definition at line 85 of file pbx.c.

#define WAITEXTEN_MOH   (1 << 0)
 

Definition at line 100 of file pbx.c.

Referenced by pbx_builtin_waitexten().


Enumeration Type Documentation

enum ext_match_t
 

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.

Enumerator:
E_MATCHMORE 
E_CANMATCH 
E_MATCH 
E_MATCH_MASK 
E_SPAWN 
E_FINDLABEL 

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 };


Function Documentation

static struct ast_context* __ast_context_create struct ast_context **  extcontexts,
const char *  name,
const char *  registrar,
int  existsokay
[static]
 

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 }

void __ast_context_destroy struct ast_context con,
const char *  registrar
 

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 }

static int __ast_goto_if_exists struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
int  async
[static]
 

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 }

static int __ast_pbx_run struct ast_channel c  )  [static]
 

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 }

static int _extension_match_core const char *  pattern,
const char *  data,
enum ext_match_t  mode
[static]
 

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 }

static int add_pri struct ast_context con,
struct ast_exten tmp,
struct ast_exten el,
struct ast_exten e,
int  replace
[static]
 

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 }

int ast_active_calls void   ) 
 

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 }

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(*)(void *)  datad,
const char *  registrar
 

Add and extension to an extension context.

Parameters:
context context to add the extension to
replace 
extension extension to add
priority priority level of extension addition
label extension label
callerid pattern to match CallerID, or NULL to match any CallerID
application application to run on the extension with that priority level
data data to pass to the application
datad 
registrar who registered the extension
Return values:
0 success
-1 failure

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 }

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(*)(void *)  datad,
const char *  registrar
 

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 }

static int ast_add_hint struct ast_exten e  )  [static]
 

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 }

AST_APP_OPTIONS resetcdr_opts   ) 
 

AST_APP_OPTIONS waitexten_opts   ) 
 

AST_APP_OPTIONS background_opts   ) 
 

int ast_async_goto struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority
 

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 }

int ast_async_goto_by_name const char *  channame,
const char *  context,
const char *  exten,
int  priority
 

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 }

int ast_async_goto_if_exists struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority
 

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 }

int ast_build_timing struct ast_timing i,
const char *  info_in
 

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 }

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.

Parameters:
c not really important
context context to serach within
exten extension to check
priority priority of extension path
callerid callerid of extension being searched for
Returns:
If "exten" *could be* a valid extension in this context with or without some more digits, return non-zero. Basically, when this returns 0, no matter what you add to exten, it's not going to be a valid extension anymore

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 }

static int ast_change_hint struct ast_exten oe,
struct ast_exten ne
[static]
 

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 }

int ast_check_timing const struct ast_timing i  ) 
 

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 }

int ast_context_add_ignorepat const char *  context,
const char *  ignorepat,
const char *  registrar
 

Add an ignorepat.

Parameters:
context which context to add the ignorpattern to
ignorepat ignorepattern to set up for the extension
registrar registrar of the ignore pattern
Adds an ignore pattern to a particular context.

Return values:
0 on success
-1 on failure

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 }

int ast_context_add_ignorepat2 struct ast_context con,
const char *  value,
const char *  registrar
 

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 }

int ast_context_add_include const char *  context,
const char *  include,
const char *  registrar
 

Add a context include.

Parameters:
context context to add include to
include new include to add
registrar who's registering it
Adds an include taking a char * string as the context parameter

Return values:
0 on success
-1 on error

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 }

int ast_context_add_include2 struct ast_context con,
const char *  include,
const char *  registrar
 

Add a context include.

Parameters:
con context to add the include to
include include to add
registrar who registered the context
Adds an include taking a struct ast_context as the first parameter

Return values:
0 on success
-1 on failure

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 }

int ast_context_add_switch const char *  context,
const char *  sw,
const char *  data,
int  eval,
const char *  registrar
 

Add a switch.

Parameters:
context context to which to add the switch
sw switch to add
data data to pass to switch
eval whether to evaluate variables when running switch
registrar whoever registered the switch
This function registers a switch with the asterisk switch architecture

Return values:
0 on success
-1 on failure

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 }

int ast_context_add_switch2 struct ast_context con,
const char *  sw,
const char *  data,
int  eval,
const char *  registrar
 

Adds a switch (first param is a ast_context).

Note:
See ast_context_add_switch() for argument information, with the exception of the first argument. In this case, it's a pointer to an ast_context structure as opposed to the name.

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 }

struct ast_context* ast_context_create struct ast_context **  extcontexts,
const char *  name,
const char *  registrar
 

Register a new context.

Parameters:
extcontexts pointer to the ast_context structure pointer
name name of the new context
registrar registrar of the context
This will first search for a context with your name. If it exists already, it will not create a new one. If it does not exist, it will create a new one with the given name and registrar.

Returns:
NULL on failure, and an ast_context structure on success

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 }

void ast_context_destroy struct ast_context con,
const char *  registrar
 

Destroy a context (matches the specified context (or ANY context if NULL).

Parameters:
con context to destroy
registrar who registered it
You can optionally leave out either parameter. It will find it based on either the ast_context or the registrar name.

Returns:
nothing

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 }

struct ast_context* ast_context_find const char *  name  ) 
 

Find a context.

Parameters:
name name of the context to find
Will search for the context with the given name.

Returns:
the ast_context on success, NULL on failure.

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 }

struct 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.

Parameters:
extcontexts pointer to the ast_context structure pointer
name name of the new context
registrar registrar of the context
This will first search for a context with your name. If it exists already, it will not create a new one. If it does not exist, it will create a new one with the given name and registrar.

Returns:
NULL on failure, and an ast_context structure on success

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 }

int ast_context_lockmacro const char *  context  ) 
 

locks the macrolock in the given given context

Note:
This function locks contexts list by &conlist, searches for the right context structure, and locks the macrolock mutex in that context. macrolock is used to limit a macro to be executed by one call at a time.

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 }

int ast_context_remove_extension const char *  context,
const char *  extension,
int  priority,
const char *  registrar
 

Simply remove extension from context.

Parameters:
context context to remove extension from
extension which extension to remove
priority priority of extension to remove
registrar registrar of the extension
This function removes an extension from a given context.

Return values:
0 on success
-1 on failure

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 }

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.

Note:
When do you want to call this function, make sure that &conlock is locked, because some process can handle with your *con context before you lock it.

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 }

int ast_context_remove_ignorepat const char *  context,
const char *  ignorepat,
const char *  registrar
 

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 }

int ast_context_remove_ignorepat2 struct ast_context con,
const char *  ignorepat,
const char *  registrar
 

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 }

int ast_context_remove_include const char *  context,
const char *  include,
const char *  registrar
 

Remove a context include.

Note:
See ast_context_add_include for information on arguments
Return values:
0 on success
-1 on failure

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 }

int ast_context_remove_include2 struct ast_context con,
const char *  include,
const char *  registrar
 

Removes an include by an ast_context structure.

Note:
See ast_context_add_include2 for information on arguments
Return values:
0 on success
-1 on success

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 }

int ast_context_remove_switch const char *  context,
const char *  sw,
const char *  data,
const char *  registrar
 

Remove a switch.

Note:
This function locks contexts list by &conlist, search for the rigt context structure, leave context list locked and call ast_context_remove_switch2 which removes switch, unlock contexts list and return ...

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 }

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.

Note:
When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault.

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 }

int ast_context_unlockmacro const char *  context  ) 
 

Unlocks the macrolock in the given context.

Note:
This function locks contexts list by &conlist, searches for the right context structure, and unlocks the macrolock mutex in that context. macrolock is used to limit a macro to be executed by one call at a time.

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 }

int ast_context_verify_includes struct ast_context con  ) 
 

Verifies includes in an ast_contect structure.

Parameters:
con context in which to verify the includes
Return values:
0 if no problems found
-1 if there were any missing context

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 }

struct ast_custom_function* ast_custom_function_find const char *  name  ) 
 

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 }

int ast_custom_function_register struct ast_custom_function acf  ) 
 

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 }

int ast_custom_function_unregister struct ast_custom_function acf  ) 
 

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 }

int ast_exists_extension struct ast_channel c,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid
 

Determine whether an extension exists.

Parameters:
c this is not important
context which context to look in
exten which extension to search for
priority priority of the action within the extension
callerid callerid to search for
Returns:
If an extension within the given context(or callerid) with the given priority is found a non zero value will be returned. Otherwise, 0 is returned.

Definition at line 2143 of file pbx.c.

References E_MATCH, and pbx_extension_helper().

Referenced by __ast_goto_if_exists(), __ast_pbx_run(), __login_exec(), agentmonitoroutgoing_exec(), answer_call(), ast_park_call(), ast_pbx_outgoing_exten(), builtin_atxfer(), builtin_blindtransfer(), cb_events(), console_dial(), console_transfer(), dp_lookup(), dundi_lookup_local(), get_also_info(), get_destination(), get_refer_info(), handle_stimulus_message(), local_alloc(), local_devicestate(), loopback_exists(), metermaidstate(), mgcp_ss(), misdn_overlap_dial_task(), pbx_builtin_waitexten(), phone_check_exception(), process_ast_dsp(), register_peer_exten(), skinny_ss(), socket_process(), ss_thread(), waitstream_core(), and zt_read().

02144 {
02145    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH);
02146 }

int ast_explicit_goto struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority
 

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 }

int ast_extension_close const char *  pattern,
const char *  data,
int  needmore
 

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 }

int ast_extension_match const char *  pattern,
const char *  extension
 

Determine if a given extension matches a given pattern (in NXX format).

Parameters:
pattern pattern to match
extension extension to check against the pattern.
Checks whether or not the given extension matches the given pattern.

Return values:
1 on match
0 on failure

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 }

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.

Parameters:
c this is not important
context which context to look in
exten which extension to get state
Returns:
extension state as defined in the ast_extension_states enum

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 }

static int ast_extension_state2 struct ast_exten e  )  [static]
 

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 }

const char* ast_extension_state2str int  extension_state  ) 
 

Return string representation of the state of an extension.

Parameters:
extension_state is the numerical state delivered by ast_extension_state
Returns:
the state of an extension as string

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 }

int ast_extension_state_add const char *  context,
const char *  exten,
ast_state_cb_type  callback,
void *  data
 

Registers a state change callback.

Parameters:
context which context to look in
exten which extension to get state
callback callback to call if state changed
data to pass to callback
The callback is called if the state of an extension is changed.

Return values:
-1 on failure
ID on success

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 }

int ast_extension_state_del int  id,
ast_state_cb_type  callback
 

Deletes a registered state change callback by ID.

Parameters:
id of the callback to delete
callback callback
Removes the callback from list of callbacks

Return values:
0 success
-1 failure

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 }

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.

Parameters:
c this is not important
context which context to look in
exten which extension to search for
label label of the action within the extension to match to priority
callerid callerid to search for
Returns:
the priority which matches the given label in the extension or -1 if not found.

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 }

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.

Note:
This function is the same as ast_findlabel_extension, except that it accepts a pointer to an ast_context structure to specify the context instead of the name of the context. Otherwise, the functions behave the same.

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 }

int ast_func_read struct ast_channel chan,
const char *  function,
char *  workspace,
size_t  len
 

executes a read operation on a function

Parameters:
chan Channel to execute on
function Data containing the function call string (will be modified)
workspace A pointer to safe memory to use for a return value
len the number of bytes in workspace
This application executes a function in read mode on a given channel.

Returns:
zero on success, non-zero on failure

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 }

int ast_func_write struct ast_channel chan,
const char *  function,
const char *  value
 

executes a write operation on a function

Parameters:
chan Channel to execute on
function Data containing the function call string (will be modified)
value A value parameter to pass for writing
This application executes a function in write mode on a given channel.

Returns:
zero on success, non-zero on failure

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 }

const char* ast_get_context_name struct ast_context con  ) 
 

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

06004 {
06005    return con ? con->name : NULL;
06006 }

const char* ast_get_context_registrar struct ast_context c  ) 
 

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 }

const char* ast_get_extension_app struct ast_exten e  ) 
 

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 }

void* ast_get_extension_app_data struct ast_exten e  ) 
 

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 }

const char* ast_get_extension_cidmatch struct ast_exten e  ) 
 

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 }

struct ast_context* ast_get_extension_context struct ast_exten exten  ) 
 

Definition at line 6008 of file pbx.c.

References exten.

Referenced by handle_show_hints().

06009 {
06010    return exten ? exten->parent : NULL;
06011 }

const char* ast_get_extension_label struct ast_exten exten  ) 
 

Definition at line 6018 of file pbx.c.

References exten.

Referenced by handle_save_dialplan(), manager_show_dialplan_helper(), and show_dialplan_helper().

06019 {
06020    return exten ? exten->label : NULL;
06021 }

int ast_get_extension_matchcid struct ast_exten e  ) 
 

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 }

const char* ast_get_extension_name struct ast_exten exten  ) 
 

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

06014 {
06015    return exten ? exten->exten : NULL;
06016 }

int ast_get_extension_priority struct ast_exten exten  ) 
 

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

06034 {
06035    return exten ? exten->priority : -1;
06036 }

const char* ast_get_extension_registrar struct ast_exten e  ) 
 

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 }

int ast_get_hint char *  hint,
int  maxlen,
char *  name,
int  maxnamelen,
struct ast_channel c,
const char *  context,
const char *  exten
 

If an extension hint exists, return non-zero.

Parameters:
hint buffer for hint
maxlen size of hint buffer
name buffer for name portion of hint
maxnamelen size of name buffer
c this is not important
context which context to look in
exten which extension to search for
Returns:
If an extension within the given context with the priority PRIORITY_HINT is found a non zero value will be returned. Otherwise, 0 is returned.

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 }

const char* ast_get_ignorepat_name struct ast_ignorepat ip  ) 
 

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 }

const char* ast_get_ignorepat_registrar struct ast_ignorepat ip  ) 
 

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 }

const char* ast_get_include_name struct ast_include inc  ) 
 

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 }

const char* ast_get_include_registrar struct ast_include i  ) 
 

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 }

const char* ast_get_switch_data struct ast_sw sw  ) 
 

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 }

const char* ast_get_switch_name struct ast_sw sw  ) 
 

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 }

const char* ast_get_switch_registrar struct ast_sw sw  )