2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2008, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief Core PBX routines.
23 * \author Mark Spencer <markster@digium.com>
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
30 #include "asterisk/_private.h"
31 #include "asterisk/paths.h" /* use ast_config_AST_SYSTEM_NAME */
35 #if defined(HAVE_SYSINFO)
36 #include <sys/sysinfo.h>
39 #include <sys/loadavg.h>
42 #include "asterisk/lock.h"
43 #include "asterisk/cli.h"
44 #include "asterisk/pbx.h"
45 #include "asterisk/channel.h"
46 #include "asterisk/file.h"
47 #include "asterisk/callerid.h"
48 #include "asterisk/cdr.h"
49 #include "asterisk/config.h"
50 #include "asterisk/term.h"
51 #include "asterisk/manager.h"
52 #include "asterisk/ast_expr.h"
53 #include "asterisk/linkedlists.h"
54 #define SAY_STUBS /* generate declarations and stubs for say methods */
55 #include "asterisk/say.h"
56 #include "asterisk/utils.h"
57 #include "asterisk/causes.h"
58 #include "asterisk/musiconhold.h"
59 #include "asterisk/app.h"
60 #include "asterisk/devicestate.h"
61 #include "asterisk/stringfields.h"
62 #include "asterisk/event.h"
63 #include "asterisk/hashtab.h"
64 #include "asterisk/module.h"
65 #include "asterisk/indications.h"
68 * \note I M P O R T A N T :
70 * The speed of extension handling will likely be among the most important
71 * aspects of this PBX. The switching scheme as it exists right now isn't
72 * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
73 * of priorities, but a constant search time here would be great ;-)
75 * A new algorithm to do searching based on a 'compiled' pattern tree is introduced
76 * here, and shows a fairly flat (constant) search time, even for over
77 * 1000 patterns. Might Still needs some work-- there are some fine points of the matching
78 * spec about tie-breaking based on the characters in character sets, but this
79 * should be do-able via the weight system currently being used.
81 * Also, using a hash table for context/priority name lookup can help prevent
82 * the find_extension routines from absorbing exponential cpu cycles. I've tested
83 * find_extension with red-black trees, which have O(log2(n)) speed. Right now,
84 * I'm using hash tables, which do searches (ideally) in O(1) time.
89 #define EXT_DATA_SIZE 256
91 #define EXT_DATA_SIZE 8192
94 #define SWITCH_DATA_LENGTH 256
96 #define VAR_BUF_SIZE 4096
99 #define VAR_SOFTTRAN 2
100 #define VAR_HARDTRAN 3
102 #define BACKGROUND_SKIP (1 << 0)
103 #define BACKGROUND_NOANSWER (1 << 1)
104 #define BACKGROUND_MATCHEXTEN (1 << 2)
105 #define BACKGROUND_PLAYBACK (1 << 3)
107 AST_APP_OPTIONS(background_opts, {
108 AST_APP_OPTION('s', BACKGROUND_SKIP),
109 AST_APP_OPTION('n', BACKGROUND_NOANSWER),
110 AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN),
111 AST_APP_OPTION('p', BACKGROUND_PLAYBACK),
114 #define WAITEXTEN_MOH (1 << 0)
115 #define WAITEXTEN_DIALTONE (1 << 1)
117 AST_APP_OPTIONS(waitexten_opts, {
118 AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 0),
119 AST_APP_OPTION_ARG('d', WAITEXTEN_DIALTONE, 0),
126 \brief ast_exten: An extension
127 The dialplan is saved as a linked list with each context
128 having it's own linked list of extensions - one item per
132 char *exten; /*!< Extension name */
133 int matchcid; /*!< Match caller id ? */
134 const char *cidmatch; /*!< Caller id to match for this extension */
135 int priority; /*!< Priority */
136 const char *label; /*!< Label */
137 struct ast_context *parent; /*!< The context this extension belongs to */
138 const char *app; /*!< Application to execute */
139 struct ast_app *cached_app; /*!< Cached location of application */
140 void *data; /*!< Data to use (arguments) */
141 void (*datad)(void *); /*!< Data destructor */
142 struct ast_exten *peer; /*!< Next higher priority with our extension */
143 struct ast_hashtab *peer_tree; /*!< Priorities list in tree form -- only on the head of the peer list */
144 struct ast_hashtab *peer_label_tree; /*!< labeled priorities in the peer list -- only on the head of the peer list */
145 const char *registrar; /*!< Registrar */
146 struct ast_exten *next; /*!< Extension with a greater ID */
150 /*! \brief ast_include: include= support in extensions.conf */
153 const char *rname; /*!< Context to include */
154 const char *registrar; /*!< Registrar */
155 int hastime; /*!< If time construct exists */
156 struct ast_timing timing; /*!< time construct */
157 struct ast_include *next; /*!< Link them together */
161 /*! \brief ast_sw: Switch statement in extensions.conf */
164 const char *registrar; /*!< Registrar */
165 char *data; /*!< Data load */
167 AST_LIST_ENTRY(ast_sw) list;
172 /*! \brief ast_ignorepat: Ignore patterns in dial plan */
173 struct ast_ignorepat {
174 const char *registrar;
175 struct ast_ignorepat *next;
176 const char pattern[0];
179 /*! \brief match_char: forms a syntax tree for quick matching of extension patterns */
182 int is_pattern; /* the pattern started with '_' */
183 int deleted; /* if this is set, then... don't return it */
184 char *x; /* the pattern itself-- matches a single char */
185 int specificity; /* simply the strlen of x, or 10 for X, 9 for Z, and 8 for N; and '.' and '!' will add 11 ? */
186 struct match_char *alt_char;
187 struct match_char *next_char;
188 struct ast_exten *exten; /* attached to last char of a pattern for exten */
191 struct scoreboard /* make sure all fields are 0 before calling new_find_extension */
193 int total_specificity;
195 char last_char; /* set to ! or . if they are the end of the pattern */
196 int canmatch; /* if the string to match was just too short */
197 struct match_char *node;
198 struct ast_exten *canmatch_exten;
199 struct ast_exten *exten;
202 /*! \brief ast_context: An extension context */
204 ast_rwlock_t lock; /*!< A lock to prevent multiple threads from clobbering the context */
205 struct ast_exten *root; /*!< The root of the list of extensions */
206 struct ast_hashtab *root_tree; /*!< For exact matches on the extensions in the pattern tree, and for traversals of the pattern_tree */
207 struct match_char *pattern_tree; /*!< A tree to speed up extension pattern matching */
208 struct ast_context *next; /*!< Link them together */
209 struct ast_include *includes; /*!< Include other contexts */
210 struct ast_ignorepat *ignorepats; /*!< Patterns for which to continue playing dialtone */
211 const char *registrar; /*!< Registrar */
212 AST_LIST_HEAD_NOLOCK(, ast_sw) alts; /*!< Alternative switches */
213 ast_mutex_t macrolock; /*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
214 char name[0]; /*!< Name of the context */
218 /*! \brief ast_app: A registered application */
220 int (*execute)(struct ast_channel *chan, void *data);
221 const char *synopsis; /*!< Synopsis text for 'show applications' */
222 const char *description; /*!< Description (help text) for 'show application <name>' */
223 AST_RWLIST_ENTRY(ast_app) list; /*!< Next app in list */
224 struct ast_module *module; /*!< Module this app belongs to */
225 char name[0]; /*!< Name of the application */
228 /*! \brief ast_state_cb: An extension state notify register item */
229 struct ast_state_cb {
232 ast_state_cb_type callback;
233 struct ast_state_cb *next;
236 /*! \brief Structure for dial plan hints
238 \note Hints are pointers from an extension in the dialplan to one or
239 more devices (tech/name)
240 - See \ref AstExtState
243 struct ast_exten *exten; /*!< Extension */
244 int laststate; /*!< Last known state */
245 struct ast_state_cb *callbacks; /*!< Callback list for this extension */
246 AST_RWLIST_ENTRY(ast_hint) list;/*!< Pointer to next hint in list */
249 static const struct cfextension_states {
251 const char * const text;
252 } extension_states[] = {
253 { AST_EXTENSION_NOT_INUSE, "Idle" },
254 { AST_EXTENSION_INUSE, "InUse" },
255 { AST_EXTENSION_BUSY, "Busy" },
256 { AST_EXTENSION_UNAVAILABLE, "Unavailable" },
257 { AST_EXTENSION_RINGING, "Ringing" },
258 { AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" },
259 { AST_EXTENSION_ONHOLD, "Hold" },
260 { AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD, "InUse&Hold" }
264 AST_LIST_ENTRY(statechange) entry;
269 * \brief Data used by the device state thread
272 /*! Set to 1 to stop the thread */
274 /*! The device state monitoring thread */
276 /*! Lock for the state change queue */
278 /*! Condition for the state change queue */
280 /*! Queue of state changes */
281 AST_LIST_HEAD_NOLOCK(, statechange) state_change_q;
283 .thread = AST_PTHREADT_NULL,
286 struct pbx_exception {
287 AST_DECLARE_STRING_FIELDS(
288 AST_STRING_FIELD(context); /*!< Context associated with this exception */
289 AST_STRING_FIELD(exten); /*!< Exten associated with this exception */
290 AST_STRING_FIELD(reason); /*!< The exception reason */
293 int priority; /*!< Priority associated with this exception */
296 static int pbx_builtin_answer(struct ast_channel *, void *);
297 static int pbx_builtin_goto(struct ast_channel *, void *);
298 static int pbx_builtin_hangup(struct ast_channel *, void *);
299 static int pbx_builtin_background(struct ast_channel *, void *);
300 static int pbx_builtin_wait(struct ast_channel *, void *);
301 static int pbx_builtin_waitexten(struct ast_channel *, void *);
302 static int pbx_builtin_keepalive(struct ast_channel *, void *);
303 static int pbx_builtin_resetcdr(struct ast_channel *, void *);
304 static int pbx_builtin_setamaflags(struct ast_channel *, void *);
305 static int pbx_builtin_ringing(struct ast_channel *, void *);
306 static int pbx_builtin_progress(struct ast_channel *, void *);
307 static int pbx_builtin_congestion(struct ast_channel *, void *);
308 static int pbx_builtin_busy(struct ast_channel *, void *);
309 static int pbx_builtin_noop(struct ast_channel *, void *);
310 static int pbx_builtin_gotoif(struct ast_channel *, void *);
311 static int pbx_builtin_gotoiftime(struct ast_channel *, void *);
312 static int pbx_builtin_execiftime(struct ast_channel *, void *);
313 static int pbx_builtin_saynumber(struct ast_channel *, void *);
314 static int pbx_builtin_saydigits(struct ast_channel *, void *);
315 static int pbx_builtin_saycharacters(struct ast_channel *, void *);
316 static int pbx_builtin_sayphonetic(struct ast_channel *, void *);
317 static int matchcid(const char *cidpattern, const char *callerid);
318 int pbx_builtin_setvar(struct ast_channel *, void *);
319 void log_match_char_tree(struct match_char *node, char *prefix); /* for use anywhere */
320 static int pbx_builtin_setvar_multiple(struct ast_channel *, void *);
321 static int pbx_builtin_importvar(struct ast_channel *, void *);
322 static void set_ext_pri(struct ast_channel *c, const char *exten, int pri);
323 static void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid);
324 static struct match_char *already_in_tree(struct match_char *current, char *pat);
325 static struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly);
326 static struct match_char *add_pattern_node(struct ast_context *con, struct match_char *current, char *pattern, int is_pattern, int already, int specificity);
327 static void create_match_char_tree(struct ast_context *con);
328 static struct ast_exten *get_canmatch_exten(struct match_char *node);
329 static void destroy_pattern_tree(struct match_char *pattern_tree);
330 static int hashtab_compare_contexts(const void *ah_a, const void *ah_b);
331 static int hashtab_compare_extens(const void *ha_a, const void *ah_b);
332 static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b);
333 static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b);
334 static unsigned int hashtab_hash_contexts(const void *obj);
335 static unsigned int hashtab_hash_extens(const void *obj);
336 static unsigned int hashtab_hash_priority(const void *obj);
337 static unsigned int hashtab_hash_labels(const void *obj);
339 /* labels, contexts are case sensitive priority numbers are ints */
340 static int hashtab_compare_contexts(const void *ah_a, const void *ah_b)
342 const struct ast_context *ac = ah_a;
343 const struct ast_context *bc = ah_b;
344 /* assume context names are registered in a string table! */
345 return strcmp(ac->name, bc->name);
348 static int hashtab_compare_extens(const void *ah_a, const void *ah_b)
350 const struct ast_exten *ac = ah_a;
351 const struct ast_exten *bc = ah_b;
352 int x = strcmp(ac->exten, bc->exten);
353 if (x) /* if exten names are diff, then return */
355 /* but if they are the same, do the cidmatch values match? */
356 if (ac->matchcid && bc->matchcid) {
357 return strcmp(ac->cidmatch,bc->cidmatch);
358 } else if (!ac->matchcid && !bc->matchcid) {
359 return 0; /* if there's no matchcid on either side, then this is a match */
361 return 1; /* if there's matchcid on one but not the other, they are different */
365 static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b)
367 const struct ast_exten *ac = ah_a;
368 const struct ast_exten *bc = ah_b;
369 return ac->priority != bc->priority;
372 static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b)
374 const struct ast_exten *ac = ah_a;
375 const struct ast_exten *bc = ah_b;
376 return strcmp(ac->label, bc->label);
379 static unsigned int hashtab_hash_contexts(const void *obj)
381 const struct ast_context *ac = obj;
382 return ast_hashtab_hash_string(ac->name);
385 static unsigned int hashtab_hash_extens(const void *obj)
387 const struct ast_exten *ac = obj;
388 unsigned int x = ast_hashtab_hash_string(ac->exten);
391 y = ast_hashtab_hash_string(ac->cidmatch);
395 static unsigned int hashtab_hash_priority(const void *obj)
397 const struct ast_exten *ac = obj;
398 return ast_hashtab_hash_int(ac->priority);
401 static unsigned int hashtab_hash_labels(const void *obj)
403 const struct ast_exten *ac = obj;
404 return ast_hashtab_hash_string(ac->label);
408 AST_RWLOCK_DEFINE_STATIC(globalslock);
409 static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
411 static int autofallthrough = 1;
412 static int extenpatternmatchnew = 0;
414 /*! \brief Subscription for device state change events */
415 static struct ast_event_sub *device_state_sub;
417 AST_MUTEX_DEFINE_STATIC(maxcalllock);
418 static int countcalls;
419 static int totalcalls;
421 static AST_RWLIST_HEAD_STATIC(acf_root, ast_custom_function);
423 /*! \brief Declaration of builtin applications */
424 static struct pbx_builtin {
425 char name[AST_MAX_APP];
426 int (*execute)(struct ast_channel *chan, void *data);
431 /* These applications are built into the PBX core and do not
432 need separate modules */
434 { "Answer", pbx_builtin_answer,
435 "Answer a channel if ringing",
436 " Answer([delay]): If the call has not been answered, this application will\n"
437 "answer it. Otherwise, it has no effect on the call. If a delay is specified,\n"
438 "Asterisk will wait this number of milliseconds before returning to\n"
439 "the dialplan after answering the call.\n"
442 { "BackGround", pbx_builtin_background,
443 "Play an audio file while waiting for digits of an extension to go to.",
444 " Background(filename1[&filename2...][,options[,langoverride][,context]]):\n"
445 "This application will play the given list of files (do not put extension)\n"
446 "while waiting for an extension to be dialed by the calling channel. To\n"
447 "continue waiting for digits after this application has finished playing\n"
448 "files, the WaitExten application should be used. The 'langoverride' option\n"
449 "explicitly specifies which language to attempt to use for the requested sound\n"
450 "files. If a 'context' is specified, this is the dialplan context that this\n"
451 "application will use when exiting to a dialed extension."
452 " If one of the requested sound files does not exist, call processing will be\n"
455 " s - Causes the playback of the message to be skipped\n"
456 " if the channel is not in the 'up' state (i.e. it\n"
457 " hasn't been answered yet). If this happens, the\n"
458 " application will return immediately.\n"
459 " n - Don't answer the channel before playing the files.\n"
460 " m - Only break if a digit hit matches a one digit\n"
461 " extension in the destination context.\n"
462 "This application sets the following channel variable upon completion:\n"
463 " BACKGROUNDSTATUS The status of the background attempt as a text string, one of\n"
464 " SUCCESS | FAILED\n"
467 { "Busy", pbx_builtin_busy,
468 "Indicate the Busy condition",
469 " Busy([timeout]): This application will indicate the busy condition to\n"
470 "the calling channel. If the optional timeout is specified, the calling channel\n"
471 "will be hung up after the specified number of seconds. Otherwise, this\n"
472 "application will wait until the calling channel hangs up.\n"
475 { "Congestion", pbx_builtin_congestion,
476 "Indicate the Congestion condition",
477 " Congestion([timeout]): This application will indicate the congestion\n"
478 "condition to the calling channel. If the optional timeout is specified, the\n"
479 "calling channel will be hung up after the specified number of seconds.\n"
480 "Otherwise, this application will wait until the calling channel hangs up.\n"
483 { "ExecIfTime", pbx_builtin_execiftime,
484 "Conditional application execution based on the current time",
485 " ExecIfTime(<times>,<weekdays>,<mdays>,<months>?appname[(appargs)]):\n"
486 "This application will execute the specified dialplan application, with optional\n"
487 "arguments, if the current time matches the given time specification.\n"
490 { "Goto", pbx_builtin_goto,
491 "Jump to a particular priority, extension, or context",
492 " Goto([[context,]extension,]priority): This application will set the current\n"
493 "context, extension, and priority in the channel structure. After it completes, the\n"
494 "pbx engine will continue dialplan execution at the specified location.\n"
495 "If no specific extension, or extension and context, are specified, then this\n"
496 "application will just set the specified priority of the current extension.\n"
497 " At least a priority is required as an argument, or the goto will return a -1,\n"
498 "and the channel and call will be terminated.\n"
499 " If the location that is put into the channel information is bogus, and asterisk cannot\n"
500 "find that location in the dialplan,\n"
501 "then the execution engine will try to find and execute the code in the 'i' (invalid)\n"
502 "extension in the current context. If that does not exist, it will try to execute the\n"
503 "'h' extension. If either or neither the 'h' or 'i' extensions have been defined, the\n"
504 "channel is hung up, and the execution of instructions on the channel is terminated.\n"
505 "What this means is that, for example, you specify a context that does not exist, then\n"
506 "it will not be possible to find the 'h' or 'i' extensions, and the call will terminate!\n"
509 { "GotoIf", pbx_builtin_gotoif,
511 " GotoIf(condition?[labeliftrue]:[labeliffalse]): This application will set the current\n"
512 "context, extension, and priority in the channel structure based on the evaluation of\n"
513 "the given condition. After this application completes, the\n"
514 "pbx engine will continue dialplan execution at the specified location in the dialplan.\n"
515 "The channel will continue at\n"
516 "'labeliftrue' if the condition is true, or 'labeliffalse' if the condition is\n"
517 "false. The labels are specified with the same syntax as used within the Goto\n"
518 "application. If the label chosen by the condition is omitted, no jump is\n"
519 "performed, and the execution passes to the next instruction.\n"
520 "If the target location is bogus, and does not exist, the execution engine will try \n"
521 "to find and execute the code in the 'i' (invalid)\n"
522 "extension in the current context. If that does not exist, it will try to execute the\n"
523 "'h' extension. If either or neither the 'h' or 'i' extensions have been defined, the\n"
524 "channel is hung up, and the execution of instructions on the channel is terminated.\n"
525 "Remember that this command can set the current context, and if the context specified\n"
526 "does not exist, then it will not be able to find any 'h' or 'i' extensions there, and\n"
527 "the channel and call will both be terminated!\n"
530 { "GotoIfTime", pbx_builtin_gotoiftime,
531 "Conditional Goto based on the current time",
532 " GotoIfTime(<times>,<weekdays>,<mdays>,<months>?[labeliftrue]:[labeliffalse]):\n"
533 "This application will set the context, extension, and priority in the channel structure\n"
534 "based on the evaluation of the given time specification. After this application completes,\n"
535 "the pbx engine will continue dialplan execution at the specified location in the dialplan.\n"
536 "If the current time is within the given time specification, the channel will continue at\n"
537 "'labeliftrue'. Otherwise the channel will continue at 'labeliffalse'. If the label chosen\n"
538 "by the condition is omitted, no jump is performed, and execution passes to the next\n"
539 "instruction. If the target jump location is bogus, the same actions would be taken as for\n"
541 "Further information on the time specification can be found in examples\n"
542 "illustrating how to do time-based context includes in the dialplan.\n"
545 { "ImportVar", pbx_builtin_importvar,
546 "Import a variable from a channel into a new variable",
547 " ImportVar(newvar=channelname,variable): This application imports a variable\n"
548 "from the specified channel (as opposed to the current one) and stores it as\n"
549 "a variable in the current channel (the channel that is calling this\n"
550 "application). Variables created by this application have the same inheritance\n"
551 "properties as those created with the Set application. See the documentation for\n"
552 "Set for more information.\n"
555 { "Hangup", pbx_builtin_hangup,
556 "Hang up the calling channel",
557 " Hangup([causecode]): This application will hang up the calling channel.\n"
558 "If a causecode is given the channel's hangup cause will be set to the given\n"
562 { "NoOp", pbx_builtin_noop,
563 "Do Nothing (No Operation)",
564 " NoOp(): This application does nothing. However, it is useful for debugging\n"
565 "purposes. Any text that is provided as arguments to this application can be\n"
566 "viewed at the Asterisk CLI. This method can be used to see the evaluations of\n"
567 "variables or functions without having any effect. Alternatively, see the\n"
568 "Verbose() application for finer grain control of output at custom verbose levels.\n"
571 { "Progress", pbx_builtin_progress,
573 " Progress(): This application will request that in-band progress information\n"
574 "be provided to the calling channel.\n"
577 { "RaiseException", pbx_builtin_raise_exception,
578 "Handle an exceptional condition",
579 " RaiseException(<reason>): This application will jump to the \"e\" extension\n"
580 "in the current context, setting the dialplan function EXCEPTION(). If the \"e\"\n"
581 "extension does not exist, the call will hangup.\n"
584 { "ResetCDR", pbx_builtin_resetcdr,
585 "Resets the Call Data Record",
586 " ResetCDR([options]): This application causes the Call Data Record to be\n"
589 " w -- Store the current CDR record before resetting it.\n"
590 " a -- Store any stacked records.\n"
591 " v -- Save CDR variables.\n"
592 " e -- Enable CDR only (negate effects of NoCDR).\n"
595 { "Ringing", pbx_builtin_ringing,
596 "Indicate ringing tone",
597 " Ringing(): This application will request that the channel indicate a ringing\n"
598 "tone to the user.\n"
601 { "SayAlpha", pbx_builtin_saycharacters,
603 " SayAlpha(string): This application will play the sounds that correspond to\n"
604 "the letters of the given string.\n"
607 { "SayDigits", pbx_builtin_saydigits,
609 " SayDigits(digits): This application will play the sounds that correspond\n"
610 "to the digits of the given number. This will use the language that is currently\n"
611 "set for the channel. See the LANGUAGE function for more information on setting\n"
612 "the language for the channel.\n"
615 { "SayNumber", pbx_builtin_saynumber,
617 " SayNumber(digits[,gender]): This application will play the sounds that\n"
618 "correspond to the given number. Optionally, a gender may be specified.\n"
619 "This will use the language that is currently set for the channel. See the\n"
620 "LANGUAGE function for more information on setting the language for the channel.\n"
623 { "SayPhonetic", pbx_builtin_sayphonetic,
625 " SayPhonetic(string): This application will play the sounds from the phonetic\n"
626 "alphabet that correspond to the letters in the given string.\n"
629 { "Set", pbx_builtin_setvar,
630 "Set channel variable or function value",
632 "This function can be used to set the value of channel variables or dialplan\n"
633 "functions. When setting variables, if the variable name is prefixed with _,\n"
634 "the variable will be inherited into channels created from the current\n"
635 "channel. If the variable name is prefixed with __, the variable will be\n"
636 "inherited into channels created from the current channel and all children\n"
640 { "MSet", pbx_builtin_setvar_multiple,
641 "Set channel variable(s) or function value(s)",
642 " MSet(name1=value1,name2=value2,...)\n"
643 "This function can be used to set the value of channel variables or dialplan\n"
644 "functions. When setting variables, if the variable name is prefixed with _,\n"
645 "the variable will be inherited into channels created from the current\n"
646 "channel. If the variable name is prefixed with __, the variable will be\n"
647 "inherited into channels created from the current channel and all children\n"
649 "MSet behaves in a similar fashion to the way Set worked in 1.2/1.4 and is thus\n"
650 "prone to doing things that you may not expect. Avoid its use if possible.\n"
653 { "SetAMAFlags", pbx_builtin_setamaflags,
655 " SetAMAFlags([flag]): This application will set the channel's AMA Flags for\n"
656 " billing purposes.\n"
659 { "Wait", pbx_builtin_wait,
660 "Waits for some time",
661 " Wait(seconds): This application waits for a specified number of seconds.\n"
662 "Then, dialplan execution will continue at the next priority.\n"
663 " Note that the seconds can be passed with fractions of a second. For example,\n"
664 "'1.5' will ask the application to wait for 1.5 seconds.\n"
667 { "WaitExten", pbx_builtin_waitexten,
668 "Waits for an extension to be entered",
669 " WaitExten([seconds][,options]): This application waits for the user to enter\n"
670 "a new extension for a specified number of seconds.\n"
671 " Note that the seconds can be passed with fractions of a second. For example,\n"
672 "'1.5' will ask the application to wait for 1.5 seconds.\n"
674 " m[(x)] - Provide music on hold to the caller while waiting for an extension.\n"
675 " Optionally, specify the class for music on hold within parenthesis.\n"
678 { "KeepAlive", pbx_builtin_keepalive,
679 "returns AST_PBX_KEEPALIVE value",
680 " KeepAlive(): This application is chiefly meant for internal use with Gosubs.\n"
681 "Please do not run it alone from the dialplan!\n"
686 static struct ast_context *contexts;
687 static struct ast_hashtab *contexts_tree = NULL;
689 AST_RWLOCK_DEFINE_STATIC(conlock); /*!< Lock for the ast_context list */
691 static AST_RWLIST_HEAD_STATIC(apps, ast_app);
693 static AST_RWLIST_HEAD_STATIC(switches, ast_switch);
695 static int stateid = 1;
697 When holding this list's lock, do _not_ do anything that will cause conlock
698 to be taken, unless you _already_ hold it. The ast_merge_contexts_and_delete
699 function will take the locks in conlock/hints order, so any other
700 paths that require both locks must also take them in that order.
702 static AST_RWLIST_HEAD_STATIC(hints, ast_hint);
703 struct ast_state_cb *statecbs;
706 \note This function is special. It saves the stack so that no matter
707 how many times it is called, it returns to the same place */
708 int pbx_exec(struct ast_channel *c, /*!< Channel */
709 struct ast_app *app, /*!< Application */
710 void *data) /*!< Data for execution */
713 struct ast_module_user *u = NULL;
714 const char *saved_c_appl;
715 const char *saved_c_data;
717 if (c->cdr && !ast_check_hangup(c))
718 ast_cdr_setapp(c->cdr, app->name, data);
720 /* save channel values */
721 saved_c_appl= c->appl;
722 saved_c_data= c->data;
727 u = __ast_module_user_add(app->module, c);
728 res = app->execute(c, S_OR(data, ""));
729 if (app->module && u)
730 __ast_module_user_remove(app->module, u);
731 /* restore channel values */
732 c->appl = saved_c_appl;
733 c->data = saved_c_data;
738 /*! Go no deeper than this through includes (not counting loops) */
739 #define AST_PBX_MAX_STACK 128
741 /*! \brief Find application handle in linked list
743 struct ast_app *pbx_findapp(const char *app)
747 AST_RWLIST_RDLOCK(&apps);
748 AST_RWLIST_TRAVERSE(&apps, tmp, list) {
749 if (!strcasecmp(tmp->name, app))
752 AST_RWLIST_UNLOCK(&apps);
757 static struct ast_switch *pbx_findswitch(const char *sw)
759 struct ast_switch *asw;
761 AST_RWLIST_RDLOCK(&switches);
762 AST_RWLIST_TRAVERSE(&switches, asw, list) {
763 if (!strcasecmp(asw->name, sw))
766 AST_RWLIST_UNLOCK(&switches);
771 static inline int include_valid(struct ast_include *i)
776 return ast_check_timing(&(i->timing));
779 static void pbx_destroy(struct ast_pbx *p)
784 /* form a tree that fully describes all the patterns in a context's extensions
785 * in this tree, a "node" consists of a series of match_char structs linked in a chain
786 * via the alt_char pointers. More than one pattern can share the same parts of the
787 * tree as other extensions with the same pattern to that point. The algorithm to
788 * find which pattern best matches a string, would follow **all** matching paths. As
789 * complete matches are found, a "max" match record would be updated if the match first involves
790 * a longer string, then, on a tie, a smaller total of specificity. This can be accomplished
791 * by recursive calls affecting a shared scoreboard.
792 * As and example, consider these 4 extensions:
798 * In the above, between (a) and (d), (a) is a more specific pattern than (d), and would win over
799 * most numbers. For all numbers beginning with 307754, (b) should always win.
801 * These pattern should form a tree that looks like this:
802 * { "N" } --next--> { "X" } --next--> { "X" } --next--> { "N" } --next--> { "X" } ... blah ... --> { "X" exten_match: (a) }
806 * | { "X" } --next--> { "X" } ... blah ... --> { "X" exten_match: (d) }
808 * { "3" } --next--> { "0" } --next--> { "7" } --next--> { "7" } --next--> { "5" } ... blah ... --> { "X" exten_match: (b) }
812 * { "f" } --next--> { "a" } --next--> { "x" exten_match: (c) }
814 * In the above, I could easily turn "N" into "23456789", but I think that a quick "if( *z >= '2' && *z <= '9' )" might take
815 * fewer CPU cycles than a call to index("23456789",*z), where *z is the char to match...
817 * traversal is pretty simple: one routine merely traverses the alt list, and for each match in the pattern, it calls itself
818 * on the corresponding next pointer, incrementing also the pointer of the string to be matched, and passing the total specificity and length.
819 * We pass a pointer to a scoreboard down through, also.
820 * When an exten_match pointer is set, or a '.' or a '!' is encountered, we update the scoreboard only if the length is greater, or in case
821 * of equal length, if the specificity is lower, and return. Hope the limit on stack depth won't be a problem... this routine should
822 * be pretty lean as far a stack usage goes. Any non-match terminates the recursion down a branch.
824 * In the above example, with the number "3077549999" as the pattern, the traversor should match extensions a, b and d. All are
825 * of length 10; but they have total specificities of 96, 46, and 98, respectively. (b) wins with its lower specificity number!
827 * Just how much time this algorithm might save over a plain linear traversal over all possible patterns is unknown. But, it should
828 * be pretty close to optimal for this sort of overall algorithm.
832 /* you only really update the scoreboard, if the new score is BETTER than the
833 * one stored there. ignore it otherwise.
837 static void update_scoreboard(struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node)
839 /* doing a matchcid() check here would be easy and cheap, but...
840 unfortunately, it only works if an extension can have only one
841 cid to match. That's not real life. CID patterns need to exist
842 in the tree for this sort of thing to work properly. */
844 /* if this extension is marked as deleted, then skip this -- if it never shows
845 on the scoreboard, it will never be found */
848 if (length > board->total_length) {
849 board->total_specificity = spec;
850 board->total_length = length;
851 board->exten = exten;
852 board->last_char = last;
854 } else if (length == board->total_length && spec < board->total_specificity) {
855 board->total_specificity = spec;
856 board->total_length = length;
857 board->exten = exten;
858 board->last_char = last;
863 void log_match_char_tree(struct match_char *node, char *prefix)
866 struct ast_str *my_prefix = ast_str_alloca(1024);
870 if (node && node->exten && node->exten)
871 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
873 if (strlen(node->x) > 1) {
874 ast_debug(1, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N',
875 node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"",
876 node->exten ? node->exten->exten : "", extenstr);
878 ast_debug(1, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N',
879 node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"",
880 node->exten ? node->exten->exten : "", extenstr);
883 ast_str_set(&my_prefix, 0, "%s+ ", prefix);
886 log_match_char_tree(node->next_char, my_prefix->str);
889 log_match_char_tree(node->alt_char, prefix);
892 static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
895 struct ast_str *my_prefix = ast_str_alloca(1024);
899 if (node && node->exten && node->exten)
900 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
902 if (strlen(node->x) > 1) {
903 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
904 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
905 node->exten ? node->exten->exten : "", extenstr);
907 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
908 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
909 node->exten ? node->exten->exten : "", extenstr);
912 ast_str_set(&my_prefix, 0, "%s+ ", prefix);
915 cli_match_char_tree(node->next_char, my_prefix->str, fd);
918 cli_match_char_tree(node->alt_char, prefix, fd);
921 static struct ast_exten *get_canmatch_exten(struct match_char *node)
923 /* find the exten at the end of the rope */
924 struct match_char *node2 = node;
926 for (node2 = node; node2; node2 = node2->next_char) {
934 static struct ast_exten *trie_find_next_match(struct match_char *node)
936 struct match_char *m3;
937 struct match_char *m4;
938 struct ast_exten *e3;
940 if (node && node->x[0] == '.' && !node->x[1]) /* dot and ! will ALWAYS be next match in a matchmore */
943 if (node && node->x[0] == '!' && !node->x[1])
946 if (!node || !node->next_char)
949 m3 = node->next_char;
953 for(m4=m3->alt_char; m4; m4 = m4->alt_char) {
957 for(m4=m3; m4; m4 = m4->alt_char) {
958 e3 = trie_find_next_match(m3);
965 static void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid)
967 struct match_char *p; /* note minimal stack storage requirements */
970 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s\n", str, tree->x);
972 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL\n", str);
974 for (p=tree; p; p=p->alt_char) {
975 if (p->x[0] == 'N' && p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
976 if (p->exten && !(*(str+1))) /* if a shorter pattern matches along the way, might as well report it */
977 update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted, p);
979 if (p->next_char && ( *(str+1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0))) {
981 new_find_extension(str+1, score, p->next_char, length+1, spec+p->specificity, callerid);
983 new_find_extension("/", score, p->next_char, length+1, spec+p->specificity, callerid);
984 } else if (p->next_char && !*(str+1)) {
986 score->canmatch_exten = get_canmatch_exten(p);
990 } else if (p->x[0] == 'Z' && p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
991 if (p->exten && !(*(str+1))) /* if a shorter pattern matches along the way, might as well report it */
992 update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted,p);
994 if (p->next_char && ( *(str+1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0))) {
996 new_find_extension(str+1, score, p->next_char, length+1, spec+p->specificity, callerid);
998 new_find_extension("/", score, p->next_char, length+1, spec+p->specificity, callerid);
999 } else if (p->next_char && !*(str+1)) {
1000 score->canmatch = 1;
1001 score->canmatch_exten = get_canmatch_exten(p);
1005 } else if (p->x[0] == 'X' && p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
1006 if (p->exten && !(*(str+1))) /* if a shorter pattern matches along the way, might as well report it */
1007 update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted,p);
1009 if (p->next_char && ( *(str+1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0))) {
1011 new_find_extension(str+1, score, p->next_char, length+1, spec+p->specificity, callerid);
1013 new_find_extension("/", score, p->next_char, length+1, spec+p->specificity, callerid);
1014 } else if (p->next_char && !*(str+1)) {
1015 score->canmatch = 1;
1016 score->canmatch_exten = get_canmatch_exten(p);
1020 } else if (p->x[0] == '.' && p->x[1] == 0) {
1021 /* how many chars will the . match against? */
1023 const char *str2 = str;
1027 if (p->exten && !(*(str+1)))
1028 update_scoreboard(score, length+i, spec+(i*p->specificity), p->exten, '.', callerid, p->deleted, p);
1029 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
1030 new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid);
1033 } else if (p->x[0] == '!' && p->x[1] == 0) {
1034 /* how many chars will the . match against? */
1036 const char *str2 = str;
1040 if (p->exten && !(*(str+1)))
1041 update_scoreboard(score, length+1, spec+(p->specificity*i), p->exten, '!', callerid, p->deleted, p);
1042 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
1043 new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid);
1046 } else if (p->x[0] == '/' && p->x[1] == 0) {
1047 /* the pattern in the tree includes the cid match! */
1048 if (p->next_char && callerid && *callerid) {
1049 new_find_extension(callerid, score, p->next_char, length+1, spec, callerid);
1051 } else if (index(p->x, *str)) {
1052 if (p->exten && !(*(str+1))) /* if a shorter pattern matches along the way, might as well report it */
1053 update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted, p);
1056 if (p->next_char && ( *(str+1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0))) {
1058 new_find_extension(str+1, score, p->next_char, length+1, spec+p->specificity, callerid);
1060 new_find_extension("/", score, p->next_char, length+1, spec+p->specificity, callerid);
1062 } else if (p->next_char && !*(str+1)) {
1063 score->canmatch = 1;
1064 score->canmatch_exten = get_canmatch_exten(p);
1072 /* the algorithm for forming the extension pattern tree is also a bit simple; you
1073 * traverse all the extensions in a context, and for each char of the extension,
1074 * you see if it exists in the tree; if it doesn't, you add it at the appropriate
1075 * spot. What more can I say? At the end of the list, you cap it off by adding the
1076 * address of the extension involved. Duplicate patterns will be complained about.
1078 * Ideally, this would be done for each context after it is created and fully
1079 * filled. It could be done as a finishing step after extensions.conf or .ael is
1080 * loaded, or it could be done when the first search is encountered. It should only
1081 * have to be done once, until the next unload or reload.
1083 * I guess forming this pattern tree would be analogous to compiling a regex.
1086 static struct match_char *already_in_tree(struct match_char *current, char *pat)
1088 struct match_char *t;
1091 for (t=current; t; t=t->alt_char) {
1092 if (strcmp(pat,t->x) == 0) /* uh, we may want to sort exploded [] contents to make matching easy */
1098 static struct match_char *add_pattern_node(struct ast_context *con, struct match_char *current, char *pattern, int is_pattern, int already, int specificity)
1100 struct match_char *m = ast_calloc(1,sizeof(struct match_char));
1101 m->x = ast_strdup(pattern);
1102 m->is_pattern = is_pattern;
1103 if (specificity == 1 && is_pattern && pattern[0] == 'N')
1104 m->specificity = 98;
1105 else if (specificity == 1 && is_pattern && pattern[0] == 'Z')
1106 m->specificity = 99;
1107 else if (specificity == 1 && is_pattern && pattern[0] == 'X')
1108 m->specificity = 100;
1109 else if (specificity == 1 && is_pattern && pattern[0] == '.')
1110 m->specificity = 200;
1111 else if (specificity == 1 && is_pattern && pattern[0] == '!')
1112 m->specificity = 200;
1114 m->specificity = specificity;
1116 if (!con->pattern_tree) {
1117 con->pattern_tree = m;
1119 if (already) { /* switch to the new regime (traversing vs appending)*/
1120 m->alt_char = current->alt_char;
1121 current->alt_char = m;
1123 if (current->next_char) {
1124 m->alt_char = current->next_char->alt_char;
1125 current->next_char = m;
1127 current->next_char = m;
1134 static struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
1136 struct match_char *m1 = NULL, *m2 = NULL;
1142 char *s1 = extenbuf;
1143 int l1 = strlen(e1->exten) + strlen(e1->cidmatch) + 2;
1146 strncpy(extenbuf,e1->exten,sizeof(extenbuf));
1147 if (e1->matchcid && l1 <= sizeof(extenbuf)) {
1148 strcat(extenbuf,"/");
1149 strcat(extenbuf,e1->cidmatch);
1150 } else if (l1 > sizeof(extenbuf)) {
1151 ast_log(LOG_ERROR,"The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n", e1->exten, e1->cidmatch);
1155 ast_log(LOG_DEBUG,"Adding exten %s%c%s to tree\n", s1, e1->matchcid? '/':' ', e1->matchcid? e1->cidmatch : "");
1157 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
1165 if (pattern && *s1 == '[' && *(s1-1) != '\\') {
1168 s1++; /* get past the '[' */
1169 while (*s1 != ']' && *(s1-1) != '\\' ) {
1171 if (*(s1+1) == ']') {
1174 } else if (*(s1+1) == '\\') {
1177 } else if (*(s1+1) == '-') {
1180 } else if (*(s1+1) == '[') {
1184 } else if (*s1 == '-') { /* remember to add some error checking to all this! */
1187 for (s3++; s3 <= s4; s3++) {
1195 *s2 = 0; /* null terminate the exploded range */
1196 specif = strlen(buf);
1204 if (*s1 == 'n') /* make sure n,x,z patterns are canonicalized to N,X,Z */
1206 else if (*s1 == 'x')
1208 else if (*s1 == 'z')
1217 if (already && (m2=already_in_tree(m1,buf)) && m2->next_char) {
1218 if (!(*(s1+1))) { /* if this is the end of the pattern, but not the end of the tree, then mark this node with the exten...
1219 a shorter pattern might win if the longer one doesn't match */
1223 m1 = m2->next_char; /* m1 points to the node to compare against */
1232 m1 = add_pattern_node(con, m1, buf, pattern, already,specif); /* m1 is the node just added */
1242 s1++; /* advance to next char */
1247 static void create_match_char_tree(struct ast_context *con)
1249 struct ast_hashtab_iter *t1;
1250 struct ast_exten *e1;
1252 int biggest_bucket, resizes, numobjs, numbucks;
1254 ast_log(LOG_DEBUG,"Creating Extension Trie for context %s\n", con->name);
1255 ast_hashtab_get_stats(con->root_tree, &biggest_bucket, &resizes, &numobjs, &numbucks);
1256 ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
1257 numobjs, numbucks, biggest_bucket, resizes);
1259 t1 = ast_hashtab_start_traversal(con->root_tree);
1260 while( (e1 = ast_hashtab_next(t1)) ) {
1262 add_exten_to_pattern_tree(con, e1, 0);
1264 ast_log(LOG_ERROR,"Attempt to create extension with no extension name.\n");
1266 ast_hashtab_end_traversal(t1);
1269 static void destroy_pattern_tree(struct match_char *pattern_tree) /* pattern tree is a simple binary tree, sort of, so the proper way to destroy it is... recursively! */
1271 /* destroy all the alternates */
1272 if (pattern_tree->alt_char) {
1273 destroy_pattern_tree(pattern_tree->alt_char);
1274 pattern_tree->alt_char = 0;
1276 /* destroy all the nexts */
1277 if (pattern_tree->next_char) {
1278 destroy_pattern_tree(pattern_tree->next_char);
1279 pattern_tree->next_char = 0;
1281 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
1282 if (pattern_tree->x)
1283 free(pattern_tree->x);
1288 * Special characters used in patterns:
1289 * '_' underscore is the leading character of a pattern.
1290 * In other position it is treated as a regular char.
1291 * ' ' '-' space and '-' are separator and ignored.
1292 * . one or more of any character. Only allowed at the end of
1294 * ! zero or more of anything. Also impacts the result of CANMATCH
1295 * and MATCHMORE. Only allowed at the end of a pattern.
1296 * In the core routine, ! causes a match with a return code of 2.
1297 * In turn, depending on the search mode: (XXX check if it is implemented)
1298 * - E_MATCH retuns 1 (does match)
1299 * - E_MATCHMORE returns 0 (no match)
1300 * - E_CANMATCH returns 1 (does match)
1302 * / should not appear as it is considered the separator of the CID info.
1303 * XXX at the moment we may stop on this char.
1305 * X Z N match ranges 0-9, 1-9, 2-9 respectively.
1306 * [ denotes the start of a set of character. Everything inside
1307 * is considered literally. We can have ranges a-d and individual
1308 * characters. A '[' and '-' can be considered literally if they
1309 * are just before ']'.
1310 * XXX currently there is no way to specify ']' in a range, nor \ is
1311 * considered specially.
1313 * When we compare a pattern with a specific extension, all characters in the extension
1314 * itself are considered literally with the only exception of '-' which is considered
1315 * as a separator and thus ignored.
1316 * XXX do we want to consider space as a separator as well ?
1317 * XXX do we want to consider the separators in non-patterns as well ?
1321 * \brief helper functions to sort extensions and patterns in the desired way,
1322 * so that more specific patterns appear first.
1324 * ext_cmp1 compares individual characters (or sets of), returning
1325 * an int where bits 0-7 are the ASCII code of the first char in the set,
1326 * while bit 8-15 are the cardinality of the set minus 1.
1327 * This way more specific patterns (smaller cardinality) appear first.
1328 * Wildcards have a special value, so that we can directly compare them to
1329 * sets by subtracting the two values. In particular:
1330 * 0x000xx one character, xx
1331 * 0x0yyxx yy character set starting with xx
1332 * 0x10000 '.' (one or more of anything)
1333 * 0x20000 '!' (zero or more of anything)
1334 * 0x30000 NUL (end of string)
1335 * 0x40000 error in set.
1336 * The pointer to the string is advanced according to needs.
1338 * 1. the empty set is equivalent to NUL.
1339 * 2. given that a full set has always 0 as the first element,
1340 * we could encode the special cases as 0xffXX where XX
1341 * is 1, 2, 3, 4 as used above.
1343 static int ext_cmp1(const char **p)
1346 int c, cmin = 0xff, count = 0;
1349 /* load, sign extend and advance pointer until we find
1350 * a valid character.
1352 while ( (c = *(*p)++) && (c == ' ' || c == '-') )
1353 ; /* ignore some characters */
1355 /* always return unless we have a set of chars */
1357 default: /* ordinary character */
1358 return 0x0000 | (c & 0xff);
1360 case 'N': /* 2..9 */
1361 return 0x0700 | '2' ;
1363 case 'X': /* 0..9 */
1364 return 0x0900 | '0';
1366 case 'Z': /* 1..9 */
1367 return 0x0800 | '1';
1369 case '.': /* wildcard */
1372 case '!': /* earlymatch */
1373 return 0x20000; /* less specific than NULL */
1375 case '\0': /* empty string */
1379 case '[': /* pattern */
1382 /* locate end of set */
1383 end = strchr(*p, ']');
1386 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
1387 return 0x40000; /* XXX make this entry go last... */
1390 bzero(chars, sizeof(chars)); /* clear all chars in the set */
1391 for (; *p < end ; (*p)++) {
1392 unsigned char c1, c2; /* first-last char in range */
1393 c1 = (unsigned char)((*p)[0]);
1394 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
1395 c2 = (unsigned char)((*p)[2]);
1396 *p += 2; /* skip a total of 3 chars */
1397 } else /* individual character */
1401 for (; c1 <= c2; c1++) {
1402 uint32_t mask = 1 << (c1 % 32);
1403 if ( (chars[ c1 / 32 ] & mask) == 0)
1405 chars[ c1 / 32 ] |= mask;
1409 return count == 0 ? 0x30000 : (count | cmin);
1413 * \brief the full routine to compare extensions in rules.
1415 static int ext_cmp(const char *a, const char *b)
1417 /* make sure non-patterns come first.
1418 * If a is not a pattern, it either comes first or
1419 * we use strcmp to compare the strings.
1424 return (b[0] == '_') ? -1 : strcmp(a, b);
1426 /* Now we know a is a pattern; if b is not, a comes first */
1429 #if 0 /* old mode for ext matching */
1430 return strcmp(a, b);
1432 /* ok we need full pattern sorting routine */
1433 while (!ret && a && b)
1434 ret = ext_cmp1(&a) - ext_cmp1(&b);
1438 return (ret > 0) ? 1 : -1;
1441 int ast_extension_cmp(const char *a, const char *b)
1443 return ext_cmp(a, b);
1448 * \brief used ast_extension_{match|close}
1449 * mode is as follows:
1450 * E_MATCH success only on exact match
1451 * E_MATCHMORE success only on partial match (i.e. leftover digits in pattern)
1452 * E_CANMATCH either of the above.
1453 * \retval 0 on no-match
1454 * \retval 1 on match
1455 * \retval 2 on early match.
1458 static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
1460 mode &= E_MATCH_MASK; /* only consider the relevant bits */
1462 if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) /* note: if this test is left out, then _x. will not match _x. !!! */
1465 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
1466 int ld = strlen(data), lp = strlen(pattern);
1468 if (lp < ld) /* pattern too short, cannot match */
1470 /* depending on the mode, accept full or partial match or both */
1471 if (mode == E_MATCH)
1472 return !strcmp(pattern, data); /* 1 on match, 0 on fail */
1473 if (ld == 0 || !strncasecmp(pattern, data, ld)) /* partial or full match */
1474 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
1478 pattern++; /* skip leading _ */
1480 * XXX below we stop at '/' which is a separator for the CID info. However we should
1481 * not store '/' in the pattern at all. When we insure it, we can remove the checks.
1483 while (*data && *pattern && *pattern != '/') {
1486 if (*data == '-') { /* skip '-' in data (just a separator) */
1490 switch (toupper(*pattern)) {
1491 case '[': /* a range */
1492 end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */
1494 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
1495 return 0; /* unconditional failure */
1497 for (pattern++; pattern != end; pattern++) {
1498 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
1499 if (*data >= pattern[0] && *data <= pattern[2])
1500 break; /* match found */
1502 pattern += 2; /* skip a total of 3 chars */
1505 } else if (*data == pattern[0])
1506 break; /* match found */
1510 pattern = end; /* skip and continue */
1513 if (*data < '2' || *data > '9')
1517 if (*data < '0' || *data > '9')
1521 if (*data < '1' || *data > '9')
1524 case '.': /* Must match, even with more digits */
1526 case '!': /* Early match */
1529 case '-': /* Ignore these in patterns */
1530 data--; /* compensate the final data++ */
1533 if (*data != *pattern)
1539 if (*data) /* data longer than pattern, no match */
1542 * match so far, but ran off the end of the data.
1543 * Depending on what is next, determine match or not.
1545 if (*pattern == '\0' || *pattern == '/') /* exact match */
1546 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */
1547 else if (*pattern == '!') /* early match */
1549 else /* partial match */
1550 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */
1554 * Wrapper around _extension_match_core() to do performance measurement
1555 * using the profiling code.
1557 static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
1560 static int prof_id = -2; /* marker for 'unallocated' id */
1562 prof_id = ast_add_profile("ext_match", 0);
1563 ast_mark(prof_id, 1);
1564 i = _extension_match_core(pattern, data, mode);
1565 ast_mark(prof_id, 0);
1569 int ast_extension_match(const char *pattern, const char *data)
1571 return extension_match_core(pattern, data, E_MATCH);
1574 int ast_extension_close(const char *pattern, const char *data, int needmore)
1576 if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
1577 ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
1578 return extension_match_core(pattern, data, needmore);
1581 struct fake_context /* this struct is purely for matching in the hashtab */
1584 struct ast_exten *root;
1585 struct ast_hashtab *root_tree;
1586 struct match_char *pattern_tree;
1587 struct ast_context *next;
1588 struct ast_include *includes;
1589 struct ast_ignorepat *ignorepats;
1590 const char *registrar;
1591 AST_LIST_HEAD_NOLOCK(, ast_sw) alts;
1592 ast_mutex_t macrolock;
1596 struct ast_context *ast_context_find(const char *name)
1598 struct ast_context *tmp = NULL;
1599 struct fake_context item;
1600 strncpy(item.name,name,256);
1601 ast_rdlock_contexts();
1602 if( contexts_tree ) {
1603 tmp = ast_hashtab_lookup(contexts_tree,&item);
1605 while ( (tmp = ast_walk_contexts(tmp)) ) {
1606 if (!name || !strcasecmp(name, tmp->name))
1610 ast_unlock_contexts();
1614 #define STATUS_NO_CONTEXT 1
1615 #define STATUS_NO_EXTENSION 2
1616 #define STATUS_NO_PRIORITY 3
1617 #define STATUS_NO_LABEL 4
1618 #define STATUS_SUCCESS 5
1620 static int matchcid(const char *cidpattern, const char *callerid)
1622 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
1623 failing to get a number should count as a match, otherwise not */
1625 if (ast_strlen_zero(callerid))
1626 return ast_strlen_zero(cidpattern) ? 1 : 0;
1628 return ast_extension_match(cidpattern, callerid);
1631 struct ast_exten *pbx_find_extension(struct ast_channel *chan,
1632 struct ast_context *bypass, struct pbx_find_info *q,
1633 const char *context, const char *exten, int priority,
1634 const char *label, const char *callerid, enum ext_match_t action)
1637 struct ast_context *tmp = NULL;
1638 struct ast_exten *e = NULL, *eroot = NULL;
1639 struct ast_include *i = NULL;
1640 struct ast_sw *sw = NULL;
1641 struct ast_exten pattern = {NULL, };
1642 struct scoreboard score = {0, };
1644 pattern.label = label;
1645 pattern.priority = priority;
1647 ast_log(LOG_NOTICE,"Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int)action);
1649 /* Initialize status if appropriate */
1650 if (q->stacklen == 0) {
1651 q->status = STATUS_NO_CONTEXT;
1654 q->foundcontext = NULL;
1655 } else if (q->stacklen >= AST_PBX_MAX_STACK) {
1656 ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
1660 /* Check first to see if we've already been checked */
1661 for (x = 0; x < q->stacklen; x++) {
1662 if (!strcasecmp(q->incstack[x], context))
1666 if (bypass) /* bypass means we only look there */
1668 else { /* look in contexts */
1669 struct fake_context item;
1670 strncpy(item.name,context,256);
1671 tmp = ast_hashtab_lookup(contexts_tree,&item);
1674 while ((tmp = ast_walk_contexts(tmp)) ) {
1675 if (!strcmp(tmp->name, context))
1684 if (q->status < STATUS_NO_EXTENSION)
1685 q->status = STATUS_NO_EXTENSION;
1687 /* Do a search for matching extension */
1690 score.total_specificity = 0;
1692 score.total_length = 0;
1693 if (!tmp->pattern_tree && tmp->root_tree)
1695 create_match_char_tree(tmp);
1697 ast_log(LOG_DEBUG,"Tree Created in context %s:\n", context);
1698 log_match_char_tree(tmp->pattern_tree," ");
1702 ast_log(LOG_NOTICE,"The Trie we are searching in:\n");
1703 log_match_char_tree(tmp->pattern_tree, ":: ");
1706 if (extenpatternmatchnew) {
1707 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid);
1708 eroot = score.exten;
1710 if (score.last_char == '!' && action == E_MATCHMORE) {
1711 /* We match an extension ending in '!'.
1712 * The decision in this case is final and is NULL (no match).
1715 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
1720 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
1721 q->status = STATUS_SUCCESS;
1723 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
1725 return score.canmatch_exten;
1728 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) {
1730 struct ast_exten *z = trie_find_next_match(score.node);
1733 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
1735 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
1740 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
1742 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */
1746 /* found entry, now look for the right priority */
1747 if (q->status < STATUS_NO_PRIORITY)
1748 q->status = STATUS_NO_PRIORITY;
1750 if (action == E_FINDLABEL && label ) {
1751 if (q->status < STATUS_NO_LABEL)
1752 q->status = STATUS_NO_LABEL;
1753 e = ast_hashtab_lookup(eroot->peer_label_tree, &pattern);
1755 e = ast_hashtab_lookup(eroot->peer_tree, &pattern);
1757 if (e) { /* found a valid match */
1758 q->status = STATUS_SUCCESS;
1759 q->foundcontext = context;
1761 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
1768 /* scan the list trying to match extension and CID */
1770 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
1771 int match = extension_match_core(eroot->exten, exten, action);
1772 /* 0 on fail, 1 on match, 2 on earlymatch */
1774 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
1775 continue; /* keep trying */
1776 if (match == 2 && action == E_MATCHMORE) {
1777 /* We match an extension ending in '!'.
1778 * The decision in this case is final and is NULL (no match).
1782 /* found entry, now look for the right priority */
1783 if (q->status < STATUS_NO_PRIORITY)
1784 q->status = STATUS_NO_PRIORITY;
1786 if (action == E_FINDLABEL && label ) {
1787 if (q->status < STATUS_NO_LABEL)
1788 q->status = STATUS_NO_LABEL;
1789 e = ast_hashtab_lookup(eroot->peer_label_tree, &pattern);
1791 e = ast_hashtab_lookup(eroot->peer_tree, &pattern);
1794 while ( (e = ast_walk_extension_priorities(eroot, e)) ) {
1795 /* Match label or priority */
1796 if (action == E_FINDLABEL) {
1797 if (q->status < STATUS_NO_LABEL)
1798 q->status = STATUS_NO_LABEL;
1799 if (label && e->label && !strcmp(label, e->label))
1800 break; /* found it */
1801 } else if (e->priority == priority) {
1802 break; /* found it */
1803 } /* else keep searching */
1806 if (e) { /* found a valid match */
1807 q->status = STATUS_SUCCESS;
1808 q->foundcontext = context;
1815 /* Check alternative switches */
1816 AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
1817 struct ast_switch *asw = pbx_findswitch(sw->name);
1818 ast_switch_f *aswf = NULL;
1822 ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
1825 /* Substitute variables now */
1828 pbx_substitute_variables_helper(chan, sw->data, sw->tmpdata, SWITCH_DATA_LENGTH - 1);
1830 /* equivalent of extension_match_core() at the switch level */
1831 if (action == E_CANMATCH)
1832 aswf = asw->canmatch;
1833 else if (action == E_MATCHMORE)
1834 aswf = asw->matchmore;
1835 else /* action == E_MATCH */
1837 datap = sw->eval ? sw->tmpdata : sw->data;
1842 ast_autoservice_start(chan);
1843 res = aswf(chan, context, exten, priority, callerid, datap);
1845 ast_autoservice_stop(chan);
1847 if (res) { /* Got a match */
1850 q->foundcontext = context;
1851 /* XXX keep status = STATUS_NO_CONTEXT ? */
1855 q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */
1856 /* Now try any includes we have in this context */
1857 for (i = tmp->includes; i; i = i->next) {
1858 if (include_valid(i)) {
1859 if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
1861 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
1873 * \brief extract offset:length from variable name.
1874 * \return 1 if there is a offset:length part, which is
1875 * trimmed off (values go into variables)
1877 static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
1884 for (; *var; var++) {
1888 } else if (*var == ')') {
1890 } else if (*var == ':' && parens == 0) {
1892 sscanf(var, "%d:%d", offset, length);
1893 return 1; /* offset:length valid */
1900 *\brief takes a substring. It is ok to call with value == workspace.
1902 * \param offset < 0 means start from the end of the string and set the beginning
1903 * to be that many characters back.
1904 * \param length is the length of the substring, a value less than 0 means to leave
1905 * that many off the end.
1907 * \param workspace_len
1908 * Always return a copy in workspace.
1910 static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
1912 char *ret = workspace;
1913 int lr; /* length of the input string after the copy */
1915 ast_copy_string(workspace, value, workspace_len); /* always make a copy */
1917 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
1919 /* Quick check if no need to do anything */
1920 if (offset == 0 && length >= lr) /* take the whole string */
1923 if (offset < 0) { /* translate negative offset into positive ones */
1924 offset = lr + offset;
1925 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
1929 /* too large offset result in empty string so we know what to return */
1931 return ret + lr; /* the final '\0' */
1933 ret += offset; /* move to the start position */
1934 if (length >= 0 && length < lr - offset) /* truncate if necessary */
1936 else if (length < 0) {
1937 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
1938 ret[lr + length - offset] = '\0';
1946 /*! \brief Support for Asterisk built-in variables in the dialplan
1949 - \ref AstVar Channel variables
1950 - \ref AstCauses The HANGUPCAUSE variable
1952 void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
1954 const char not_found = '\0';
1956 const char *s; /* the result */
1958 int i, need_substring;
1959 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */
1962 ast_channel_lock(c);
1963 places[0] = &c->varshead;
1966 * Make a copy of var because parse_variable_name() modifies the string.
1967 * Then if called directly, we might need to run substring() on the result;
1968 * remember this for later in 'need_substring', 'offset' and 'length'
1970 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
1971 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
1974 * Look first into predefined variables, then into variable lists.
1975 * Variable 's' points to the result, according to the following rules:
1976 * s == ¬_found (set at the beginning) means that we did not find a
1977 * matching variable and need to look into more places.
1978 * If s != ¬_found, s is a valid result string as follows:
1979 * s = NULL if the variable does not have a value;
1980 * you typically do this when looking for an unset predefined variable.
1981 * s = workspace if the result has been assembled there;
1982 * typically done when the result is built e.g. with an snprintf(),
1983 * so we don't need to do an additional copy.
1984 * s != workspace in case we have a string, that needs to be copied
1985 * (the ast_copy_string is done once for all at the end).
1986 * Typically done when the result is already available in some string.
1988 s = ¬_found; /* default value */
1989 if (c) { /* This group requires a valid channel */
1990 /* Names with common parts are looked up a piece at a time using strncmp. */
1991 if (!strncmp(var, "CALL", 4)) {
1992 if (!strncmp(var + 4, "ING", 3)) {
1993 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */
1994 snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
1996 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */
1997 snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
1999 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */
2000 snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
2002 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */
2003 snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
2007 } else if (!strcmp(var, "HINT")) {
2008 s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL;
2009 } else if (!strcmp(var, "HINTNAME")) {
2010 s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL;
2011 } else if (!strcmp(var, "EXTEN")) {
2013 } else if (!strcmp(var, "CONTEXT")) {
2015 } else if (!strcmp(var, "PRIORITY")) {
2016 snprintf(workspace, workspacelen, "%d", c->priority);
2018 } else if (!strcmp(var, "CHANNEL")) {
2020 } else if (!strcmp(var, "UNIQUEID")) {
2022 } else if (!strcmp(var, "HANGUPCAUSE")) {
2023 snprintf(workspace, workspacelen, "%d", c->hangupcause);
2027 if (s == ¬_found) { /* look for more */
2028 if (!strcmp(var, "EPOCH")) {
2029 snprintf(workspace, workspacelen, "%u",(int)time(NULL));
2031 } else if (!strcmp(var, "SYSTEMNAME")) {
2032 s = ast_config_AST_SYSTEM_NAME;
2035 /* if not found, look into chanvars or global vars */
2036 for (i = 0; s == ¬_found && i < (sizeof(places) / sizeof(places[0])); i++) {
2037 struct ast_var_t *variables;
2040 if (places[i] == &globals)
2041 ast_rwlock_rdlock(&globalslock);
2042 AST_LIST_TRAVERSE(places[i], variables, entries) {
2043 if (!strcasecmp(ast_var_name(variables), var)) {
2044 s = ast_var_value(variables);
2048 if (places[i] == &globals)
2049 ast_rwlock_unlock(&globalslock);
2051 if (s == ¬_found || s == NULL)
2055 ast_copy_string(workspace, s, workspacelen);
2058 *ret = substring(*ret, offset, length, workspace, workspacelen);
2062 ast_channel_unlock(c);
2065 static void exception_store_free(void *data)
2067 struct pbx_exception *exception = data;
2068 ast_string_field_free_memory(exception);
2069 ast_free(exception);
2072 static struct ast_datastore_info exception_store_info = {
2073 .type = "EXCEPTION",
2074 .destroy = exception_store_free,
2077 int pbx_builtin_raise_exception(struct ast_channel *chan, void *vreason)
2079 const char *reason = vreason;
2080 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
2081 struct pbx_exception *exception = NULL;
2084 ds = ast_channel_datastore_alloc(&exception_store_info, NULL);
2087 exception = ast_calloc(1, sizeof(struct pbx_exception));
2089 ast_channel_datastore_free(ds);
2092 if (ast_string_field_init(exception, 128)) {
2093 ast_free(exception);
2094 ast_channel_datastore_free(ds);
2097 ds->data = exception;
2098 ast_channel_datastore_add(chan, ds);
2100 exception = ds->data;
2102 ast_string_field_set(exception, reason, reason);
2103 ast_string_field_set(exception, context, chan->context);
2104 ast_string_field_set(exception, exten, chan->exten);
2105 exception->priority = chan->priority;
2106 set_ext_pri(chan, "e", 0);
2110 static int acf_exception_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
2112 struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
2113 struct pbx_exception *exception = NULL;
2114 if (!ds || !ds->data)
2116 exception = ds->data;
2117 if (!strcasecmp(data, "REASON"))
2118 ast_copy_string(buf, exception->reason, buflen);
2119 else if (!strcasecmp(data, "CONTEXT"))
2120 ast_copy_string(buf, exception->context, buflen);
2121 else if (!strncasecmp(data, "EXTEN", 5))
2122 ast_copy_string(buf, exception->exten, buflen);
2123 else if (!strcasecmp(data, "PRIORITY"))
2124 snprintf(buf, buflen, "%d", exception->priority);
2130 static struct ast_custom_function exception_function = {
2131 .name = "EXCEPTION",
2132 .synopsis = "Retrieve the details of the current dialplan exception",
2134 "The following fields are available for retrieval:\n"
2135 " reason INVALID, ERROR, RESPONSETIMEOUT, ABSOLUTETIMEOUT, or custom\n"
2136 " value set by the RaiseException() application\n"
2137 " context The context executing when the exception occurred\n"
2138 " exten The extension executing when the exception occurred\n"
2139 " priority The numeric priority executing when the exception occurred\n",
2140 .syntax = "EXCEPTION(<field>)",
2141 .read = acf_exception_read,
2144 static char *handle_show_functions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2146 struct ast_custom_function *acf;
2152 e->command = "core show functions [like]";
2154 "Usage: core show functions [like <text>]\n"
2155 " List builtin functions, optionally only those matching a given string\n";
2161 if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
2163 } else if (a->argc != 3) {
2164 return CLI_SHOWUSAGE;
2167 ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
2169 AST_RWLIST_RDLOCK(&acf_root);
2170 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
2171 if (!like || strstr(acf->name, a->argv[4])) {
2173 ast_cli(a->fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis);
2176 AST_RWLIST_UNLOCK(&acf_root);
2178 ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
2183 static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2185 struct ast_custom_function *acf;
2186 /* Maximum number of characters added by terminal coloring is 22 */
2187 char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
2188 char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
2189 char stxtitle[40], *syntax = NULL;
2190 int synopsis_size, description_size, syntax_size;
2197 e->command = "core show function";
2199 "Usage: core show function <function>\n"
2200 " Describe a particular dialplan function.\n";
2203 wordlen = strlen(a->word);
2204 /* case-insensitive for convenience in this 'complete' function */
2205 AST_RWLIST_RDLOCK(&acf_root);
2206 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
2207 if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) {
2208 ret = ast_strdup(acf->name);
2212 AST_RWLIST_UNLOCK(&acf_root);
2218 return CLI_SHOWUSAGE;
2220 if (!(acf = ast_custom_function_find(a->argv[3]))) {
2221 ast_cli(a->fd, "No function by that name registered.\n");
2227 synopsis_size = strlen(acf->synopsis) + 23;
2229 synopsis_size = strlen("Not available") + 23;
2230 synopsis = alloca(synopsis_size);
2233 description_size = strlen(acf->desc) + 23;
2235 description_size = strlen("Not available") + 23;
2236 description = alloca(description_size);
2239 syntax_size = strlen(acf->syntax) + 23;
2241 syntax_size = strlen("Not available") + 23;
2242 syntax = alloca(syntax_size);
2244 snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name);
2245 term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
2246 term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
2247 term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
2248 term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
2250 acf->syntax ? acf->syntax : "Not available",
2251 COLOR_CYAN, 0, syntax_size);
2252 term_color(synopsis,
2253 acf->synopsis ? acf->synopsis : "Not available",
2254 COLOR_CYAN, 0, synopsis_size);
2255 term_color(description,
2256 acf->desc ? acf->desc : "Not available",
2257 COLOR_CYAN, 0, description_size);
2259 ast_cli(a->fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
2264 struct ast_custom_function *ast_custom_function_find(const char *name)
2266 struct ast_custom_function *acf = NULL;
2268 AST_RWLIST_RDLOCK(&acf_root);
2269 AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
2270 if (!strcmp(name, acf->name))
2273 AST_RWLIST_UNLOCK(&acf_root);
2278 int ast_custom_function_unregister(struct ast_custom_function *acf)
2280 struct ast_custom_function *cur;
2285 AST_RWLIST_WRLOCK(&acf_root);
2286 if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist)))
2287 ast_verb(2, "Unregistered custom function %s\n", cur->name);
2288 AST_RWLIST_UNLOCK(&acf_root);
2290 return cur ? 0 : -1;
2293 int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
2295 struct ast_custom_function *cur;
2303 AST_RWLIST_WRLOCK(&acf_root);
2305 AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
2306 if (!strcmp(acf->name, cur->name)) {
2307 ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
2308 AST_RWLIST_UNLOCK(&acf_root);
2313 /* Store in alphabetical order */
2314 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
2315 if (strcasecmp(acf->name, cur->name) < 0) {
2316 AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
2320 AST_RWLIST_TRAVERSE_SAFE_END;
2322 AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
2324 AST_RWLIST_UNLOCK(&acf_root);
2326 ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
2331 /*! \brief return a pointer to the arguments of the function,
2332 * and terminates the function name with '\\0'
2334 static char *func_args(char *function)
2336 char *args = strchr(function, '(');
2339 ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n");
2343 if ((p = strrchr(args, ')')) )
2346 ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
2351 int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
2353 char *copy = ast_strdupa(function);
2354 char *args = func_args(copy);
2355 struct ast_custom_function *acfptr = ast_custom_function_find(copy);
2358 ast_log(LOG_ERROR, "Function %s not registered\n", copy);
2359 else if (!acfptr->read)
2360 ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
2363 struct ast_module_user *u = NULL;
2365 u = __ast_module_user_add(acfptr->mod, chan);
2366 res = acfptr->read(chan, copy, args, workspace, len);
2367 if (acfptr->mod && u)
2368 __ast_module_user_remove(acfptr->mod, u);
2374 int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
2376 char *copy = ast_strdupa(function);
2377 char *args = func_args(copy);
2378 struct ast_custom_function *acfptr = ast_custom_function_find(copy);
2381 ast_log(LOG_ERROR, "Function %s not registered\n", copy);
2382 else if (!acfptr->write)
2383 ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
2386 struct ast_module_user *u = NULL;
2388 u = __ast_module_user_add(acfptr->mod, chan);
2389 res = acfptr->write(chan, copy, args, value);
2390 if (acfptr->mod && u)
2391 __ast_module_user_remove(acfptr->mod, u);
2398 static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
2400 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */
2402 const char *tmp, *whereweare;
2403 int length, offset, offset2, isfunction;
2404 char *workspace = NULL;
2405 char *ltmp = NULL, *var = NULL;
2406 char *nextvar, *nextexp, *nextthing;
2408 int pos, brackets, needsub, len;
2410 *cp2 = 0; /* just in case nothing ends up there */
2412 while (!ast_strlen_zero(whereweare) && count) {
2413 /* Assume we're copying the whole remaining string */
2414 pos = strlen(whereweare);
2417 nextthing = strchr(whereweare, '$');
2419 switch (nextthing[1]) {
2421 nextvar = nextthing;
2422 pos = nextvar - whereweare;
2425 nextexp = nextthing;
2426 pos = nextexp - whereweare;
2434 /* Can't copy more than 'count' bytes */
2438 /* Copy that many bytes */
2439 memcpy(cp2, whereweare, pos);
2448 /* We have a variable. Find the start and end, and determine
2449 if we are going to have to recursively call ourselves on the
2451 vars = vare = nextvar + 2;
2455 /* Find the end of it */
2456 while (brackets && *vare) {
2457 if ((vare[0] == '$') && (vare[1] == '{')) {
2459 } else if (vare[0] == '{') {
2461 } else if (vare[0] == '}') {
2463 } else if ((vare[0] == '$') && (vare[1] == '['))
2468 ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
2469 len = vare - vars - 1;
2471 /* Skip totally over variable string */
2472 whereweare += (len + 3);
2475 var = alloca(VAR_BUF_SIZE);
2477 /* Store variable name (and truncate) */
2478 ast_copy_string(var, vars, len + 1);
2480 /* Substitute if necessary */
2483 ltmp = alloca(VAR_BUF_SIZE);
2485 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
2492 workspace = alloca(VAR_BUF_SIZE);
2494 workspace[0] = '\0';
2496 parse_variable_name(vars, &offset, &offset2, &isfunction);
2498 /* Evaluate function */
2500 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
2502 struct varshead old;
2503 struct ast_channel *c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars);
2505 memcpy(&old, &c->varshead, sizeof(old));
2506 memcpy(&c->varshead, headp, sizeof(c->varshead));
2507 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
2508 /* Don't deallocate the varshead that was passed in */
2509 memcpy(&c->varshead, &old, sizeof(c->varshead));
2510 ast_channel_free(c);
2512 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n");
2514 ast_debug(1, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
2516 /* Retrieve variable value */
2517 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
2520 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
2522 length = strlen(cp4);
2525 memcpy(cp2, cp4, length);
2530 } else if (nextexp) {
2531 /* We have an expression. Find the start and end, and determine
2532 if we are going to have to recursively call ourselves on the
2534 vars = vare = nextexp + 2;
2538 /* Find the end of it */
2539 while (brackets && *vare) {
2540 if ((vare[0] == '$') && (vare[1] == '[')) {
2544 } else if (vare[0] == '[') {
2546 } else if (vare[0] == ']') {
2548 } else if ((vare[0] == '$') && (vare[1] == '{')) {
2555 ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
2556 len = vare - vars - 1;
2558 /* Skip totally over expression */
2559 whereweare += (len + 3);
2562 var = alloca(VAR_BUF_SIZE);
2564 /* Store variable name (and truncate) */
2565 ast_copy_string(var, vars, len + 1);
2567 /* Substitute if necessary */
2570 ltmp = alloca(VAR_BUF_SIZE);
2572 pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
2578 length = ast_expr(vars, cp2, count, c);
2581 ast_debug(1, "Expression result is '%s'\n", cp2);
2590 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
2592 pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
2595 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
2597 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
2600 static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
2604 /* Nothing more to do */
2608 /* No variables or expressions in e->data, so why scan it? */
2609 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
2610 ast_copy_string(passdata, e->data, datalen);
2614 pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
2618 * \brief The return value depends on the action:
2620 * E_MATCH, E_CANMATCH, E_MATCHMORE require a real match,
2621 * and return 0 on failure, -1 on match;
2622 * E_FINDLABEL maps the label to a priority, and returns
2623 * the priority on success, ... XXX
2624 * E_SPAWN, spawn an application,
2626 * \retval 0 on success.
2627 * \retval -1 on failure.
2629 * \note The channel is auto-serviced in this function, because doing an extension
2630 * match may block for a long time. For example, if the lookup has to use a network
2631 * dialplan switch, such as DUNDi or IAX2, it may take a while. However, the channel
2632 * auto-service code will queue up any important signalling frames to be processed
2633 * after this is done.
2635 static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
2636 const char *context, const char *exten, int priority,
2637 const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
2639 struct ast_exten *e;
2640 struct ast_app *app;
2642 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
2643 char passdata[EXT_DATA_SIZE];
2645 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
2647 ast_rdlock_contexts();
2651 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
2655 if (matching_action) {
2656 ast_unlock_contexts();
2657 return -1; /* success, we found it */
2658 } else if (action == E_FINDLABEL) { /* map the label to a priority */
2660 ast_unlock_contexts();
2661 return res; /* the priority we were looking for */
2662 } else { /* spawn */
2664 e->cached_app = pbx_findapp(e->app);
2665 app = e->cached_app;
2666 ast_unlock_contexts();
2668 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
2671 if (c->context != context)
2672 ast_copy_string(c->context, context, sizeof(c->context));
2673 if (c->exten != exten)
2674 ast_copy_string(c->exten, exten, sizeof(c->exten));
2675 c->priority = priority;
2676 pbx_substitute_variables(passdata, sizeof(passdata), c, e);
2677 #ifdef CHANNEL_TRACE
2678 ast_channel_trace_update(c);
2680 ast_debug(1, "Launching '%s'\n", app->name);
2681 if (VERBOSITY_ATLEAST(3)) {
2682 char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
2683 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
2684 exten, context, priority,
2685 term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
2686 term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
2687 term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
2690 manager_event(EVENT_FLAG_DIALPLAN, "Newexten",
2695 "Application: %s\r\n"
2698 c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
2699 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */
2701 } else if (q.swo) { /* not found here, but in another switch */
2702 ast_unlock_contexts();
2703 if (matching_action) {
2707 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
2710 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
2712 } else { /* not found anywhere, see what happened */
2713 ast_unlock_contexts();
2715 case STATUS_NO_CONTEXT:
2716 if (!matching_action && !combined_find_spawn)
2717 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
2719 case STATUS_NO_EXTENSION:
2720 if (!matching_action && !combined_find_spawn)
2721 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
2723 case STATUS_NO_PRIORITY:
2724 if (!matching_action && !combined_find_spawn)
2725 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
2727 case STATUS_NO_LABEL:
2728 if (context && !combined_find_spawn)
2729 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
2732 ast_debug(1, "Shouldn't happen!\n");
2735 return (matching_action) ? 0 : -1;
2739 /*! \brief Find hint for given extension in context */
2740 static struct ast_exten *ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
2742 struct ast_exten *e;
2743 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
2745 ast_rdlock_contexts();
2746 e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
2747 ast_unlock_contexts();
2752 /*! \brief Check state of extension by using hints */
2753 static int ast_extension_state2(struct ast_exten *e)
2755 char hint[AST_MAX_EXTENSION];
2757 int allunavailable = 1, allbusy = 1, allfree = 1, allonhold = 1;
2758 int busy = 0, inuse = 0, ring = 0;
2763 ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
2765 rest = hint; /* One or more devices separated with a & character */
2766 while ( (cur = strsep(&rest, "&")) ) {
2767 int res = ast_device_state(cur);
2769 case AST_DEVICE_NOT_INUSE:
2774 case AST_DEVICE_INUSE:
2780 case AST_DEVICE_RINGING:
2786 case AST_DEVICE_RINGINUSE:
2793 case AST_DEVICE_ONHOLD:
2797 case AST_DEVICE_BUSY:
2803 case AST_DEVICE_UNAVAILABLE:
2804 case AST_DEVICE_INVALID:
2818 return AST_EXTENSION_RINGING;
2820 return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
2822 return AST_EXTENSION_INUSE;
2824 return AST_EXTENSION_NOT_INUSE;
2826 return AST_EXTENSION_ONHOLD;
2828 return AST_EXTENSION_BUSY;
2830 return AST_EXTENSION_UNAVAILABLE;
2832 return AST_EXTENSION_INUSE;
2834 return AST_EXTENSION_NOT_INUSE;
2837 /*! \brief Return extension_state as string */
2838 const char *ast_extension_state2str(int extension_state)
2842 for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
2843 if (extension_states[i].extension_state == extension_state)
2844 return extension_states[i].text;
2849 /*! \brief Check extension state for an extension by using hint */
2850 int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
2852 struct ast_exten *e;
2854 e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */
2856 return -1; /* No hint, return -1 */
2858 return ast_extension_state2(e); /* Check all devices in the hint */
2861 static void handle_statechange(const char *device)
2863 struct ast_hint *hint;
2865 AST_RWLIST_RDLOCK(&hints);
2867 AST_RWLIST_TRAVERSE(&hints, hint, list) {
2868 struct ast_state_cb *cblist;
2869 char buf[AST_MAX_EXTENSION];
2874 ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
2875 while ( (cur = strsep(&parse, "&")) ) {
2876 if (!strcasecmp(cur, device))
2882 /* Get device state for this hint */
2883 state = ast_extension_state2(hint->exten);
2885 if ((state == -1) || (state == hint->laststate))
2888 /* Device state changed since last check - notify the watchers */
2890 /* For general callbacks */
2891 for (cblist = statecbs; cblist; cblist = cblist->next)
2892 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
2894 /* For extension callbacks */
2895 for (cblist = hint->callbacks; cblist; cblist = cblist->next)
2896 cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
2898 hint->laststate = state; /* record we saw the change */
2901 AST_RWLIST_UNLOCK(&hints);
2904 static int statechange_queue(const char *dev)
2906 struct statechange *sc;
2908 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(dev) + 1)))
2911 strcpy(sc->dev, dev);
2913 ast_mutex_lock(&device_state.lock);
2914 AST_LIST_INSERT_TAIL(&device_state.state_change_q, sc, entry);
2915 ast_cond_signal(&device_state.cond);
2916 ast_mutex_unlock(&device_state.lock);
2921 static void *device_state_thread(void *data)
2923 struct statechange *sc;
2925 while (!device_state.stop) {
2926 ast_mutex_lock(&device_state.lock);
2927 while (!(sc = AST_LIST_REMOVE_HEAD(&device_state.state_change_q, entry))) {
2928 ast_cond_wait(&device_state.cond, &device_state.lock);
2929 /* Check to see if we were woken up to see the request to stop */
2930 if (device_state.stop) {
2931 ast_mutex_unlock(&device_state.lock);
2935 ast_mutex_unlock(&device_state.lock);
2937 handle_statechange(sc->dev);
2945 /*! \brief Add watcher for extension states */
2946 int ast_extension_state_add(const char *context, const char *exten,
2947 ast_state_cb_type callback, void *data)
2949 struct ast_hint *hint;
2950 struct ast_state_cb *cblist;
2951 struct ast_exten *e;
2953 /* If there's no context and extension: add callback to statecbs list */
2954 if (!context && !exten) {
2955 AST_RWLIST_WRLOCK(&hints);
2957 for (cblist = statecbs; cblist; cblist = cblist->next) {
2958 if (cblist->callback == callback) {
2959 cblist->data = data;
2960 AST_RWLIST_UNLOCK(&hints);
2965 /* Now insert the callback */
2966 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
2967 AST_RWLIST_UNLOCK(&hints);
2971 cblist->callback = callback;
2972 cblist->data = data;
2974 cblist->next = statecbs;
2977 AST_RWLIST_UNLOCK(&hints);
2981 if (!context || !exten)
2984 /* This callback type is for only one hint, so get the hint */
2985 e = ast_hint_extension(NULL, context, exten);
2990 /* Find the hint in the list of hints */
2991 AST_RWLIST_WRLOCK(&hints);
2993 AST_RWLIST_TRAVERSE(&hints, hint, list) {
2994 if (hint->exten == e)
2999 /* We have no hint, sorry */
3000 AST_RWLIST_UNLOCK(&hints);
3004 /* Now insert the callback in the callback list */
3005 if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
3006 AST_RWLIST_UNLOCK(&hints);
3009 cblist->id = stateid++; /* Unique ID for this callback */
3010 cblist->callback = callback; /* Pointer to callback routine */
3011 cblist->data = data; /* Data for the callback */
3013 cblist->next = hint->callbacks;
3014 hint->callbacks = cblist;
3016 AST_RWLIST_UNLOCK(&hints);
3020 /*! \brief Remove a watcher from the callback list */
3021 int ast_extension_state_del(int id, ast_state_cb_type callback)
3023 struct ast_state_cb **p_cur = NULL; /* address of pointer to us */
3026 if (!id && !callback)
3029 AST_RWLIST_WRLOCK(&hints);
3031 if (!id) { /* id == 0 is a callback without extension */
3032 for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) {
3033 if ((*p_cur)->callback == callback)
3036 } else { /* callback with extension, find the callback based on ID */
3037 struct ast_hint *hint;
3038 AST_RWLIST_TRAVERSE(&hints, hint, list) {
3039 for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) {
3040 if ((*p_cur)->id == id)
3043 if (*p_cur) /* found in the inner loop */
3047 if (p_cur && *p_cur) {
3048 struct ast_state_cb *cur = *p_cur;
3053 AST_RWLIST_UNLOCK(&hints);
3057 /*! \brief Add hint to hint list, check initial extension state */
3058 static int ast_add_hint(struct ast_exten *e)
3060 struct ast_hint *hint;
3065 AST_RWLIST_WRLOCK(&hints);
3067 /* Search if hint exists, do nothing */
3068 AST_RWLIST_TRAVERSE(&hints, hint, list) {
3069 if (hint->exten == e) {
3070 AST_RWLIST_UNLOCK(&hints);
3071 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
3076 ast_debug(2, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
3078 if (!(hint = ast_calloc(1, sizeof(*hint)))) {
3079 AST_RWLIST_UNLOCK(&hints);
3082 /* Initialize and insert new item at the top */
3084 hint->laststate = ast_extension_state2(e);
3085 AST_RWLIST_INSERT_HEAD(&hints, hint, list);
3087 AST_RWLIST_UNLOCK(&hints);
3091 /*! \brief Change hint for an extension */
3092 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
3094 struct ast_hint *hint;
3097 AST_RWLIST_WRLOCK(&hints);
3098 AST_RWLIST_TRAVERSE(&hints, hint, list) {
3099 if (hint->exten == oe) {
3105 AST_RWLIST_UNLOCK(&hints);
3110 /*! \brief Remove hint from extension */
3111 static int ast_remove_hint(struct ast_exten *e)
3113 /* Cleanup the Notifys if hint is removed */
3114 struct ast_hint *hint;
3115 struct ast_state_cb *cblist, *cbprev;
3121 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
3122 if (hint->exten == e) {
3124 cblist = hint->callbacks;
3126 /* Notify with -1 and remove all callbacks */
3128 cblist = cblist->next;
3129 cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
3132 hint->callbacks = NULL;
3133 AST_RWLIST_REMOVE_CURRENT(list);
3139 AST_RWLIST_TRAVERSE_SAFE_END;
3145 /*! \brief Get hint for channel */
3146 int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
3148 struct ast_exten *e = ast_hint_extension(c, context, exten);
3152 ast_copy_string(hint, ast_get_extension_app(e), hintsize);
3154 const char *tmp = ast_get_extension_app_data(e);
3156 ast_copy_string(name, tmp, namesize);
3163 int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
3165 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
3168 int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
3170 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
3173 int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
3175 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
3178 int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
3180 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
3183 int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
3185 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
3188 int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
3190 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
3193 /*! helper function to set extension and priority */
3194 static void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
3196 ast_channel_lock(c);
3197 ast_copy_string(c->exten, exten, sizeof(c->exten));
3199 ast_channel_unlock(c);
3203 * \brief collect digits from the channel into the buffer.
3204 * \retval 0 on timeout or done.
3205 * \retval -1 on error.
3207 static int collect_digits(struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
3211 buf[pos] = '\0'; /* make sure it is properly terminated */
3212 while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) {
3213 /* As long as we're willing to wait, and as long as it's not defined,
3214 keep reading digits until we can't possibly get a right answer anymore. */
3215 digit = ast_waitfordigit(c, waittime * 1000);
3216 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
3219 if (!digit) /* No entry */
3221 if (digit < 0) /* Error, maybe a hangup */
3223 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
3227 waittime = c->pbx->dtimeout;
3233 static int __ast_pbx_run(struct ast_channel *c)
3235 int found = 0; /* set if we find at least one match */
3238 int error = 0; /* set an error conditions */
3240 /* A little initial setup here */
3242 ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
3243 /* XXX and now what ? */
3246 if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx))))
3250 c->cdr = ast_cdr_alloc();
3252 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
3256 ast_cdr_init(c->cdr, c);
3259 /* Set reasonable defaults */
3260 c->pbx->rtimeout = 10;
3261 c->pbx->dtimeout = 5;
3263 autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */
3264 ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
3266 /* Start by trying whatever the channel is set to */
3267 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
3268 /* If not successful fall back to 's' */
3269 ast_verb(2, "Starting %s at %s,%s,%d failed so falling back to exten 's'\n", c->name, c->context, c->exten, c->priority);
3270 /* XXX the original code used the existing priority in the call to
3271 * ast_exists_extension(), and reset it to 1 afterwards.
3272 * I believe the correct thing is to set it to 1 immediately.
3274 set_ext_pri(c, "s", 1);
3275 if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
3276 /* JK02: And finally back to default if everything else failed */
3277 ast_verb(2, "Starting %s at %s,%s,%d still failed so falling back to context 'default'\n", c->name, c->context, c->exten, c->priority);
3278 ast_copy_string(c->context, "default", sizeof(c->context));
3281 if (c->cdr && ast_tvzero(c->cdr->start))
3282 ast_cdr_start(c->cdr);
3284 char dst_exten[256]; /* buffer to accumulate digits */
3285 int pos = 0; /* XXX should check bounds */
3288 /* loop on priorities in this context/exten */
3289 while ( !(res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found,1))) {
3290 if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) {
3291 set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */
3292 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
3293 c->whentohangup = 0;
3294 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
3295 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
3296 pbx_builtin_raise_exception(c, "ABSOLUTETIMEOUT");
3297 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
3298 c->whentohangup = 0;
3299 c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
3300 } else if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
3303 } else if (ast_check_hangup(c)) {
3304 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
3305 c->exten, c->priority);
3310 } /* end while - from here on we can use 'break' to go out */
3312 /* Something bad happened, or a hangup has been requested. */
3313 if (strchr("0123456789ABCDEF*#", res)) {
3314 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
3316 dst_exten[pos++] = digit = res;
3317 dst_exten[pos] = '\0';
3318 } else if (res == AST_PBX_KEEPALIVE) {
3319 ast_debug(1, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
3320 ast_verb(2, "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
3323 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
3324 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
3326 if ((res == AST_PBX_ERROR) && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
3327 /* if we are already on the 'e' exten, don't jump to it again */
3328 if (!strcmp(c->exten, "e")) {
3329 ast_verb(2, "Spawn extension (%s, %s, %d) exited ERROR while already on 'e' exten on '%s'\n", c->context, c->exten, c->priority, c->name);
3332 pbx_builtin_raise_exception(c, "ERROR");
3337 if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
3340 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
3341 /* atimeout, nothing bad */
3354 * We get here on a failure of some kind: non-existing extension or
3355 * hangup. We have options, here. We can either catch the failure
3356 * and continue, or we can drop out entirely. */
3358 if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
3360 * If there is no match at priority 1, it is not a valid extension anymore.
3361 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
3364 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
3365 ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
3366 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
3367 set_ext_pri(c, "i", 1);
3368 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
3369 pbx_builtin_raise_exception(c, "INVALID");
3371 ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
3372 c->name, c->exten, c->context);
3373 error = 1; /* we know what to do with it */
3376 } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
3377 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
3379 } else { /* keypress received, get more digits for a full extension */
3382 waittime = c->pbx->dtimeout;
3383 else if (!autofallthrough)
3384 waittime = c->pbx->rtimeout;
3386 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
3389 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
3390 if (!strcasecmp(status, "CONGESTION"))
3391 res = pbx_builtin_congestion(c, "10");
3392 else if (!strcasecmp(status, "CHANUNAVAIL"))
3393 res = pbx_builtin_congestion(c, "10");
3394 else if (!strcasecmp(status, "BUSY"))
3395 res = pbx_builtin_busy(c, "10");
3396 error = 1; /* XXX disable message */
3397 break; /* exit from the 'for' loop */
3400 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
3402 if (ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */
3403 set_ext_pri(c, dst_exten, 1);
3405 /* No such extension */
3406 if (!ast_strlen_zero(dst_exten)) {
3407 /* An invalid extension */
3408 if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
3409 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name);
3410 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
3411 set_ext_pri(c, "i", 1);
3412 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
3413 pbx_builtin_raise_exception(c, "INVALID");
3415 ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context);
3416 found = 1; /* XXX disable message */
3420 /* A simple timeout */
3421 if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) {
3422 ast_verb(3, "Timeout on %s\n", c->name);
3423 set_ext_pri(c, "t", 1);
3424 } else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
3425 pbx_builtin_raise_exception(c, "RESPONSETIMEOUT");
3427 ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
3428 found = 1; /* XXX disable message */
3434 ast_verb(2, "CDR updated on %s\n",c->name);
3439 if (!found && !error)
3440 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
3441 if (res != AST_PBX_KEEPALIVE)
3442 ast_softhangup(c, c->hangupcause ? c->hangupcause : AST_CAUSE_NORMAL_CLEARING);
3443 if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) {
3444 if (c->cdr && ast_opt_end_cdr_before_h_exten)
3445 ast_cdr_end(c->cdr);
3446 set_ext_pri(c, "h", 1);
3447 while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found, 1)) == 0) {
3451 /* Something bad happened, or a hangup has been requested. */
3452 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
3453 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
3456 ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
3458 pbx_destroy(c->pbx);
3460 if (res != AST_PBX_KEEPALIVE)
3466 * \brief Increase call count for channel
3467 * \retval 0 on success
3468 * \retval non-zero if a configured limit (maxcalls, maxload, minmemfree) was reached
3470 static int increase_call_count(const struct ast_channel *c)
3474 #if defined(HAVE_SYSINFO)
3476 struct sysinfo sys_info;
3479 ast_mutex_lock(&maxcalllock);
3480 if (option_maxcalls) {
3481 if (countcalls >= option_maxcalls) {
3482 ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
3486 if (option_maxload) {
3487 getloadavg(&curloadavg, 1);
3488 if (curloadavg >= option_maxload) {
3489 ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
3493 #if defined(HAVE_SYSINFO)
3494 if (option_minmemfree) {
3495 if (!sysinfo(&sys_info)) {
3496 /* make sure that the free system memory is above the configured low watermark
3497 * convert the amount of freeram from mem_units to MB */
3498 curfreemem = sys_info.freeram / sys_info.mem_unit;
3499 curfreemem /= 1024*1024;
3500 if (curfreemem < option_minmemfree) {
3501 ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree);