Asterisk - The Open Source Telephony Project  18.5.0
pbx.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2008, Digium, Inc.
5  *
6  * Mark Spencer <[email protected]>
7  *
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.
13  *
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.
17  */
18 
19 /*! \file
20  *
21  * \brief Core PBX routines.
22  *
23  * \author Mark Spencer <[email protected]>
24  */
25 
26 /*** MODULEINFO
27  <support_level>core</support_level>
28  ***/
29 
30 #include "asterisk.h"
31 
32 #include "asterisk/_private.h"
33 #include "asterisk/paths.h" /* use ast_config_AST_SYSTEM_NAME */
34 #include <ctype.h>
35 #include <time.h>
36 #include <sys/time.h>
37 #if defined(HAVE_SYSINFO)
38 #include <sys/sysinfo.h>
39 #endif
40 #if defined(SOLARIS)
41 #include <sys/loadavg.h>
42 #endif
43 
44 #include "asterisk/lock.h"
45 #include "asterisk/cli.h"
46 #include "asterisk/pbx.h"
47 #include "asterisk/channel.h"
48 #include "asterisk/file.h"
49 #include "asterisk/callerid.h"
50 #include "asterisk/cdr.h"
51 #include "asterisk/config.h"
52 #include "asterisk/term.h"
53 #include "asterisk/time.h"
54 #include "asterisk/manager.h"
55 #include "asterisk/ast_expr.h"
56 #include "asterisk/linkedlists.h"
57 #define SAY_STUBS /* generate declarations and stubs for say methods */
58 #include "asterisk/say.h"
59 #include "asterisk/utils.h"
60 #include "asterisk/causes.h"
61 #include "asterisk/musiconhold.h"
62 #include "asterisk/app.h"
63 #include "asterisk/devicestate.h"
64 #include "asterisk/presencestate.h"
65 #include "asterisk/hashtab.h"
66 #include "asterisk/module.h"
67 #include "asterisk/indications.h"
68 #include "asterisk/taskprocessor.h"
69 #include "asterisk/xmldoc.h"
70 #include "asterisk/astobj2.h"
72 #include "asterisk/dial.h"
73 #include "asterisk/vector.h"
74 #include "pbx_private.h"
75 
76 /*!
77  * \note I M P O R T A N T :
78  *
79  * The speed of extension handling will likely be among the most important
80  * aspects of this PBX. The switching scheme as it exists right now isn't
81  * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
82  * of priorities, but a constant search time here would be great ;-)
83  *
84  * A new algorithm to do searching based on a 'compiled' pattern tree is introduced
85  * here, and shows a fairly flat (constant) search time, even for over
86  * 10000 patterns.
87  *
88  * Also, using a hash table for context/priority name lookup can help prevent
89  * the find_extension routines from absorbing exponential cpu cycles as the number
90  * of contexts/priorities grow. I've previously tested find_extension with red-black trees,
91  * which have O(log2(n)) speed. Right now, I'm using hash tables, which do
92  * searches (ideally) in O(1) time. While these techniques do not yield much
93  * speed in small dialplans, they are worth the trouble in large dialplans.
94  *
95  */
96 
97 /*** DOCUMENTATION
98  <function name="EXCEPTION" language="en_US">
99  <synopsis>
100  Retrieve the details of the current dialplan exception.
101  </synopsis>
102  <syntax>
103  <parameter name="field" required="true">
104  <para>The following fields are available for retrieval:</para>
105  <enumlist>
106  <enum name="reason">
107  <para>INVALID, ERROR, RESPONSETIMEOUT, ABSOLUTETIMEOUT, or custom
108  value set by the RaiseException() application</para>
109  </enum>
110  <enum name="context">
111  <para>The context executing when the exception occurred.</para>
112  </enum>
113  <enum name="exten">
114  <para>The extension executing when the exception occurred.</para>
115  </enum>
116  <enum name="priority">
117  <para>The numeric priority executing when the exception occurred.</para>
118  </enum>
119  </enumlist>
120  </parameter>
121  </syntax>
122  <description>
123  <para>Retrieve the details (specified <replaceable>field</replaceable>) of the current dialplan exception.</para>
124  </description>
125  <see-also>
126  <ref type="application">RaiseException</ref>
127  </see-also>
128  </function>
129  <function name="TESTTIME" language="en_US">
130  <synopsis>
131  Sets a time to be used with the channel to test logical conditions.
132  </synopsis>
133  <syntax>
134  <parameter name="date" required="true" argsep=" ">
135  <para>Date in ISO 8601 format</para>
136  </parameter>
137  <parameter name="time" required="true" argsep=" ">
138  <para>Time in HH:MM:SS format (24-hour time)</para>
139  </parameter>
140  <parameter name="zone" required="false">
141  <para>Timezone name</para>
142  </parameter>
143  </syntax>
144  <description>
145  <para>To test dialplan timing conditions at times other than the current time, use
146  this function to set an alternate date and time. For example, you may wish to evaluate
147  whether a location will correctly identify to callers that the area is closed on Christmas
148  Day, when Christmas would otherwise fall on a day when the office is normally open.</para>
149  </description>
150  <see-also>
151  <ref type="application">GotoIfTime</ref>
152  </see-also>
153  </function>
154  <manager name="ShowDialPlan" language="en_US">
155  <synopsis>
156  Show dialplan contexts and extensions
157  </synopsis>
158  <syntax>
159  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
160  <parameter name="Extension">
161  <para>Show a specific extension.</para>
162  </parameter>
163  <parameter name="Context">
164  <para>Show a specific context.</para>
165  </parameter>
166  </syntax>
167  <description>
168  <para>Show dialplan contexts and extensions. Be aware that showing the full dialplan
169  may take a lot of capacity.</para>
170  </description>
171  </manager>
172  <manager name="ExtensionStateList" language="en_US">
173  <synopsis>
174  List the current known extension states.
175  </synopsis>
176  <syntax>
177  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
178  </syntax>
179  <description>
180  <para>This will list out all known extension states in a
181  sequence of <replaceable>ExtensionStatus</replaceable> events.
182  When finished, a <replaceable>ExtensionStateListComplete</replaceable> event
183  will be emitted.</para>
184  </description>
185  <see-also>
186  <ref type="manager">ExtensionState</ref>
187  <ref type="function">HINT</ref>
188  <ref type="function">EXTENSION_STATE</ref>
189  </see-also>
190  <responses>
191  <list-elements>
192  <xi:include xpointer="xpointer(/docs/managerEvent[@name='ExtensionStatus'])" />
193  </list-elements>
194  <managerEvent name="ExtensionStateListComplete" language="en_US">
195  <managerEventInstance class="EVENT_FLAG_COMMAND">
196  <synopsis>
197  Indicates the end of the list the current known extension states.
198  </synopsis>
199  <syntax>
200  <parameter name="EventList">
201  <para>Conveys the status of the event list.</para>
202  </parameter>
203  <parameter name="ListItems">
204  <para>Conveys the number of statuses reported.</para>
205  </parameter>
206  </syntax>
207  </managerEventInstance>
208  </managerEvent>
209  </responses>
210  </manager>
211  ***/
212 
213 #ifdef LOW_MEMORY
214 #define EXT_DATA_SIZE 256
215 #else
216 #define EXT_DATA_SIZE 8192
217 #endif
218 
219 #define SWITCH_DATA_LENGTH 256
220 
221 #define VAR_NORMAL 1
222 #define VAR_SOFTTRAN 2
223 #define VAR_HARDTRAN 3
224 
225 struct ast_context;
226 struct ast_app;
227 
230 
231 /*!
232  \brief ast_exten: An extension
233  The dialplan is saved as a linked list with each context
234  having it's own linked list of extensions - one item per
235  priority.
236 */
237 struct ast_exten {
238  char *exten; /*!< Clean Extension id */
239  char *name; /*!< Extension name (may include '-' eye candy) */
240  int matchcid; /*!< Match caller id ? */
241  const char *cidmatch; /*!< Caller id to match for this extension */
242  const char *cidmatch_display; /*!< Caller id to match (display version) */
243  int priority; /*!< Priority */
244  const char *label; /*!< Label */
245  struct ast_context *parent; /*!< The context this extension belongs to */
246  const char *app; /*!< Application to execute */
247  struct ast_app *cached_app; /*!< Cached location of application */
248  void *data; /*!< Data to use (arguments) */
249  void (*datad)(void *); /*!< Data destructor */
250  struct ast_exten *peer; /*!< Next higher priority with our extension */
251  struct ast_hashtab *peer_table; /*!< Priorities list in hashtab form -- only on the head of the peer list */
252  struct ast_hashtab *peer_label_table; /*!< labeled priorities in the peers -- only on the head of the peer list */
253  const char *registrar; /*!< Registrar */
254  const char *registrar_file; /*!< File name used to register extension */
255  int registrar_line; /*!< Line number the extension was registered in text */
256  struct ast_exten *next; /*!< Extension with a greater ID */
257  char stuff[0];
258 };
259 
260 /*! \brief match_char: forms a syntax tree for quick matching of extension patterns */
262 {
263  int is_pattern; /* the pattern started with '_' */
264  int deleted; /* if this is set, then... don't return it */
265  int specificity; /* simply the strlen of x, or 10 for X, 9 for Z, and 8 for N; and '.' and '!' will add 11 ? */
268  struct ast_exten *exten; /* attached to last char of a pattern for exten */
269  char x[1]; /* the pattern itself-- matches a single char */
270 };
271 
272 struct scoreboard /* make sure all fields are 0 before calling new_find_extension */
273 {
276  char last_char; /* set to ! or . if they are the end of the pattern */
277  int canmatch; /* if the string to match was just too short */
278  struct match_char *node;
280  struct ast_exten *exten;
281 };
282 
283 /*! \brief ast_context: An extension context - must remain in sync with fake_context */
284 struct ast_context {
285  ast_rwlock_t lock; /*!< A lock to prevent multiple threads from clobbering the context */
286  struct ast_exten *root; /*!< The root of the list of extensions */
287  struct ast_hashtab *root_table; /*!< For exact matches on the extensions in the pattern tree, and for traversals of the pattern_tree */
288  struct match_char *pattern_tree; /*!< A tree to speed up extension pattern matching */
289  struct ast_context *next; /*!< Link them together */
290  struct ast_includes includes; /*!< Include other contexts */
291  struct ast_ignorepats ignorepats; /*!< Patterns for which to continue playing dialtone */
292  struct ast_sws alts; /*!< Alternative switches */
293  char *registrar; /*!< Registrar -- make sure you malloc this, as the registrar may have to survive module unloads */
294  int refcount; /*!< each module that would have created this context should inc/dec this as appropriate */
295  int autohints; /*!< Whether autohints support is enabled or not */
296  ast_mutex_t macrolock; /*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
297  char name[0]; /*!< Name of the context */
298 };
299 
300 /*! \brief ast_state_cb: An extension state notify register item */
301 struct ast_state_cb {
302  /*! Watcher ID returned when registered. */
303  int id;
304  /*! Arbitrary data passed for callbacks. */
305  void *data;
306  /*! Flag if this callback is an extended callback containing detailed device status */
307  int extended;
308  /*! Callback when state changes. */
310  /*! Callback when destroyed so any resources given by the registerer can be freed. */
312  /*! \note Only used by ast_merge_contexts_and_delete */
314 };
315 
316 /*!
317  * \brief Structure for dial plan hints
318  *
319  * \note Hints are pointers from an extension in the dialplan to
320  * one or more devices (tech/name)
321  *
322  * See \ref AstExtState
323  */
324 struct ast_hint {
325  /*!
326  * \brief Hint extension
327  *
328  * \note
329  * Will never be NULL while the hint is in the hints container.
330  */
331  struct ast_exten *exten;
332  struct ao2_container *callbacks; /*!< Device state callback container for this extension */
333 
334  /*! Dev state variables */
335  int laststate; /*!< Last known device state */
336 
337  /*! Presence state variables */
338  int last_presence_state; /*!< Last known presence state */
339  char *last_presence_subtype; /*!< Last known presence subtype string */
340  char *last_presence_message; /*!< Last known presence message string */
341 
342  char context_name[AST_MAX_CONTEXT];/*!< Context of destroyed hint extension. */
343  char exten_name[AST_MAX_EXTENSION];/*!< Extension of destroyed hint extension. */
344 
345  AST_VECTOR(, char *) devices; /*!< Devices associated with the hint */
346 };
347 
348 STASIS_MESSAGE_TYPE_DEFN_LOCAL(hint_change_message_type);
349 STASIS_MESSAGE_TYPE_DEFN_LOCAL(hint_remove_message_type);
350 
351 #define HINTDEVICE_DATA_LENGTH 16
353 
354 /* --- Hash tables of various objects --------*/
355 #ifdef LOW_MEMORY
356 #define HASH_EXTENHINT_SIZE 17
357 #else
358 #define HASH_EXTENHINT_SIZE 563
359 #endif
360 
361 
362 /*! \brief Container for hint devices */
363 static struct ao2_container *hintdevices;
364 
365 /*!
366  * \brief Structure for dial plan hint devices
367  * \note hintdevice is one device pointing to a hint.
368  */
370  /*!
371  * \brief Hint this hintdevice belongs to.
372  * \note Holds a reference to the hint object.
373  */
374  struct ast_hint *hint;
375  /*! Name of the hint device. */
376  char hintdevice[1];
377 };
378 
379 /*! \brief Container for autohint contexts */
380 static struct ao2_container *autohints;
381 
382 /*!
383  * \brief Structure for dial plan autohints
384  */
385 struct ast_autohint {
386  /*! \brief Name of the registrar */
387  char *registrar;
388  /*! \brief Name of the context */
389  char context[1];
390 };
391 
392 /*!
393  * \note Using the device for hash
394  */
395 static int hintdevice_hash_cb(const void *obj, const int flags)
396 {
397  const struct ast_hintdevice *ext;
398  const char *key;
399 
400  switch (flags & OBJ_SEARCH_MASK) {
401  case OBJ_SEARCH_KEY:
402  key = obj;
403  break;
404  case OBJ_SEARCH_OBJECT:
405  ext = obj;
406  key = ext->hintdevice;
407  break;
408  default:
409  ast_assert(0);
410  return 0;
411  }
412 
413  return ast_str_case_hash(key);
414 }
415 
416 /*!
417  * \note Devices on hints are not unique so no CMP_STOP is returned
418  * Dont use ao2_find against hintdevices container cause there always
419  * could be more than one result.
420  */
421 static int hintdevice_cmp_multiple(void *obj, void *arg, int flags)
422 {
423  struct ast_hintdevice *left = obj;
424  struct ast_hintdevice *right = arg;
425  const char *right_key = arg;
426  int cmp;
427 
428  switch (flags & OBJ_SEARCH_MASK) {
429  case OBJ_SEARCH_OBJECT:
430  right_key = right->hintdevice;
431  /* Fall through */
432  case OBJ_SEARCH_KEY:
433  cmp = strcasecmp(left->hintdevice, right_key);
434  break;
436  /*
437  * We could also use a partial key struct containing a length
438  * so strlen() does not get called for every comparison instead.
439  */
440  cmp = strncmp(left->hintdevice, right_key, strlen(right_key));
441  break;
442  default:
443  ast_assert(0);
444  cmp = 0;
445  break;
446  }
447  return cmp ? 0 : CMP_MATCH;
448 }
449 
450 /*!
451  * \note Using the context name for hash
452  */
453 static int autohint_hash_cb(const void *obj, const int flags)
454 {
455  const struct ast_autohint *autohint;
456  const char *key;
457 
458  switch (flags & OBJ_SEARCH_MASK) {
459  case OBJ_SEARCH_KEY:
460  key = obj;
461  break;
462  case OBJ_SEARCH_OBJECT:
463  autohint = obj;
464  key = autohint->context;
465  break;
466  default:
467  ast_assert(0);
468  return 0;
469  }
470 
471  return ast_str_case_hash(key);
472 }
473 
474 static int autohint_cmp(void *obj, void *arg, int flags)
475 {
476  struct ast_autohint *left = obj;
477  struct ast_autohint *right = arg;
478  const char *right_key = arg;
479  int cmp;
480 
481  switch (flags & OBJ_SEARCH_MASK) {
482  case OBJ_SEARCH_OBJECT:
483  right_key = right->context;
484  /* Fall through */
485  case OBJ_SEARCH_KEY:
486  cmp = strcasecmp(left->context, right_key);
487  break;
489  /*
490  * We could also use a partial key struct containing a length
491  * so strlen() does not get called for every comparison instead.
492  */
493  cmp = strncmp(left->context, right_key, strlen(right_key));
494  break;
495  default:
496  ast_assert(0);
497  cmp = 0;
498  break;
499  }
500  return cmp ? 0 : CMP_MATCH | CMP_STOP;
501 }
502 
503 /*! \internal \brief \c ao2_callback function to remove hintdevices */
504 static int hintdevice_remove_cb(void *obj, void *arg, void *data, int flags)
505 {
506  struct ast_hintdevice *candidate = obj;
507  char *device = arg;
508  struct ast_hint *hint = data;
509 
510  if (!strcasecmp(candidate->hintdevice, device)
511  && candidate->hint == hint) {
512  return CMP_MATCH;
513  }
514  return 0;
515 }
516 
517 static int remove_hintdevice(struct ast_hint *hint)
518 {
519  while (AST_VECTOR_SIZE(&hint->devices) > 0) {
520  char *device = AST_VECTOR_GET(&hint->devices, 0);
521 
523  hintdevice_remove_cb, device, hint, "Remove device from container");
524  AST_VECTOR_REMOVE_UNORDERED(&hint->devices, 0);
525  ast_free(device);
526  }
527 
528  return 0;
529 }
530 
531 static char *parse_hint_device(struct ast_str *hint_args);
532 /*!
533  * \internal
534  * \brief Destroy the given hintdevice object.
535  *
536  * \param obj Hint device to destroy.
537  *
538  * \return Nothing
539  */
540 static void hintdevice_destroy(void *obj)
541 {
542  struct ast_hintdevice *doomed = obj;
543 
544  if (doomed->hint) {
545  ao2_ref(doomed->hint, -1);
546  doomed->hint = NULL;
547  }
548 }
549 
550 /*! \brief add hintdevice structure and link it into the container.
551  */
552 static int add_hintdevice(struct ast_hint *hint, const char *devicelist)
553 {
554  struct ast_str *str;
555  char *parse;
556  char *cur;
557  struct ast_hintdevice *device;
558  int devicelength;
559 
560  if (!hint || !devicelist) {
561  /* Trying to add garbage? Don't bother. */
562  return 0;
563  }
564  if (!(str = ast_str_thread_get(&hintdevice_data, 16))) {
565  return -1;
566  }
567  ast_str_set(&str, 0, "%s", devicelist);
568  parse = ast_str_buffer(str);
569 
570  /* Spit on '&' and ',' to handle presence hints as well */
571  while ((cur = strsep(&parse, "&,"))) {
572  char *device_name;
573 
574  devicelength = strlen(cur);
575  if (!devicelength) {
576  continue;
577  }
578 
579  device_name = ast_strdup(cur);
580  if (!device_name) {
581  return -1;
582  }
583 
584  device = ao2_t_alloc(sizeof(*device) + devicelength, hintdevice_destroy,
585  "allocating a hintdevice structure");
586  if (!device) {
587  ast_free(device_name);
588  return -1;
589  }
590  strcpy(device->hintdevice, cur);
591  ao2_ref(hint, +1);
592  device->hint = hint;
593  if (AST_VECTOR_APPEND(&hint->devices, device_name)) {
594  ast_free(device_name);
595  ao2_ref(device, -1);
596  return -1;
597  }
598  ao2_t_link(hintdevices, device, "Linking device into hintdevice container.");
599  ao2_t_ref(device, -1, "hintdevice is linked so we can unref");
600  }
601 
602  return 0;
603 }
604 
605 
606 static const struct cfextension_states {
608  const char * const text;
609 } extension_states[] = {
610  { AST_EXTENSION_NOT_INUSE, "Idle" },
611  { AST_EXTENSION_INUSE, "InUse" },
612  { AST_EXTENSION_BUSY, "Busy" },
613  { AST_EXTENSION_UNAVAILABLE, "Unavailable" },
614  { AST_EXTENSION_RINGING, "Ringing" },
615  { AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" },
616  { AST_EXTENSION_ONHOLD, "Hold" },
617  { AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD, "InUse&Hold" }
618 };
619 
622  AST_STRING_FIELD(context); /*!< Context associated with this exception */
623  AST_STRING_FIELD(exten); /*!< Exten associated with this exception */
624  AST_STRING_FIELD(reason); /*!< The exception reason */
625  );
626 
627  int priority; /*!< Priority associated with this exception */
628 };
629 
630 static int matchcid(const char *cidpattern, const char *callerid);
631 #ifdef NEED_DEBUG
632 static void log_match_char_tree(struct match_char *node, char *prefix); /* for use anywhere */
633 #endif
634 static void new_find_extension(const char *str, struct scoreboard *score,
635  struct match_char *tree, int length, int spec, const char *callerid,
636  const char *label, enum ext_match_t action);
637 static struct match_char *already_in_tree(struct match_char *current, char *pat, int is_pattern);
638 static struct match_char *add_exten_to_pattern_tree(struct ast_context *con,
639  struct ast_exten *e1, int findonly);
640 static void create_match_char_tree(struct ast_context *con);
641 static struct ast_exten *get_canmatch_exten(struct match_char *node);
642 static void destroy_pattern_tree(struct match_char *pattern_tree);
643 static int hashtab_compare_extens(const void *ha_a, const void *ah_b);
644 static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b);
645 static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b);
646 static unsigned int hashtab_hash_extens(const void *obj);
647 static unsigned int hashtab_hash_priority(const void *obj);
648 static unsigned int hashtab_hash_labels(const void *obj);
649 static void __ast_internal_context_destroy( struct ast_context *con);
650 static int ast_add_extension_nolock(const char *context, int replace, const char *extension,
651  int priority, const char *label, const char *callerid,
652  const char *application, void *data, void (*datad)(void *), const char *registrar);
653 static int ast_add_extension2_lockopt(struct ast_context *con,
654  int replace, const char *extension, int priority, const char *label, const char *callerid,
655  const char *application, void *data, void (*datad)(void *),
656  const char *registrar, const char *registrar_file, int registrar_line,
657  int lock_context);
658 static struct ast_context *find_context_locked(const char *context);
659 static struct ast_context *find_context(const char *context);
661 static unsigned int ext_strncpy(char *dst, const char *src, size_t dst_size, int nofluff);
662 
663 /*!
664  * \internal
665  * \brief Character array comparison function for qsort.
666  *
667  * \param a Left side object.
668  * \param b Right side object.
669  *
670  * \retval <0 if a < b
671  * \retval =0 if a = b
672  * \retval >0 if a > b
673  */
674 static int compare_char(const void *a, const void *b)
675 {
676  const unsigned char *ac = a;
677  const unsigned char *bc = b;
678 
679  return *ac - *bc;
680 }
681 
682 /* labels, contexts are case sensitive priority numbers are ints */
683 int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
684 {
685  const struct ast_context *ac = ah_a;
686  const struct ast_context *bc = ah_b;
687  if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
688  return 1;
689  /* assume context names are registered in a string table! */
690  return strcmp(ac->name, bc->name);
691 }
692 
693 static int hashtab_compare_extens(const void *ah_a, const void *ah_b)
694 {
695  const struct ast_exten *ac = ah_a;
696  const struct ast_exten *bc = ah_b;
697  int x = strcmp(ac->exten, bc->exten);
698  if (x) { /* if exten names are diff, then return */
699  return x;
700  }
701 
702  /* but if they are the same, do the cidmatch values match? */
703  /* not sure which side may be using ast_ext_matchcid_types, so check both */
705  return 0;
706  }
708  return 0;
709  }
710  if (ac->matchcid != bc->matchcid) {
711  return 1;
712  }
713  /* all other cases already disposed of, match now required on callerid string (cidmatch) */
714  /* although ast_add_extension2_lockopt() enforces non-zero ptr, caller may not have */
716  return 0;
717  }
718  return strcmp(ac->cidmatch, bc->cidmatch);
719 }
720 
721 static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b)
722 {
723  const struct ast_exten *ac = ah_a;
724  const struct ast_exten *bc = ah_b;
725  return ac->priority != bc->priority;
726 }
727 
728 static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b)
729 {
730  const struct ast_exten *ac = ah_a;
731  const struct ast_exten *bc = ah_b;
732  return strcmp(S_OR(ac->label, ""), S_OR(bc->label, ""));
733 }
734 
735 unsigned int ast_hashtab_hash_contexts(const void *obj)
736 {
737  const struct ast_context *ac = obj;
738  return ast_hashtab_hash_string(ac->name);
739 }
740 
741 static unsigned int hashtab_hash_extens(const void *obj)
742 {
743  const struct ast_exten *ac = obj;
744  unsigned int x = ast_hashtab_hash_string(ac->exten);
745  unsigned int y = 0;
746  if (ac->matchcid == AST_EXT_MATCHCID_ON)
748  return x+y;
749 }
750 
751 static unsigned int hashtab_hash_priority(const void *obj)
752 {
753  const struct ast_exten *ac = obj;
754  return ast_hashtab_hash_int(ac->priority);
755 }
756 
757 static unsigned int hashtab_hash_labels(const void *obj)
758 {
759  const struct ast_exten *ac = obj;
760  return ast_hashtab_hash_string(S_OR(ac->label, ""));
761 }
762 
763 static int autofallthrough = 1;
764 static int extenpatternmatchnew = 0;
765 static char *overrideswitch = NULL;
766 
767 /*! \brief Subscription for device state change events */
769 /*! \brief Subscription for presence state change events */
771 
773 static int countcalls;
774 static int totalcalls;
775 
776 static struct ast_context *contexts;
777 static struct ast_hashtab *contexts_table = NULL;
778 
779 /*!
780  * \brief Lock for the ast_context list
781  * \note
782  * This lock MUST be recursive, or a deadlock on reload may result. See
783  * https://issues.asterisk.org/view.php?id=17643
784  */
786 
787 /*!
788  * \brief Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
789  */
791 
792 static int stateid = 1;
793 /*!
794  * \note When holding this container's lock, do _not_ do
795  * anything that will cause conlock to be taken, unless you
796  * _already_ hold it. The ast_merge_contexts_and_delete function
797  * will take the locks in conlock/hints order, so any other
798  * paths that require both locks must also take them in that
799  * order.
800  */
801 static struct ao2_container *hints;
802 
803 static struct ao2_container *statecbs;
804 
805 #ifdef CONTEXT_DEBUG
806 
807 /* these routines are provided for doing run-time checks
808  on the extension structures, in case you are having
809  problems, this routine might help you localize where
810  the problem is occurring. It's kinda like a debug memory
811  allocator's arena checker... It'll eat up your cpu cycles!
812  but you'll see, if you call it in the right places,
813  right where your problems began...
814 */
815 
816 /* you can break on the check_contexts_trouble()
817 routine in your debugger to stop at the moment
818 there's a problem */
819 void check_contexts_trouble(void);
820 
821 void check_contexts_trouble(void)
822 {
823  int x = 1;
824  x = 2;
825 }
826 
827 int check_contexts(char *, int);
828 
829 int check_contexts(char *file, int line )
830 {
831  struct ast_hashtab_iter *t1;
832  struct ast_context *c1, *c2;
833  int found = 0;
834  struct ast_exten *e1, *e2, *e3;
835  struct ast_exten ex;
836 
837  /* try to find inconsistencies */
838  /* is every context in the context table in the context list and vice-versa ? */
839 
840  if (!contexts_table) {
841  ast_log(LOG_NOTICE,"Called from: %s:%d: No contexts_table!\n", file, line);
842  usleep(500000);
843  }
844 
845  t1 = ast_hashtab_start_traversal(contexts_table);
846  while( (c1 = ast_hashtab_next(t1))) {
847  for(c2=contexts;c2;c2=c2->next) {
848  if (!strcmp(c1->name, c2->name)) {
849  found = 1;
850  break;
851  }
852  }
853  if (!found) {
854  ast_log(LOG_NOTICE,"Called from: %s:%d: Could not find the %s context in the linked list\n", file, line, c1->name);
855  check_contexts_trouble();
856  }
857  }
859  for(c2=contexts;c2;c2=c2->next) {
860  c1 = find_context_locked(c2->name);
861  if (!c1) {
862  ast_log(LOG_NOTICE,"Called from: %s:%d: Could not find the %s context in the hashtab\n", file, line, c2->name);
863  check_contexts_trouble();
864  } else
866  }
867 
868  /* loop thru all contexts, and verify the exten structure compares to the
869  hashtab structure */
870  for(c2=contexts;c2;c2=c2->next) {
871  c1 = find_context_locked(c2->name);
872  if (c1) {
874 
875  /* is every entry in the root list also in the root_table? */
876  for(e1 = c1->root; e1; e1=e1->next)
877  {
878  char dummy_name[1024];
879  ex.exten = dummy_name;
880  ex.matchcid = e1->matchcid;
881  ex.cidmatch = e1->cidmatch;
882  ast_copy_string(dummy_name, e1->exten, sizeof(dummy_name));
883  e2 = ast_hashtab_lookup(c1->root_table, &ex);
884  if (!e2) {
885  if (e1->matchcid == AST_EXT_MATCHCID_ON) {
886  ast_log(LOG_NOTICE, "Called from: %s:%d: The %s context records "
887  "the exten %s (CID match: %s) but it is not in its root_table\n",
888  file, line, c2->name, dummy_name, e1->cidmatch_display);
889  } else {
890  ast_log(LOG_NOTICE, "Called from: %s:%d: The %s context records "
891  "the exten %s but it is not in its root_table\n",
892  file, line, c2->name, dummy_name);
893  }
894  check_contexts_trouble();
895  }
896  }
897 
898  /* is every entry in the root_table also in the root list? */
899  if (!c2->root_table) {
900  if (c2->root) {
901  ast_log(LOG_NOTICE,"Called from: %s:%d: No c2->root_table for context %s!\n", file, line, c2->name);
902  usleep(500000);
903  }
904  } else {
906  while( (e2 = ast_hashtab_next(t1)) ) {
907  for(e1=c2->root;e1;e1=e1->next) {
908  if (!strcmp(e1->exten, e2->exten)) {
909  found = 1;
910  break;
911  }
912  }
913  if (!found) {
914  ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context records the exten %s but it is not in its root_table\n", file, line, c2->name, e2->exten);
915  check_contexts_trouble();
916  }
917 
918  }
920  }
921  }
922  /* is every priority reflected in the peer_table at the head of the list? */
923 
924  /* is every entry in the root list also in the root_table? */
925  /* are the per-extension peer_tables in the right place? */
926 
927  for(e1 = c2->root; e1; e1 = e1->next) {
928 
929  for(e2=e1;e2;e2=e2->peer) {
930  ex.priority = e2->priority;
931  if (e2 != e1 && e2->peer_table) {
932  ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority has a peer_table entry, and shouldn't!\n", file, line, c2->name, e1->exten, e2->priority );
933  check_contexts_trouble();
934  }
935 
936  if (e2 != e1 && e2->peer_label_table) {
937  ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority has a peer_label_table entry, and shouldn't!\n", file, line, c2->name, e1->exten, e2->priority );
938  check_contexts_trouble();
939  }
940 
941  if (e2 == e1 && !e2->peer_table){
942  ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority doesn't have a peer_table!\n", file, line, c2->name, e1->exten, e2->priority );
943  check_contexts_trouble();
944  }
945 
946  if (e2 == e1 && !e2->peer_label_table) {
947  ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority doesn't have a peer_label_table!\n", file, line, c2->name, e1->exten, e2->priority );
948  check_contexts_trouble();
949  }
950 
951 
952  e3 = ast_hashtab_lookup(e1->peer_table, &ex);
953  if (!e3) {
954  ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority is not reflected in the peer_table\n", file, line, c2->name, e1->exten, e2->priority );
955  check_contexts_trouble();
956  }
957  }
958 
959  if (!e1->peer_table){
960  ast_log(LOG_NOTICE,"Called from: %s:%d: No e1->peer_table!\n", file, line);
961  usleep(500000);
962  }
963 
964  /* is every entry in the peer_table also in the peer list? */
966  while( (e2 = ast_hashtab_next(t1)) ) {
967  for(e3=e1;e3;e3=e3->peer) {
968  if (e3->priority == e2->priority) {
969  found = 1;
970  break;
971  }
972  }
973  if (!found) {
974  ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority is not reflected in the peer list\n", file, line, c2->name, e1->exten, e2->priority );
975  check_contexts_trouble();
976  }
977  }
979  }
980  }
981  return 0;
982 }
983 #endif
984 
985 static void pbx_destroy(struct ast_pbx *p)
986 {
987  ast_free(p);
988 }
989 
990 /* form a tree that fully describes all the patterns in a context's extensions
991  * in this tree, a "node" represents an individual character or character set
992  * meant to match the corresponding character in a dial string. The tree
993  * consists of a series of match_char structs linked in a chain
994  * via the alt_char pointers. More than one pattern can share the same parts of the
995  * tree as other extensions with the same pattern to that point.
996  * My first attempt to duplicate the finding of the 'best' pattern was flawed in that
997  * I misunderstood the general algorithm. I thought that the 'best' pattern
998  * was the one with lowest total score. This was not true. Thus, if you have
999  * patterns "1XXXXX" and "X11111", you would be tempted to say that "X11111" is
1000  * the "best" match because it has fewer X's, and is therefore more specific,
1001  * but this is not how the old algorithm works. It sorts matching patterns
1002  * in a similar collating sequence as sorting alphabetic strings, from left to
1003  * right. Thus, "1XXXXX" comes before "X11111", and would be the "better" match,
1004  * because "1" is more specific than "X".
1005  * So, to accomodate this philosophy, I sort the tree branches along the alt_char
1006  * line so they are lowest to highest in specificity numbers. This way, as soon
1007  * as we encounter our first complete match, we automatically have the "best"
1008  * match and can stop the traversal immediately. Same for CANMATCH/MATCHMORE.
1009  * If anyone would like to resurrect the "wrong" pattern trie searching algorithm,
1010  * they are welcome to revert pbx to before 1 Apr 2008.
1011  * As an example, consider these 4 extensions:
1012  * (a) NXXNXXXXXX
1013  * (b) 307754XXXX
1014  * (c) fax
1015  * (d) NXXXXXXXXX
1016  *
1017  * In the above, between (a) and (d), (a) is a more specific pattern than (d), and would win over
1018  * most numbers. For all numbers beginning with 307754, (b) should always win.
1019  *
1020  * These pattern should form a (sorted) tree that looks like this:
1021  * { "3" } --next--> { "0" } --next--> { "7" } --next--> { "7" } --next--> { "5" } ... blah ... --> { "X" exten_match: (b) }
1022  * |
1023  * |alt
1024  * |
1025  * { "f" } --next--> { "a" } --next--> { "x" exten_match: (c) }
1026  * { "N" } --next--> { "X" } --next--> { "X" } --next--> { "N" } --next--> { "X" } ... blah ... --> { "X" exten_match: (a) }
1027  * | |
1028  * | |alt
1029  * |alt |
1030  * | { "X" } --next--> { "X" } ... blah ... --> { "X" exten_match: (d) }
1031  * |
1032  * NULL
1033  *
1034  * In the above, I could easily turn "N" into "23456789", but I think that a quick "if( *z >= '2' && *z <= '9' )" might take
1035  * fewer CPU cycles than a call to strchr("23456789",*z), where *z is the char to match...
1036  *
1037  * traversal is pretty simple: one routine merely traverses the alt list, and for each matching char in the pattern, it calls itself
1038  * on the corresponding next pointer, incrementing also the pointer of the string to be matched, and passing the total specificity and length.
1039  * We pass a pointer to a scoreboard down through, also.
1040  * The scoreboard isn't as necessary to the revised algorithm, but I kept it as a handy way to return the matched extension.
1041  * The first complete match ends the traversal, which should make this version of the pattern matcher faster
1042  * the previous. The same goes for "CANMATCH" or "MATCHMORE"; the first such match ends the traversal. In both
1043  * these cases, the reason we can stop immediately, is because the first pattern match found will be the "best"
1044  * according to the sort criteria.
1045  * Hope the limit on stack depth won't be a problem... this routine should
1046  * be pretty lean as far a stack usage goes. Any non-match terminates the recursion down a branch.
1047  *
1048  * In the above example, with the number "3077549999" as the pattern, the traversor could match extensions a, b and d. All are
1049  * of length 10; they have total specificities of 24580, 10246, and 25090, respectively, not that this matters
1050  * at all. (b) wins purely because the first character "3" is much more specific (lower specificity) than "N". I have
1051  * left the specificity totals in the code as an artifact; at some point, I will strip it out.
1052  *
1053  * Just how much time this algorithm might save over a plain linear traversal over all possible patterns is unknown,
1054  * because it's a function of how many extensions are stored in a context. With thousands of extensions, the speedup
1055  * can be very noticeable. The new matching algorithm can run several hundreds of times faster, if not a thousand or
1056  * more times faster in extreme cases.
1057  *
1058  * MatchCID patterns are also supported, and stored in the tree just as the extension pattern is. Thus, you
1059  * can have patterns in your CID field as well.
1060  *
1061  * */
1062 
1063 
1064 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)
1065 {
1066  /* if this extension is marked as deleted, then skip this -- if it never shows
1067  on the scoreboard, it will never be found, nor will halt the traversal. */
1068  if (deleted)
1069  return;
1070  board->total_specificity = spec;
1071  board->total_length = length;
1072  board->exten = exten;
1073  board->last_char = last;
1074  board->node = node;
1075 #ifdef NEED_DEBUG_HERE
1076  ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec);
1077 #endif
1078 }
1079 
1080 #ifdef NEED_DEBUG
1081 static void log_match_char_tree(struct match_char *node, char *prefix)
1082 {
1083  char extenstr[40];
1084  struct ast_str *my_prefix = ast_str_alloca(1024);
1085 
1086  extenstr[0] = '\0';
1087 
1088  if (node && node->exten)
1089  snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
1090 
1091  if (strlen(node->x) > 1) {
1092  ast_debug(1, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N',
1093  node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"",
1094  node->exten ? node->exten->exten : "", extenstr);
1095  } else {
1096  ast_debug(1, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N',
1097  node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"",
1098  node->exten ? node->exten->exten : "", extenstr);
1099  }
1100 
1101  ast_str_set(&my_prefix, 0, "%s+ ", prefix);
1102 
1103  if (node->next_char)
1104  log_match_char_tree(node->next_char, ast_str_buffer(my_prefix));
1105 
1106  if (node->alt_char)
1107  log_match_char_tree(node->alt_char, prefix);
1108 }
1109 #endif
1110 
1111 static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
1112 {
1113  char extenstr[40];
1114  struct ast_str *my_prefix = ast_str_alloca(1024);
1115 
1116  extenstr[0] = '\0';
1117 
1118  if (node->exten) {
1119  snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
1120  }
1121 
1122  if (strlen(node->x) > 1) {
1123  ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
1124  node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
1125  node->exten ? node->exten->name : "", extenstr);
1126  } else {
1127  ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
1128  node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
1129  node->exten ? node->exten->name : "", extenstr);
1130  }
1131 
1132  ast_str_set(&my_prefix, 0, "%s+ ", prefix);
1133 
1134  if (node->next_char)
1135  cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd);
1136 
1137  if (node->alt_char)
1138  cli_match_char_tree(node->alt_char, prefix, fd);
1139 }
1140 
1141 static struct ast_exten *get_canmatch_exten(struct match_char *node)
1142 {
1143  /* find the exten at the end of the rope */
1144  struct match_char *node2 = node;
1145 
1146  for (node2 = node; node2; node2 = node2->next_char) {
1147  if (node2->exten) {
1148 #ifdef NEED_DEBUG_HERE
1149  ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten);
1150 #endif
1151  return node2->exten;
1152  }
1153  }
1154 #ifdef NEED_DEBUG_HERE
1155  ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x);
1156 #endif
1157  return 0;
1158 }
1159 
1160 static struct ast_exten *trie_find_next_match(struct match_char *node)
1161 {
1162  struct match_char *m3;
1163  struct match_char *m4;
1164  struct ast_exten *e3;
1165 
1166  if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */
1167  return node->exten;
1168  }
1169 
1170  if (node && node->x[0] == '!' && !node->x[1]) {
1171  return node->exten;
1172  }
1173 
1174  if (!node || !node->next_char) {
1175  return NULL;
1176  }
1177 
1178  m3 = node->next_char;
1179 
1180  if (m3->exten) {
1181  return m3->exten;
1182  }
1183  for (m4 = m3->alt_char; m4; m4 = m4->alt_char) {
1184  if (m4->exten) {
1185  return m4->exten;
1186  }
1187  }
1188  for (m4 = m3; m4; m4 = m4->alt_char) {
1189  e3 = trie_find_next_match(m3);
1190  if (e3) {
1191  return e3;
1192  }
1193  }
1194 
1195  return NULL;
1196 }
1197 
1198 #ifdef DEBUG_THIS
1199 static char *action2str(enum ext_match_t action)
1200 {
1201  switch (action) {
1202  case E_MATCH:
1203  return "MATCH";
1204  case E_CANMATCH:
1205  return "CANMATCH";
1206  case E_MATCHMORE:
1207  return "MATCHMORE";
1208  case E_FINDLABEL:
1209  return "FINDLABEL";
1210  case E_SPAWN:
1211  return "SPAWN";
1212  default:
1213  return "?ACTION?";
1214  }
1215 }
1216 
1217 #endif
1218 
1219 static const char *candidate_exten_advance(const char *str)
1220 {
1221  str++;
1222  while (*str == '-') {
1223  str++;
1224  }
1225  return str;
1226 }
1227 
1228 #define MORE(s) (*candidate_exten_advance(s))
1229 #define ADVANCE(s) candidate_exten_advance(s)
1230 
1231 static void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action)
1232 {
1233  struct match_char *p; /* note minimal stack storage requirements */
1234  struct ast_exten pattern = { .label = label };
1235 #ifdef DEBUG_THIS
1236  if (tree)
1237  ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action));
1238  else
1239  ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action));
1240 #endif
1241  for (p = tree; p; p = p->alt_char) {
1242  if (p->is_pattern) {
1243  if (p->x[0] == 'N') {
1244  if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
1245 #define NEW_MATCHER_CHK_MATCH \
1246  if (p->exten && !MORE(str)) { /* if a shorter pattern matches along the way, might as well report it */ \
1247  if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \
1248  update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \
1249  if (!p->deleted) { \
1250  if (action == E_FINDLABEL) { \
1251  if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \
1252  ast_debug(4, "Found label in preferred extension\n"); \
1253  return; \
1254  } \
1255  } else { \
1256  ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->name); \
1257  return; /* the first match, by definition, will be the best, because of the sorted tree */ \
1258  } \
1259  } \
1260  } \
1261  }
1262 
1263 #define NEW_MATCHER_RECURSE \
1264  if (p->next_char && (MORE(str) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \
1265  || p->next_char->x[0] == '!')) { \
1266  if (MORE(str) || p->next_char->x[0] == '!') { \
1267  new_find_extension(ADVANCE(str), score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
1268  if (score->exten) { \
1269  ast_debug(4 ,"returning an exact match-- %s\n", score->exten->name); \
1270  return; /* the first match is all we need */ \
1271  } \
1272  } else { \
1273  new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
1274  if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \
1275  ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->name : \
1276  "NULL"); \
1277  return; /* the first match is all we need */ \
1278  } \
1279  } \
1280  } else if ((p->next_char || action == E_CANMATCH) && !MORE(str)) { \
1281  score->canmatch = 1; \
1282  score->canmatch_exten = get_canmatch_exten(p); \
1283  if (action == E_CANMATCH || action == E_MATCHMORE) { \
1284  ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \
1285  return; \
1286  } \
1287  }
1288 
1291  }
1292  } else if (p->x[0] == 'Z') {
1293  if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
1296  }
1297  } else if (p->x[0] == 'X') {
1298  if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
1301  }
1302  } else if (p->x[0] == '.' && p->x[1] == 0) {
1303  /* how many chars will the . match against? */
1304  int i = 0;
1305  const char *str2 = str;
1306  while (*str2 && *str2 != '/') {
1307  str2++;
1308  i++;
1309  }
1310  if (p->exten && *str2 != '/') {
1311  update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p);
1312  if (score->exten) {
1313  ast_debug(4, "return because scoreboard has a match with '/'--- %s\n",
1314  score->exten->name);
1315  return; /* the first match is all we need */
1316  }
1317  }
1318  if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
1319  new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action);
1320  if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
1321  ast_debug(4, "return because scoreboard has exact match OR "
1322  "CANMATCH/MATCHMORE & canmatch set--- %s\n",
1323  score->exten ? score->exten->name : "NULL");
1324  return; /* the first match is all we need */
1325  }
1326  }
1327  } else if (p->x[0] == '!' && p->x[1] == 0) {
1328  /* how many chars will the . match against? */
1329  int i = 1;
1330  const char *str2 = str;
1331  while (*str2 && *str2 != '/') {
1332  str2++;
1333  i++;
1334  }
1335  if (p->exten && *str2 != '/') {
1336  update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p);
1337  if (score->exten) {
1338  ast_debug(4, "return because scoreboard has a '!' match--- %s\n",
1339  score->exten->name);
1340  return; /* the first match is all we need */
1341  }
1342  }
1343  if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
1344  new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action);
1345  if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
1346  ast_debug(4, "return because scoreboard has exact match OR "
1347  "CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n",
1348  score->exten ? score->exten->name : "NULL");
1349  return; /* the first match is all we need */
1350  }
1351  }
1352  } else if (p->x[0] == '/' && p->x[1] == 0) {
1353  /* the pattern in the tree includes the cid match! */
1354  if (p->next_char && callerid && *callerid) {
1355  new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action);
1356  if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
1357  ast_debug(4, "return because scoreboard has exact match OR "
1358  "CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n",
1359  score->exten ? score->exten->name : "NULL");
1360  return; /* the first match is all we need */
1361  }
1362  }
1363  } else if (strchr(p->x, *str)) {
1364  ast_debug(4, "Nothing strange about this match\n");
1367  }
1368  } else if (strchr(p->x, *str)) {
1369  ast_debug(4, "Nothing strange about this match\n");
1372  }
1373  }
1374  ast_debug(4, "return at end of func\n");
1375 }
1376 
1377 #undef MORE
1378 #undef ADVANCE
1379 
1380 /* the algorithm for forming the extension pattern tree is also a bit simple; you
1381  * traverse all the extensions in a context, and for each char of the extension,
1382  * you see if it exists in the tree; if it doesn't, you add it at the appropriate
1383  * spot. What more can I say? At the end of each exten, you cap it off by adding the
1384  * address of the extension involved. Duplicate patterns will be complained about.
1385  *
1386  * Ideally, this would be done for each context after it is created and fully
1387  * filled. It could be done as a finishing step after extensions.conf or .ael is
1388  * loaded, or it could be done when the first search is encountered. It should only
1389  * have to be done once, until the next unload or reload.
1390  *
1391  * I guess forming this pattern tree would be analogous to compiling a regex. Except
1392  * that a regex only handles 1 pattern, really. This trie holds any number
1393  * of patterns. Well, really, it **could** be considered a single pattern,
1394  * where the "|" (or) operator is allowed, I guess, in a way, sort of...
1395  */
1396 
1397 static struct match_char *already_in_tree(struct match_char *current, char *pat, int is_pattern)
1398 {
1399  struct match_char *t;
1400 
1401  if (!current) {
1402  return 0;
1403  }
1404 
1405  for (t = current; t; t = t->alt_char) {
1406  if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */
1407  return t;
1408  }
1409  }
1410 
1411  return 0;
1412 }
1413 
1414 /* The first arg is the location of the tree ptr, or the
1415  address of the next_char ptr in the node, so we can mess
1416  with it, if we need to insert at the beginning of the list */
1417 
1418 static void insert_in_next_chars_alt_char_list(struct match_char **parent_ptr, struct match_char *node)
1419 {
1420  struct match_char *curr, *lcurr;
1421 
1422  /* insert node into the tree at "current", so the alt_char list from current is
1423  sorted in increasing value as you go to the leaves */
1424  if (!(*parent_ptr)) {
1425  *parent_ptr = node;
1426  return;
1427  }
1428 
1429  if ((*parent_ptr)->specificity > node->specificity) {
1430  /* insert at head */
1431  node->alt_char = (*parent_ptr);
1432  *parent_ptr = node;
1433  return;
1434  }
1435 
1436  lcurr = *parent_ptr;
1437  for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
1438  if (curr->specificity > node->specificity) {
1439  node->alt_char = curr;
1440  lcurr->alt_char = node;
1441  break;
1442  }
1443  lcurr = curr;
1444  }
1445 
1446  if (!curr) {
1447  lcurr->alt_char = node;
1448  }
1449 
1450 }
1451 
1453  /*! Pattern node specificity */
1454  int specif;
1455  /*! Pattern node match characters. */
1456  char buf[256];
1457 };
1458 
1459 static struct match_char *add_pattern_node(struct ast_context *con, struct match_char *current, const struct pattern_node *pattern, int is_pattern, int already, struct match_char **nextcharptr)
1460 {
1461  struct match_char *m;
1462 
1463  if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) {
1464  return NULL;
1465  }
1466 
1467  /* strcpy is safe here since we know its size and have allocated
1468  * just enough space for when we allocated m
1469  */
1470  strcpy(m->x, pattern->buf);
1471 
1472  /* the specificity scores are the same as used in the old
1473  pattern matcher. */
1474  m->is_pattern = is_pattern;
1475  if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') {
1476  m->specificity = 0x0832;
1477  } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') {
1478  m->specificity = 0x0931;
1479  } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') {
1480  m->specificity = 0x0a30;
1481  } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') {
1482  m->specificity = 0x18000;
1483  } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') {
1484  m->specificity = 0x28000;
1485  } else {
1486  m->specificity = pattern->specif;
1487  }
1488 
1489  if (!con->pattern_tree) {
1491  } else {
1492  if (already) { /* switch to the new regime (traversing vs appending)*/
1493  insert_in_next_chars_alt_char_list(nextcharptr, m);
1494  } else {
1496  }
1497  }
1498 
1499  return m;
1500 }
1501 
1502 /*!
1503  * \internal
1504  * \brief Extract the next exten pattern node.
1505  *
1506  * \param node Pattern node to fill.
1507  * \param src Next source character to read.
1508  * \param pattern TRUE if the exten is a pattern.
1509  * \param extenbuf Original exten buffer to use in diagnostic messages.
1510  *
1511  * \retval Ptr to next extenbuf pos to read.
1512  */
1513 static const char *get_pattern_node(struct pattern_node *node, const char *src, int pattern, const char *extenbuf)
1514 {
1515 #define INC_DST_OVERFLOW_CHECK \
1516  do { \
1517  if (dst - node->buf < sizeof(node->buf) - 1) { \
1518  ++dst; \
1519  } else { \
1520  overflow = 1; \
1521  } \
1522  } while (0)
1523 
1524  node->specif = 0;
1525  node->buf[0] = '\0';
1526  while (*src) {
1527  if (*src == '[' && pattern) {
1528  char *dst = node->buf;
1529  const char *src_next;
1530  int length;
1531  int overflow = 0;
1532 
1533  /* get past the '[' */
1534  ++src;
1535  for (;;) {
1536  if (*src == '\\') {
1537  /* Escaped character. */
1538  ++src;
1539  if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') {
1540  *dst = *src++;
1542  }
1543  } else if (*src == '-') {
1544  unsigned char first;
1545  unsigned char last;
1546 
1547  src_next = src;
1548  first = *(src_next - 1);
1549  last = *++src_next;
1550 
1551  if (last == '\\') {
1552  /* Escaped character. */
1553  last = *++src_next;
1554  }
1555 
1556  /* Possible char range. */
1557  if (node->buf[0] && last) {
1558  /* Expand the char range. */
1559  while (++first <= last) {
1560  *dst = first;
1562  }
1563  src = src_next + 1;
1564  } else {
1565  /*
1566  * There was no left or right char for the range.
1567  * It is just a '-'.
1568  */
1569  *dst = *src++;
1571  }
1572  } else if (*src == '\0') {
1574  "A matching ']' was not found for '[' in exten pattern '%s'\n",
1575  extenbuf);
1576  break;
1577  } else if (*src == ']') {
1578  ++src;
1579  break;
1580  } else {
1581  *dst = *src++;
1583  }
1584  }
1585  /* null terminate the exploded range */
1586  *dst = '\0';
1587 
1588  if (overflow) {
1590  "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n",
1591  extenbuf);
1592  node->buf[0] = '\0';
1593  continue;
1594  }
1595 
1596  /* Sort the characters in character set. */
1597  length = strlen(node->buf);
1598  if (!length) {
1599  ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n",
1600  extenbuf);
1601  node->buf[0] = '\0';
1602  continue;
1603  }
1604  qsort(node->buf, length, 1, compare_char);
1605 
1606  /* Remove duplicate characters from character set. */
1607  dst = node->buf;
1608  src_next = node->buf;
1609  while (*src_next++) {
1610  if (*dst != *src_next) {
1611  *++dst = *src_next;
1612  }
1613  }
1614 
1615  length = strlen(node->buf);
1616  length <<= 8;
1617  node->specif = length | (unsigned char) node->buf[0];
1618  break;
1619  } else if (*src == '-') {
1620  /* Skip dashes in all extensions. */
1621  ++src;
1622  } else {
1623  if (*src == '\\') {
1624  /*
1625  * XXX The escape character here does not remove any special
1626  * meaning to characters except the '[', '\\', and '-'
1627  * characters since they are special only in this function.
1628  */
1629  node->buf[0] = *++src;
1630  if (!node->buf[0]) {
1631  break;
1632  }
1633  } else {
1634  node->buf[0] = *src;
1635  if (pattern) {
1636  /* make sure n,x,z patterns are canonicalized to N,X,Z */
1637  if (node->buf[0] == 'n') {
1638  node->buf[0] = 'N';
1639  } else if (node->buf[0] == 'x') {
1640  node->buf[0] = 'X';
1641  } else if (node->buf[0] == 'z') {
1642  node->buf[0] = 'Z';
1643  }
1644  }
1645  }
1646  node->buf[1] = '\0';
1647  node->specif = 1;
1648  ++src;
1649  break;
1650  }
1651  }
1652  return src;
1653 
1654 #undef INC_DST_OVERFLOW_CHECK
1655 }
1656 
1657 static struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
1658 {
1659  struct match_char *m1 = NULL;
1660  struct match_char *m2 = NULL;
1661  struct match_char **m0;
1662  const char *pos;
1663  int already;
1664  int pattern = 0;
1665  int idx_cur;
1666  int idx_next;
1667  char extenbuf[512];
1668  struct pattern_node pat_node[2];
1669 
1670  if (e1->matchcid) {
1671  if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) {
1673  "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n",
1674  e1->exten, e1->cidmatch);
1675  return NULL;
1676  }
1677  sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe. We just checked. */
1678  } else {
1679  ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf));
1680  }
1681 
1682 #ifdef NEED_DEBUG
1683  ast_debug(1, "Adding exten %s to tree\n", extenbuf);
1684 #endif
1685  m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
1686  m0 = &con->pattern_tree;
1687  already = 1;
1688 
1689  pos = extenbuf;
1690  if (*pos == '_') {
1691  pattern = 1;
1692  ++pos;
1693  }
1694  idx_cur = 0;
1695  pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf);
1696  for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) {
1697  idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node);
1698  pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf);
1699 
1700  /* See about adding node to tree. */
1701  m2 = NULL;
1702  if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern))
1703  && m2->next_char) {
1704  if (!pat_node[idx_next].buf[0]) {
1705  /*
1706  * This is the end of the pattern, but not the end of the tree.
1707  * Mark this node with the exten... a shorter pattern might win
1708  * if the longer one doesn't match.
1709  */
1710  if (findonly) {
1711  return m2;
1712  }
1713  if (m2->exten) {
1714  ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
1715  m2->deleted ? "(deleted/invalid)" : m2->exten->name, e1->name);
1716  }
1717  m2->exten = e1;
1718  m2->deleted = 0;
1719  }
1720  m1 = m2->next_char; /* m1 points to the node to compare against */
1721  m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */
1722  } else { /* not already OR not m2 OR nor m2->next_char */
1723  if (m2) {
1724  if (findonly) {
1725  return m2;
1726  }
1727  m1 = m2; /* while m0 stays the same */
1728  } else {
1729  if (findonly) {
1730  return m1;
1731  }
1732  m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0);
1733  if (!m1) { /* m1 is the node just added */
1734  return NULL;
1735  }
1736  m0 = &m1->next_char;
1737  }
1738  if (!pat_node[idx_next].buf[0]) {
1739  if (m2 && m2->exten) {
1740  ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
1741  m2->deleted ? "(deleted/invalid)" : m2->exten->name, e1->name);
1742  }
1743  m1->deleted = 0;
1744  m1->exten = e1;
1745  }
1746 
1747  /* The 'already' variable is a mini-optimization designed to make it so that we
1748  * don't have to call already_in_tree when we know it will return false.
1749  */
1750  already = 0;
1751  }
1752  }
1753  return m1;
1754 }
1755 
1756 static void create_match_char_tree(struct ast_context *con)
1757 {
1758  struct ast_hashtab_iter *t1;
1759  struct ast_exten *e1;
1760 #ifdef NEED_DEBUG
1761  int biggest_bucket, resizes, numobjs, numbucks;
1762 
1763  ast_debug(1, "Creating Extension Trie for context %s(%p)\n", con->name, con);
1764  ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
1765  ast_debug(1, "This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
1766  numobjs, numbucks, biggest_bucket, resizes);
1767 #endif
1769  while ((e1 = ast_hashtab_next(t1))) {
1770  if (e1->exten) {
1771  add_exten_to_pattern_tree(con, e1, 0);
1772  } else {
1773  ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n");
1774  }
1775  }
1777 }
1778 
1779 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! */
1780 {
1781  /* destroy all the alternates */
1782  if (pattern_tree->alt_char) {
1783  destroy_pattern_tree(pattern_tree->alt_char);
1784  pattern_tree->alt_char = 0;
1785  }
1786  /* destroy all the nexts */
1787  if (pattern_tree->next_char) {
1788  destroy_pattern_tree(pattern_tree->next_char);
1789  pattern_tree->next_char = 0;
1790  }
1791  pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
1792  ast_free(pattern_tree);
1793 }
1794 
1795 /*!
1796  * \internal
1797  * \brief Get the length of the exten string.
1798  *
1799  * \param str Exten to get length.
1800  *
1801  * \retval strlen of exten.
1802  */
1803 static int ext_cmp_exten_strlen(const char *str)
1804 {
1805  int len;
1806 
1807  len = 0;
1808  for (;;) {
1809  /* Ignore '-' chars as eye candy fluff. */
1810  while (*str == '-') {
1811  ++str;
1812  }
1813  if (!*str) {
1814  break;
1815  }
1816  ++str;
1817  ++len;
1818  }
1819  return len;
1820 }
1821 
1822 /*!
1823  * \internal
1824  * \brief Partial comparison of non-pattern extens.
1825  *
1826  * \param left Exten to compare.
1827  * \param right Exten to compare. Also matches if this string ends first.
1828  *
1829  * \retval <0 if left < right
1830  * \retval =0 if left == right
1831  * \retval >0 if left > right
1832  */
1833 static int ext_cmp_exten_partial(const char *left, const char *right)
1834 {
1835  int cmp;
1836 
1837  for (;;) {
1838  /* Ignore '-' chars as eye candy fluff. */
1839  while (*left == '-') {
1840  ++left;
1841  }
1842  while (*right == '-') {
1843  ++right;
1844  }
1845 
1846  if (!*right) {
1847  /*
1848  * Right ended first for partial match or both ended at the same
1849  * time for a match.
1850  */
1851  cmp = 0;
1852  break;
1853  }
1854 
1855  cmp = *left - *right;
1856  if (cmp) {
1857  break;
1858  }
1859  ++left;
1860  ++right;
1861  }
1862  return cmp;
1863 }
1864 
1865 /*!
1866  * \internal
1867  * \brief Comparison of non-pattern extens.
1868  *
1869  * \param left Exten to compare.
1870  * \param right Exten to compare.
1871  *
1872  * \retval <0 if left < right
1873  * \retval =0 if left == right
1874  * \retval >0 if left > right
1875  */
1876 static int ext_cmp_exten(const char *left, const char *right)
1877 {
1878  int cmp;
1879 
1880  for (;;) {
1881  /* Ignore '-' chars as eye candy fluff. */
1882  while (*left == '-') {
1883  ++left;
1884  }
1885  while (*right == '-') {
1886  ++right;
1887  }
1888 
1889  cmp = *left - *right;
1890  if (cmp) {
1891  break;
1892  }
1893  if (!*left) {
1894  /*
1895  * Get here only if both strings ended at the same time. cmp
1896  * would be non-zero if only one string ended.
1897  */
1898  break;
1899  }
1900  ++left;
1901  ++right;
1902  }
1903  return cmp;
1904 }
1905 
1906 /*
1907  * Special characters used in patterns:
1908  * '_' underscore is the leading character of a pattern.
1909  * In other position it is treated as a regular char.
1910  * '-' The '-' is a separator and ignored. Why? So patterns like NXX-XXX-XXXX work.
1911  * . one or more of any character. Only allowed at the end of
1912  * a pattern.
1913  * ! zero or more of anything. Also impacts the result of CANMATCH
1914  * and MATCHMORE. Only allowed at the end of a pattern.
1915  * In the core routine, ! causes a match with a return code of 2.
1916  * In turn, depending on the search mode: (XXX check if it is implemented)
1917  * - E_MATCH retuns 1 (does match)
1918  * - E_MATCHMORE returns 0 (no match)
1919  * - E_CANMATCH returns 1 (does match)
1920  *
1921  * / should not appear as it is considered the separator of the CID info.
1922  * XXX at the moment we may stop on this char.
1923  *
1924  * X Z N match ranges 0-9, 1-9, 2-9 respectively.
1925  * [ denotes the start of a set of character. Everything inside
1926  * is considered literally. We can have ranges a-d and individual
1927  * characters. A '[' and '-' can be considered literally if they
1928  * are just before ']'.
1929  * XXX currently there is no way to specify ']' in a range, nor \ is
1930  * considered specially.
1931  *
1932  * When we compare a pattern with a specific extension, all characters in the extension
1933  * itself are considered literally.
1934  * XXX do we want to consider space as a separator as well ?
1935  * XXX do we want to consider the separators in non-patterns as well ?
1936  */
1937 
1938 /*!
1939  * \brief helper functions to sort extension patterns in the desired way,
1940  * so that more specific patterns appear first.
1941  *
1942  * \details
1943  * The function compares individual characters (or sets of), returning
1944  * an int where bits 0-7 are the ASCII code of the first char in the set,
1945  * bits 8-15 are the number of characters in the set, and bits 16-20 are
1946  * for special cases.
1947  * This way more specific patterns (smaller character sets) appear first.
1948  * Wildcards have a special value, so that we can directly compare them to
1949  * sets by subtracting the two values. In particular:
1950  * 0x001xx one character, character set starting with xx
1951  * 0x0yyxx yy characters, character set starting with xx
1952  * 0x18000 '.' (one or more of anything)
1953  * 0x28000 '!' (zero or more of anything)
1954  * 0x30000 NUL (end of string)
1955  * 0x40000 error in set.
1956  * The pointer to the string is advanced according to needs.
1957  * NOTES:
1958  * 1. the empty set is ignored.
1959  * 2. given that a full set has always 0 as the first element,
1960  * we could encode the special cases as 0xffXX where XX
1961  * is 1, 2, 3, 4 as used above.
1962  */
1963 static int ext_cmp_pattern_pos(const char **p, unsigned char *bitwise)
1964 {
1965 #define BITS_PER 8 /* Number of bits per unit (byte). */
1966  unsigned char c;
1967  unsigned char cmin;
1968  int count;
1969  const char *end;
1970 
1971  do {
1972  /* Get character and advance. (Ignore '-' chars as eye candy fluff.) */
1973  do {
1974  c = *(*p)++;
1975  } while (c == '-');
1976 
1977  /* always return unless we have a set of chars */
1978  switch (c) {
1979  default:
1980  /* ordinary character */
1981  bitwise[c / BITS_PER] = 1 << ((BITS_PER - 1) - (c % BITS_PER));
1982  return 0x0100 | c;
1983 
1984  case 'n':
1985  case 'N':
1986  /* 2..9 */
1987  bitwise[6] = 0x3f;
1988  bitwise[7] = 0xc0;
1989  return 0x0800 | '2';
1990 
1991  case 'x':
1992  case 'X':
1993  /* 0..9 */
1994  bitwise[6] = 0xff;
1995  bitwise[7] = 0xc0;
1996  return 0x0A00 | '0';
1997 
1998  case 'z':
1999  case 'Z':
2000  /* 1..9 */
2001  bitwise[6] = 0x7f;
2002  bitwise[7] = 0xc0;
2003  return 0x0900 | '1';
2004 
2005  case '.':
2006  /* wildcard */
2007  return 0x18000;
2008 
2009  case '!':
2010  /* earlymatch */
2011  return 0x28000; /* less specific than '.' */
2012 
2013  case '\0':
2014  /* empty string */
2015  *p = NULL;
2016  return 0x30000;
2017 
2018  case '[':
2019  /* char set */
2020  break;
2021  }
2022  /* locate end of set */
2023  end = strchr(*p, ']');
2024 
2025  if (!end) {
2026  ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
2027  return 0x40000; /* XXX make this entry go last... */
2028  }
2029 
2030  count = 0;
2031  cmin = 0xFF;
2032  for (; *p < end; ++*p) {
2033  unsigned char c1; /* first char in range */
2034  unsigned char c2; /* last char in range */
2035 
2036  c1 = (*p)[0];
2037  if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
2038  c2 = (*p)[2];
2039  *p += 2; /* skip a total of 3 chars */
2040  } else { /* individual character */
2041  c2 = c1;
2042  }
2043  if (c1 < cmin) {
2044  cmin = c1;
2045  }
2046  for (; c1 <= c2; ++c1) {
2047  unsigned char mask = 1 << ((BITS_PER - 1) - (c1 % BITS_PER));
2048 
2049  /*
2050  * Note: If two character sets score the same, the one with the
2051  * lowest ASCII values will compare as coming first. Must fill
2052  * in most significant bits for lower ASCII values to accomplish
2053  * the desired sort order.
2054  */
2055  if (!(bitwise[c1 / BITS_PER] & mask)) {
2056  /* Add the character to the set. */
2057  bitwise[c1 / BITS_PER] |= mask;
2058  count += 0x100;
2059  }
2060  }
2061  }
2062  ++*p;
2063  } while (!count);/* While the char set was empty. */
2064  return count | cmin;
2065 }
2066 
2067 /*!
2068  * \internal
2069  * \brief Comparison of exten patterns.
2070  *
2071  * \param left Pattern to compare.
2072  * \param right Pattern to compare.
2073  *
2074  * \retval <0 if left < right
2075  * \retval =0 if left == right
2076  * \retval >0 if left > right
2077  */
2078 static int ext_cmp_pattern(const char *left, const char *right)
2079 {
2080  int cmp;
2081  int left_pos;
2082  int right_pos;
2083 
2084  for (;;) {
2085  unsigned char left_bitwise[32] = { 0, };
2086  unsigned char right_bitwise[32] = { 0, };
2087 
2088  left_pos = ext_cmp_pattern_pos(&left, left_bitwise);
2089  right_pos = ext_cmp_pattern_pos(&right, right_bitwise);
2090  cmp = left_pos - right_pos;
2091  if (!cmp) {
2092  /*
2093  * Are the character sets different, even though they score the same?
2094  *
2095  * Note: Must swap left and right to get the sense of the
2096  * comparison correct. Otherwise, we would need to multiply by
2097  * -1 instead.
2098  */
2099  cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise));
2100  }
2101  if (cmp) {
2102  break;
2103  }
2104  if (!left) {
2105  /*
2106  * Get here only if both patterns ended at the same time. cmp
2107  * would be non-zero if only one pattern ended.
2108  */
2109  break;
2110  }
2111  }
2112  return cmp;
2113 }
2114 
2115 /*!
2116  * \internal
2117  * \brief Comparison of dialplan extens for sorting purposes.
2118  *
2119  * \param left Exten/pattern to compare.
2120  * \param right Exten/pattern to compare.
2121  *
2122  * \retval <0 if left < right
2123  * \retval =0 if left == right
2124  * \retval >0 if left > right
2125  */
2126 static int ext_cmp(const char *left, const char *right)
2127 {
2128  /* Make sure non-pattern extens come first. */
2129  if (left[0] != '_') {
2130  if (right[0] == '_') {
2131  return -1;
2132  }
2133  /* Compare two non-pattern extens. */
2134  return ext_cmp_exten(left, right);
2135  }
2136  if (right[0] != '_') {
2137  return 1;
2138  }
2139 
2140  /*
2141  * OK, we need full pattern sorting routine.
2142  *
2143  * Skip past the underscores
2144  */
2145  return ext_cmp_pattern(left + 1, right + 1);
2146 }
2147 
2148 static int ext_fluff_count(const char *exten)
2149 {
2150  int fluff = 0;
2151 
2152  if (*exten != '_') {
2153  /* not a pattern, simple check. */
2154  while (*exten) {
2155  if (*exten == '-') {
2156  fluff++;
2157  }
2158  exten++;
2159  }
2160 
2161  return fluff;
2162  }
2163 
2164  /* do pattern check */
2165  while (*exten) {
2166  if (*exten == '-') {
2167  fluff++;
2168  } else if (*exten == '[') {
2169  /* skip set, dashes here matter. */
2170  exten = strchr(exten, ']');
2171 
2172  if (!exten) {
2173  /* we'll end up warning about this later, don't spam logs */
2174  return fluff;
2175  }
2176  }
2177  exten++;
2178  }
2179 
2180  return fluff;
2181 }
2182 
2183 int ast_extension_cmp(const char *a, const char *b)
2184 {
2185  int cmp;
2186 
2187  cmp = ext_cmp(a, b);
2188  if (cmp < 0) {
2189  return -1;
2190  }
2191  if (cmp > 0) {
2192  return 1;
2193  }
2194  return 0;
2195 }
2196 
2197 /*!
2198  * \internal
2199  * \brief used ast_extension_{match|close}
2200  * mode is as follows:
2201  * E_MATCH success only on exact match
2202  * E_MATCHMORE success only on partial match (i.e. leftover digits in pattern)
2203  * E_CANMATCH either of the above.
2204  * \retval 0 on no-match
2205  * \retval 1 on match
2206  * \retval 2 on early match.
2207  */
2208 
2209 static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
2210 {
2211  mode &= E_MATCH_MASK; /* only consider the relevant bits */
2212 
2213 #ifdef NEED_DEBUG_HERE
2214  ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode);
2215 #endif
2216 
2217  if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
2218  int lp = ext_cmp_exten_strlen(pattern);
2219  int ld = ext_cmp_exten_strlen(data);
2220 
2221  if (lp < ld) { /* pattern too short, cannot match */
2222 #ifdef NEED_DEBUG_HERE
2223  ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n");
2224 #endif
2225  return 0;
2226  }
2227  /* depending on the mode, accept full or partial match or both */
2228  if (mode == E_MATCH) {
2229 #ifdef NEED_DEBUG_HERE
2230  ast_log(LOG_NOTICE,"return (!ext_cmp_exten(%s,%s) when mode== E_MATCH)\n", pattern, data);
2231 #endif
2232  return !ext_cmp_exten(pattern, data); /* 1 on match, 0 on fail */
2233  }
2234  if (ld == 0 || !ext_cmp_exten_partial(pattern, data)) { /* partial or full match */
2235 #ifdef NEED_DEBUG_HERE
2236  ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld);
2237 #endif
2238  return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
2239  } else {
2240 #ifdef NEED_DEBUG_HERE
2241  ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data);
2242 #endif
2243  return 0;
2244  }
2245  }
2246  if (mode == E_MATCH && data[0] == '_') {
2247  /*
2248  * XXX It is bad design that we don't know if we should be
2249  * comparing data and pattern as patterns or comparing data if
2250  * it conforms to pattern when the function is called. First,
2251  * assume they are both patterns. If they don't match then try
2252  * to see if data conforms to the given pattern.
2253  *
2254  * note: if this test is left out, then _x. will not match _x. !!!
2255  */
2256 #ifdef NEED_DEBUG_HERE
2257  ast_log(LOG_NOTICE, "Comparing as patterns first. pattern:%s data:%s\n", pattern, data);
2258 #endif
2259  if (!ext_cmp_pattern(pattern + 1, data + 1)) {
2260 #ifdef NEED_DEBUG_HERE
2261  ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n");
2262 #endif
2263  return 1;
2264  }
2265  }
2266 
2267  ++pattern; /* skip leading _ */
2268  /*
2269  * XXX below we stop at '/' which is a separator for the CID info. However we should
2270  * not store '/' in the pattern at all. When we insure it, we can remove the checks.
2271  */
2272  for (;;) {
2273  const char *end;
2274 
2275  /* Ignore '-' chars as eye candy fluff. */
2276  while (*data == '-') {
2277  ++data;
2278  }
2279  while (*pattern == '-') {
2280  ++pattern;
2281  }
2282  if (!*data || !*pattern || *pattern == '/') {
2283  break;
2284  }
2285 
2286  switch (*pattern) {
2287  case '[': /* a range */
2288  ++pattern;
2289  end = strchr(pattern, ']'); /* XXX should deal with escapes ? */
2290  if (!end) {
2291  ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
2292  return 0; /* unconditional failure */
2293  }
2294  if (pattern == end) {
2295  /* Ignore empty character sets. */
2296  ++pattern;
2297  continue;
2298  }
2299  for (; pattern < end; ++pattern) {
2300  if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
2301  if (*data >= pattern[0] && *data <= pattern[2])
2302  break; /* match found */
2303  else {
2304  pattern += 2; /* skip a total of 3 chars */
2305  continue;
2306  }
2307  } else if (*data == pattern[0])
2308  break; /* match found */
2309  }
2310  if (pattern >= end) {
2311 #ifdef NEED_DEBUG_HERE
2312  ast_log(LOG_NOTICE,"return (0) when pattern>=end\n");
2313 #endif
2314  return 0;
2315  }
2316  pattern = end; /* skip and continue */
2317  break;
2318  case 'n':
2319  case 'N':
2320  if (*data < '2' || *data > '9') {
2321 #ifdef NEED_DEBUG_HERE
2322  ast_log(LOG_NOTICE,"return (0) N is not matched\n");
2323 #endif
2324  return 0;
2325  }
2326  break;
2327  case 'x':
2328  case 'X':
2329  if (*data < '0' || *data > '9') {
2330 #ifdef NEED_DEBUG_HERE
2331  ast_log(LOG_NOTICE,"return (0) X is not matched\n");
2332 #endif
2333  return 0;
2334  }
2335  break;
2336  case 'z':
2337  case 'Z':
2338  if (*data < '1' || *data > '9') {
2339 #ifdef NEED_DEBUG_HERE
2340  ast_log(LOG_NOTICE,"return (0) Z is not matched\n");
2341 #endif
2342  return 0;
2343  }
2344  break;
2345  case '.': /* Must match, even with more digits */
2346 #ifdef NEED_DEBUG_HERE
2347  ast_log(LOG_NOTICE, "return (1) when '.' is matched\n");
2348 #endif
2349  return 1;
2350  case '!': /* Early match */
2351 #ifdef NEED_DEBUG_HERE
2352  ast_log(LOG_NOTICE, "return (2) when '!' is matched\n");
2353 #endif
2354  return 2;
2355  default:
2356  if (*data != *pattern) {
2357 #ifdef NEED_DEBUG_HERE
2358  ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern);
2359 #endif
2360  return 0;
2361  }
2362  break;
2363  }
2364  ++data;
2365  ++pattern;
2366  }
2367  if (*data) /* data longer than pattern, no match */ {
2368 #ifdef NEED_DEBUG_HERE
2369  ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n");
2370 #endif
2371  return 0;
2372  }
2373 
2374  /*
2375  * match so far, but ran off the end of data.
2376  * Depending on what is next, determine match or not.
2377  */
2378  if (*pattern == '\0' || *pattern == '/') { /* exact match */
2379 #ifdef NEED_DEBUG_HERE
2380  ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1);
2381 #endif
2382  return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */
2383  } else if (*pattern == '!') { /* early match */
2384 #ifdef NEED_DEBUG_HERE
2385  ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n");
2386 #endif
2387  return 2;
2388  } else { /* partial match */
2389 #ifdef NEED_DEBUG_HERE
2390  ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1);
2391 #endif
2392  return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */
2393  }
2394 }
2395 
2396 /*
2397  * Wrapper around _extension_match_core() to do performance measurement
2398  * using the profiling code.
2399  */
2400 static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
2401 {
2402  int i;
2403  static int prof_id = -2; /* marker for 'unallocated' id */
2404  if (prof_id == -2) {
2405  prof_id = ast_add_profile("ext_match", 0);
2406  }
2407  ast_mark(prof_id, 1);
2408  i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode);
2409  ast_mark(prof_id, 0);
2410  return i;
2411 }
2412 
2413 int ast_extension_match(const char *pattern, const char *data)
2414 {
2415  return extension_match_core(pattern, data, E_MATCH);
2416 }
2417 
2418 int ast_extension_close(const char *pattern, const char *data, int needmore)
2419 {
2420  if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
2421  ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
2422  return extension_match_core(pattern, data, needmore);
2423 }
2424 
2425 /* This structure must remain in sync with ast_context for proper hashtab matching */
2426 struct fake_context /* this struct is purely for matching in the hashtab */
2427 {
2429  struct ast_exten *root;
2433  struct ast_includes includes;
2434  struct ast_ignorepats ignorepats;
2435  struct ast_sws alts;
2436  const char *registrar;
2440  char name[256];
2441 };
2442 
2443 struct ast_context *ast_context_find(const char *name)
2444 {
2445  struct ast_context *tmp;
2446  struct fake_context item;
2447 
2448  if (!name) {
2449  return NULL;
2450  }
2452  if (contexts_table) {
2453  ast_copy_string(item.name, name, sizeof(item.name));
2454  tmp = ast_hashtab_lookup(contexts_table, &item);
2455  } else {
2456  tmp = NULL;
2457  while ((tmp = ast_walk_contexts(tmp))) {
2458  if (!strcasecmp(name, tmp->name)) {
2459  break;
2460  }
2461  }
2462  }
2464  return tmp;
2465 }
2466 
2467 #define STATUS_NO_CONTEXT 1
2468 #define STATUS_NO_EXTENSION 2
2469 #define STATUS_NO_PRIORITY 3
2470 #define STATUS_NO_LABEL 4
2471 #define STATUS_SUCCESS 5
2472 
2473 static int matchcid(const char *cidpattern, const char *callerid)
2474 {
2475  /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
2476  failing to get a number should count as a match, otherwise not */
2477 
2478  if (ast_strlen_zero(callerid)) {
2479  return ast_strlen_zero(cidpattern) ? 1 : 0;
2480  }
2481 
2482  return ast_extension_match(cidpattern, callerid);
2483 }
2484 
2486  struct ast_context *bypass, struct pbx_find_info *q,
2487  const char *context, const char *exten, int priority,
2488  const char *label, const char *callerid, enum ext_match_t action)
2489 {
2490  int x, res;
2491  struct ast_context *tmp = NULL;
2492  struct ast_exten *e = NULL, *eroot = NULL;
2493  struct ast_exten pattern = {NULL, };
2494  struct scoreboard score = {0, };
2495  struct ast_str *tmpdata = NULL;
2496  int idx;
2497 
2498  pattern.label = label;
2499  pattern.priority = priority;
2500 #ifdef NEED_DEBUG_HERE
2501  ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
2502 #endif
2503 
2504  /* Initialize status if appropriate */
2505  if (q->stacklen == 0) {
2507  q->swo = NULL;
2508  q->data = NULL;
2509  q->foundcontext = NULL;
2510  } else if (q->stacklen >= AST_PBX_MAX_STACK) {
2511  ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
2512  return NULL;
2513  }
2514 
2515  /* Check first to see if we've already been checked */
2516  for (x = 0; x < q->stacklen; x++) {
2517  if (!strcasecmp(q->incstack[x], context))
2518  return NULL;
2519  }
2520 
2521  if (bypass) { /* bypass means we only look there */
2522  tmp = bypass;
2523  } else { /* look in contexts */
2524  tmp = find_context(context);
2525  if (!tmp) {
2526  return NULL;
2527  }
2528  }
2529 
2530  if (q->status < STATUS_NO_EXTENSION)
2532 
2533  /* Do a search for matching extension */
2534 
2535  eroot = NULL;
2536  score.total_specificity = 0;
2537  score.exten = 0;
2538  score.total_length = 0;
2539  if (!tmp->pattern_tree && tmp->root_table) {
2541 #ifdef NEED_DEBUG
2542  ast_debug(1, "Tree Created in context %s:\n", context);
2543  log_match_char_tree(tmp->pattern_tree," ");
2544 #endif
2545  }
2546 #ifdef NEED_DEBUG
2547  ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
2548  log_match_char_tree(tmp->pattern_tree, ":: ");
2549 #endif
2550 
2551  do {
2552  if (!ast_strlen_zero(overrideswitch)) {
2553  char *osw = ast_strdupa(overrideswitch), *name;
2554  struct ast_switch *asw;
2555  ast_switch_f *aswf = NULL;
2556  char *datap;
2557  int eval = 0;
2558 
2559  name = strsep(&osw, "/");
2560  asw = pbx_findswitch(name);
2561 
2562  if (!asw) {
2563  ast_log(LOG_WARNING, "No such switch '%s'\n", name);
2564  break;
2565  }
2566 
2567  if (osw && strchr(osw, '$')) {
2568  eval = 1;
2569  }
2570 
2571  if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
2572  ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n");
2573  break;
2574  } else if (eval) {
2575  /* Substitute variables now */
2576  pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
2577  datap = ast_str_buffer(tmpdata);
2578  } else {
2579  datap = osw;
2580  }
2581 
2582  /* equivalent of extension_match_core() at the switch level */
2583  if (action == E_CANMATCH)
2584  aswf = asw->canmatch;
2585  else if (action == E_MATCHMORE)
2586  aswf = asw->matchmore;
2587  else /* action == E_MATCH */
2588  aswf = asw->exists;
2589  if (!aswf) {
2590  res = 0;
2591  } else {
2592  if (chan) {
2593  ast_autoservice_start(chan);
2594  }
2595  res = aswf(chan, context, exten, priority, callerid, datap);
2596  if (chan) {
2597  ast_autoservice_stop(chan);
2598  }
2599  }
2600  if (res) { /* Got a match */
2601  q->swo = asw;
2602  q->data = datap;
2603  q->foundcontext = context;
2604  /* XXX keep status = STATUS_NO_CONTEXT ? */
2605  return NULL;
2606  }
2607  }
2608  } while (0);
2609 
2610  if (extenpatternmatchnew) {
2611  new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
2612  eroot = score.exten;
2613 
2614  if (score.last_char == '!' && action == E_MATCHMORE) {
2615  /* We match an extension ending in '!'.
2616  * The decision in this case is final and is NULL (no match).
2617  */
2618 #ifdef NEED_DEBUG_HERE
2619  ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
2620 #endif
2621  return NULL;
2622  }
2623 
2624  if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
2625  q->status = STATUS_SUCCESS;
2626 #ifdef NEED_DEBUG_HERE
2627  ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
2628 #endif
2629  return score.canmatch_exten;
2630  }
2631 
2632  if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) {
2633  if (score.node) {
2634  struct ast_exten *z = trie_find_next_match(score.node);
2635  if (z) {
2636 #ifdef NEED_DEBUG_HERE
2637  ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
2638 #endif
2639  } else {
2640  if (score.canmatch_exten) {
2641 #ifdef NEED_DEBUG_HERE
2642  ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
2643 #endif
2644  return score.canmatch_exten;
2645  } else {
2646 #ifdef NEED_DEBUG_HERE
2647  ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
2648 #endif
2649  }
2650  }
2651  return z;
2652  }
2653 #ifdef NEED_DEBUG_HERE
2654  ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
2655 #endif
2656  return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */
2657  }
2658 
2659  if (eroot) {
2660  /* found entry, now look for the right priority */
2661  if (q->status < STATUS_NO_PRIORITY)
2663  e = NULL;
2664  if (action == E_FINDLABEL && label ) {
2665  if (q->status < STATUS_NO_LABEL)
2666  q->status = STATUS_NO_LABEL;
2667  e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
2668  } else {
2669  e = ast_hashtab_lookup(eroot->peer_table, &pattern);
2670  }
2671  if (e) { /* found a valid match */
2672  q->status = STATUS_SUCCESS;
2673  q->foundcontext = context;
2674 #ifdef NEED_DEBUG_HERE
2675  ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
2676 #endif
2677  return e;
2678  }
2679  }
2680  } else { /* the old/current default exten pattern match algorithm */
2681 
2682  /* scan the list trying to match extension and CID */
2683  eroot = NULL;
2684  while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
2685  int match = extension_match_core(eroot->exten, exten, action);
2686  /* 0 on fail, 1 on match, 2 on earlymatch */
2687 
2688  if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
2689  continue; /* keep trying */
2690  if (match == 2 && action == E_MATCHMORE) {
2691  /* We match an extension ending in '!'.
2692  * The decision in this case is final and is NULL (no match).
2693  */
2694  return NULL;
2695  }
2696  /* found entry, now look for the right priority */
2697  if (q->status < STATUS_NO_PRIORITY)
2699  e = NULL;
2700  if (action == E_FINDLABEL && label ) {
2701  if (q->status < STATUS_NO_LABEL)
2702  q->status = STATUS_NO_LABEL;
2703  e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
2704  } else {
2705  e = ast_hashtab_lookup(eroot->peer_table, &pattern);
2706  }
2707  if (e) { /* found a valid match */
2708  q->status = STATUS_SUCCESS;
2709  q->foundcontext = context;
2710  return e;
2711  }
2712  }
2713  }
2714 
2715  /* Check alternative switches */
2716  for (idx = 0; idx < ast_context_switches_count(tmp); idx++) {
2717  const struct ast_sw *sw = ast_context_switches_get(tmp, idx);
2718  struct ast_switch *asw = pbx_findswitch(ast_get_switch_name(sw));
2719  ast_switch_f *aswf = NULL;
2720  const char *datap;
2721 
2722  if (!asw) {
2723  ast_log(LOG_WARNING, "No such switch '%s'\n", ast_get_switch_name(sw));
2724  continue;
2725  }
2726 
2727  /* Substitute variables now */
2728  if (ast_get_switch_eval(sw)) {
2729  if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
2730  ast_log(LOG_WARNING, "Can't evaluate switch?!\n");
2731  continue;
2732  }
2734  ast_str_buffer(tmpdata), ast_str_size(tmpdata));
2735  datap = ast_str_buffer(tmpdata);
2736  } else {
2737  datap = ast_get_switch_data(sw);
2738  }
2739 
2740  /* equivalent of extension_match_core() at the switch level */
2741  if (action == E_CANMATCH)
2742  aswf = asw->canmatch;
2743  else if (action == E_MATCHMORE)
2744  aswf = asw->matchmore;
2745  else /* action == E_MATCH */
2746  aswf = asw->exists;
2747  if (!aswf)
2748  res = 0;
2749  else {
2750  if (chan)
2751  ast_autoservice_start(chan);
2752  res = aswf(chan, context, exten, priority, callerid, datap);
2753  if (chan)
2754  ast_autoservice_stop(chan);
2755  }
2756  if (res) { /* Got a match */
2757  q->swo = asw;
2758  q->data = datap;
2759  q->foundcontext = context;
2760  /* XXX keep status = STATUS_NO_CONTEXT ? */
2761  return NULL;
2762  }
2763  }
2764  q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */
2765  /* Now try any includes we have in this context */
2766  for (idx = 0; idx < ast_context_includes_count(tmp); idx++) {
2767  const struct ast_include *i = ast_context_includes_get(tmp, idx);
2768 
2769  if (include_valid(i)) {
2770  if ((e = pbx_find_extension(chan, bypass, q, include_rname(i), exten, priority, label, callerid, action))) {
2771 #ifdef NEED_DEBUG_HERE
2772  ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
2773 #endif
2774  return e;
2775  }
2776  if (q->swo)
2777  return NULL;
2778  }
2779  }
2780  return NULL;
2781 }
2782 
2783 static void exception_store_free(void *data)
2784 {
2785  struct pbx_exception *exception = data;
2786  ast_string_field_free_memory(exception);
2787  ast_free(exception);
2788 }
2789 
2791  .type = "EXCEPTION",
2792  .destroy = exception_store_free,
2793 };
2794 
2795 /*!
2796  * \internal
2797  * \brief Set the PBX to execute the exception extension.
2798  *
2799  * \param chan Channel to raise the exception on.
2800  * \param reason Reason exception is raised.
2801  * \param priority Dialplan priority to set.
2802  *
2803  * \retval 0 on success.
2804  * \retval -1 on error.
2805  */
2806 int raise_exception(struct ast_channel *chan, const char *reason, int priority)
2807 {
2808  struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
2809  struct pbx_exception *exception = NULL;
2810 
2811  if (!ds) {
2812  ds = ast_datastore_alloc(&exception_store_info, NULL);
2813  if (!ds)
2814  return -1;
2815  if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
2816  ast_datastore_free(ds);
2817  return -1;
2818  }
2819  ds->data = exception;
2820  ast_channel_datastore_add(chan, ds);
2821  } else
2822  exception = ds->data;
2823 
2824  ast_string_field_set(exception, reason, reason);
2825  ast_string_field_set(exception, context, ast_channel_context(chan));
2826  ast_string_field_set(exception, exten, ast_channel_exten(chan));
2827  exception->priority = ast_channel_priority(chan);
2828  set_ext_pri(chan, "e", priority);
2829  return 0;
2830 }
2831 
2832 static int acf_exception_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
2833 {
2834  struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
2835  struct pbx_exception *exception = NULL;
2836  if (!ds || !ds->data)
2837  return -1;
2838  exception = ds->data;
2839  if (!strcasecmp(data, "REASON"))
2840  ast_copy_string(buf, exception->reason, buflen);
2841  else if (!strcasecmp(data, "CONTEXT"))
2842  ast_copy_string(buf, exception->context, buflen);
2843  else if (!strncasecmp(data, "EXTEN", 5))
2844  ast_copy_string(buf, exception->exten, buflen);
2845  else if (!strcasecmp(data, "PRIORITY"))
2846  snprintf(buf, buflen, "%d", exception->priority);
2847  else
2848  return -1;
2849  return 0;
2850 }
2851 
2853  .name = "EXCEPTION",
2854  .read = acf_exception_read,
2855 };
2856 
2857 /*!
2858  * \brief The return value depends on the action:
2859  *
2860  * E_MATCH, E_CANMATCH, E_MATCHMORE require a real match,
2861  * and return 0 on failure, -1 on match;
2862  * E_FINDLABEL maps the label to a priority, and returns
2863  * the priority on success, ... XXX
2864  * E_SPAWN, spawn an application,
2865  *
2866  * \retval 0 on success.
2867  * \retval -1 on failure.
2868  *
2869  * \note The channel is auto-serviced in this function, because doing an extension
2870  * match may block for a long time. For example, if the lookup has to use a network
2871  * dialplan switch, such as DUNDi or IAX2, it may take a while. However, the channel
2872  * auto-service code will queue up any important signalling frames to be processed
2873  * after this is done.
2874  */
2875 static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
2876  const char *context, const char *exten, int priority,
2877  const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
2878 {
2879  struct ast_exten *e;
2880  struct ast_app *app;
2881  char *substitute = NULL;
2882  struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
2883  char passdata[EXT_DATA_SIZE];
2884  int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
2885 
2887 
2888  if (!context) {
2889  context = con->name;
2890  }
2891 
2892  if (found)
2893  *found = 0;
2894 
2895  e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
2896  if (e) {
2897  if (found)
2898  *found = 1;
2899  if (matching_action) {
2901  return -1; /* success, we found it */
2902  } else if (action == E_FINDLABEL) { /* map the label to a priority */
2903  int res = e->priority;
2904 
2906 
2907  /* the priority we were looking for */
2908  return res;
2909  } else { /* spawn */
2910  if (!e->cached_app)
2911  e->cached_app = pbx_findapp(e->app);
2912  app = e->cached_app;
2913  if (ast_strlen_zero(e->data)) {
2914  *passdata = '\0';
2915  } else {
2916  const char *tmp;
2917  if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
2918  /* no variables to substitute, copy on through */
2919  ast_copy_string(passdata, e->data, sizeof(passdata));
2920  } else {
2921  /* save e->data on stack for later processing after lock released */
2922  substitute = ast_strdupa(e->data);
2923  }
2924  }
2926  if (!app) {
2927  ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
2928  return -1;
2929  }
2930  if (ast_channel_context(c) != context)
2931  ast_channel_context_set(c, context);
2932  if (ast_channel_exten(c) != exten)
2933  ast_channel_exten_set(c, exten);
2934  ast_channel_priority_set(c, priority);
2935  if (substitute) {
2936  pbx_substitute_variables_helper(c, substitute, passdata, sizeof(passdata)-1);
2937  }
2938  ast_debug(1, "Launching '%s'\n", app_name(app));
2939  if (VERBOSITY_ATLEAST(3)) {
2940  ast_verb(3, "Executing [%s@%s:%d] " COLORIZE_FMT "(\"" COLORIZE_FMT "\", \"" COLORIZE_FMT "\") %s\n",
2941  exten, context, priority,
2942  COLORIZE(COLOR_BRCYAN, 0, app_name(app)),
2944  COLORIZE(COLOR_BRMAGENTA, 0, passdata),
2945  "in new stack");
2946  }
2947  return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */
2948  }
2949  } else if (q.swo) { /* not found here, but in another switch */
2950  if (found)
2951  *found = 1;
2953  if (matching_action) {
2954  return -1;
2955  } else {
2956  if (!q.swo->exec) {
2957  ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
2958  return -1;
2959  }
2960  return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
2961  }
2962  } else { /* not found anywhere, see what happened */
2964  /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
2965  switch (q.status) {
2966  case STATUS_NO_CONTEXT:
2967  if (!matching_action && !combined_find_spawn)
2968  ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
2969  break;
2970  case STATUS_NO_EXTENSION:
2971  if (!matching_action && !combined_find_spawn)
2972  ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
2973  break;
2974  case STATUS_NO_PRIORITY:
2975  if (!matching_action && !combined_find_spawn)
2976  ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
2977  break;
2978  case STATUS_NO_LABEL:
2979  if (context && !combined_find_spawn)
2980  ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, ""));
2981  break;
2982  default:
2983  ast_debug(1, "Shouldn't happen!\n");
2984  }
2985 
2986  return (matching_action) ? 0 : -1;
2987  }
2988 }
2989 
2990 /*! \brief Find hint for given extension in context */
2991 static struct ast_exten *ast_hint_extension_nolock(struct ast_channel *c, const char *context, const char *exten)
2992 {
2993  struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
2994  return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
2995 }
2996 
2997 static struct ast_exten *ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
2998 {
2999  struct ast_exten *e;
3001  e = ast_hint_extension_nolock(c, context, exten);
3003  return e;
3004 }
3005 
3007 {
3008  switch (devstate) {
3009  case AST_DEVICE_ONHOLD:
3010  return AST_EXTENSION_ONHOLD;
3011  case AST_DEVICE_BUSY:
3012  return AST_EXTENSION_BUSY;
3013  case AST_DEVICE_UNKNOWN:
3014  return AST_EXTENSION_NOT_INUSE;
3016  case AST_DEVICE_INVALID:
3018  case AST_DEVICE_RINGINUSE:
3020  case AST_DEVICE_RINGING:
3021  return AST_EXTENSION_RINGING;
3022  case AST_DEVICE_INUSE:
3023  return AST_EXTENSION_INUSE;
3024  case AST_DEVICE_NOT_INUSE:
3025  return AST_EXTENSION_NOT_INUSE;
3026  case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
3027  break;
3028  }
3029 
3030  return AST_EXTENSION_NOT_INUSE;
3031 }
3032 
3033 /*!
3034  * \internal
3035  * \brief Parse out the presence portion of the hint string
3036  */
3037 static char *parse_hint_presence(struct ast_str *hint_args)
3038 {
3039  char *copy = ast_strdupa(ast_str_buffer(hint_args));
3040  char *tmp = "";
3041 
3042  if ((tmp = strrchr(copy, ','))) {
3043  *tmp = '\0';
3044  tmp++;
3045  } else {
3046  return NULL;
3047  }
3048  ast_str_set(&hint_args, 0, "%s", tmp);
3049  return ast_str_buffer(hint_args);
3050 }
3051 
3052 /*!
3053  * \internal
3054  * \brief Parse out the device portion of the hint string
3055  */
3056 static char *parse_hint_device(struct ast_str *hint_args)
3057 {
3058  char *copy = ast_strdupa(ast_str_buffer(hint_args));
3059  char *tmp;
3060 
3061  if ((tmp = strrchr(copy, ','))) {
3062  *tmp = '\0';
3063  }
3064 
3065  ast_str_set(&hint_args, 0, "%s", copy);
3066  return ast_str_buffer(hint_args);
3067 }
3068 
3069 static void device_state_info_dt(void *obj)
3070 {
3071  struct ast_device_state_info *info = obj;
3072 
3074 }
3075 
3077 {
3079 }
3080 
3081 static int ast_extension_state3(struct ast_str *hint_app, struct ao2_container *device_state_info)
3082 {
3083  char *cur;
3084  char *rest;
3085  struct ast_devstate_aggregate agg;
3086 
3087  /* One or more devices separated with a & character */
3088  rest = parse_hint_device(hint_app);
3089 
3091  while ((cur = strsep(&rest, "&"))) {
3093 
3094  ast_devstate_aggregate_add(&agg, state);
3095  if (device_state_info) {
3096  struct ast_device_state_info *obj;
3097 
3098  obj = ao2_alloc_options(sizeof(*obj) + strlen(cur), device_state_info_dt, AO2_ALLOC_OPT_LOCK_NOLOCK);
3099  /* if failed we cannot add this device */
3100  if (obj) {
3101  obj->device_state = state;
3102  strcpy(obj->device_name, cur);
3103  ao2_link(device_state_info, obj);
3104  ao2_ref(obj, -1);
3105  }
3106  }
3107  }
3108 
3110 }
3111 
3112 /*! \brief Check state of extension by using hints */
3113 static int ast_extension_state2(struct ast_exten *e, struct ao2_container *device_state_info)
3114 {
3115  struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
3116 
3117  if (!e || !hint_app) {
3118  return -1;
3119  }
3120 
3121  ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e));
3122  return ast_extension_state3(hint_app, device_state_info);
3123 }
3124 
3125 /*! \brief Return extension_state as string */
3126 const char *ast_extension_state2str(int extension_state)
3127 {
3128  int i;
3129 
3130  for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
3131  if (extension_states[i].extension_state == extension_state)
3132  return extension_states[i].text;
3133  }
3134  return "Unknown";
3135 }
3136 
3137 /*!
3138  * \internal
3139  * \brief Check extension state for an extension by using hint
3140  */
3141 static int internal_extension_state_extended(struct ast_channel *c, const char *context, const char *exten,
3142  struct ao2_container *device_state_info)
3143 {
3144  struct ast_exten *e;
3145 
3146  if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */
3147  return -1; /* No hint, return -1 */
3148  }
3149 
3150  if (e->exten[0] == '_') {
3151  /* Create this hint on-the-fly, we explicitly lock hints here to ensure the
3152  * same locking order as if this were done through configuration file - that is
3153  * hints is locked first and then (if needed) contexts is locked
3154  */
3155  ao2_lock(hints);
3156  ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
3157  e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
3158  e->registrar);
3159  ao2_unlock(hints);
3160  if (!(e = ast_hint_extension(c, context, exten))) {
3161  /* Improbable, but not impossible */
3162  return -1;
3163  }
3164  }
3165 
3166  return ast_extension_state2(e, device_state_info); /* Check all devices in the hint */
3167 }
3168 
3169 /*! \brief Check extension state for an extension by using hint */
3170 int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
3171 {
3172  return internal_extension_state_extended(c, context, exten, NULL);
3173 }
3174 
3175 /*! \brief Check extended extension state for an extension by using hint */
3176 int ast_extension_state_extended(struct ast_channel *c, const char *context, const char *exten,
3177  struct ao2_container **device_state_info)
3178 {
3179  struct ao2_container *container = NULL;
3180  int ret;
3181 
3182  if (device_state_info) {
3183  container = alloc_device_state_info();
3184  }
3185 
3186  ret = internal_extension_state_extended(c, context, exten, container);
3187  if (ret < 0 && container) {
3188  ao2_ref(container, -1);
3189  container = NULL;
3190  }
3191 
3192  if (device_state_info) {
3194  *device_state_info = container;
3195  }
3196 
3197  return ret;
3198 }
3199 
3200 static int extension_presence_state_helper(struct ast_exten *e, char **subtype, char **message)
3201 {
3202  struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
3203  char *presence_provider;
3204  const char *app;
3205 
3206  if (!e || !hint_app) {
3207  return -1;
3208  }
3209 
3210  app = ast_get_extension_app(e);
3211  if (ast_strlen_zero(app)) {
3212  return -1;
3213  }
3214 
3215  ast_str_set(&hint_app, 0, "%s", app);
3216  presence_provider = parse_hint_presence(hint_app);
3217 
3218  if (ast_strlen_zero(presence_provider)) {
3219  /* No presence string in the hint */
3220  return 0;
3221  }
3222 
3223  return ast_presence_state(presence_provider, subtype, message);
3224 }
3225 
3226 int ast_hint_presence_state(struct ast_channel *c, const char *context, const char *exten, char **subtype, char **message)
3227 {
3228  struct ast_exten *e;
3229 
3230  if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */
3231  return -1; /* No hint, return -1 */
3232  }
3233 
3234  if (e->exten[0] == '_') {
3235  /* Create this hint on-the-fly */
3236  ao2_lock(hints);
3237  ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
3238  e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
3239  e->registrar);
3240  ao2_unlock(hints);
3241  if (!(e = ast_hint_extension(c, context, exten))) {
3242  /* Improbable, but not impossible */
3243  return -1;
3244  }
3245  }
3246 
3247  return extension_presence_state_helper(e, subtype, message);
3248 }
3249 
3251  const char *context,
3252  const char *exten,
3253  void *data,
3254  enum ast_state_cb_update_reason reason,
3255  struct ast_hint *hint,
3256  struct ao2_container *device_state_info)
3257 {
3258  int res = 0;
3259  struct ast_state_cb_info info = { 0, };
3260 
3261  info.reason = reason;
3262 
3263  /* Copy over current hint data */
3264  if (hint) {
3265  ao2_lock(hint);
3266  info.exten_state = hint->laststate;
3268  info.presence_state = hint->last_presence_state;
3269  if (!(ast_strlen_zero(hint->last_presence_subtype))) {
3271  } else {
3272  info.presence_subtype = "";
3273  }
3274  if (!(ast_strlen_zero(hint->last_presence_message))) {
3276  } else {
3277  info.presence_message = "";
3278  }
3279  ao2_unlock(hint);
3280  } else {
3282  }
3283 
3284  res = cb(context, exten, &info, data);
3285 
3286  return res;
3287 }
3288 
3289 /*!
3290  * /internal
3291  * /brief Identify a channel for every device which is supposedly responsible for the device state.
3292  *
3293  * Especially when the device is ringing, the oldest ringing channel is chosen.
3294  * For all other cases the first encountered channel in the specific state is chosen.
3295  */
3297 {
3298  struct ao2_iterator iter;
3299  struct ast_device_state_info *info;
3300  struct ast_channel *chan;
3301 
3302  if (!c || !ao2_container_count(c)) {
3303  return;
3304  }
3305  iter = ao2_iterator_init(c, 0);
3306  for (; (info = ao2_iterator_next(&iter)); ao2_ref(info, -1)) {
3307  enum ast_channel_state search_state = 0; /* prevent false uninit warning */
3308  char match[AST_CHANNEL_NAME];
3309  struct ast_channel_iterator *chan_iter;
3310  struct timeval chantime = {0, }; /* prevent false uninit warning */
3311 
3312  switch (info->device_state) {
3313  case AST_DEVICE_RINGING:
3314  case AST_DEVICE_RINGINUSE:
3315  /* find ringing channel */
3316  search_state = AST_STATE_RINGING;
3317  break;
3318  case AST_DEVICE_BUSY:
3319  /* find busy channel */
3320  search_state = AST_STATE_BUSY;
3321  break;
3322  case AST_DEVICE_ONHOLD:
3323  case AST_DEVICE_INUSE:
3324  /* find up channel */
3325  search_state = AST_STATE_UP;
3326  break;
3327  case AST_DEVICE_UNKNOWN:
3328  case AST_DEVICE_NOT_INUSE:
3329  case AST_DEVICE_INVALID:
3331  case AST_DEVICE_TOTAL /* not a state */:
3332  /* no channels are of interest */
3333  continue;
3334  }
3335 
3336  /* iterate over all channels of the device */
3337  snprintf(match, sizeof(match), "%s-", info->device_name);
3338  chan_iter = ast_channel_iterator_by_name_new(match, strlen(match));
3339  for (; (chan = ast_channel_iterator_next(chan_iter)); ast_channel_unref(chan)) {
3340  ast_channel_lock(chan);
3341  /* this channel's state doesn't match */
3342  if (search_state != ast_channel_state(chan)) {
3343  ast_channel_unlock(chan);
3344  continue;
3345  }
3346  /* any non-ringing channel will fit */
3347  if (search_state != AST_STATE_RINGING) {
3348  ast_channel_unlock(chan);
3349  info->causing_channel = chan; /* is kept ref'd! */
3350  break;
3351  }
3352  /* but we need the oldest ringing channel of the device to match with undirected pickup */
3353  if (!info->causing_channel) {
3354  chantime = ast_channel_creationtime(chan);
3355  ast_channel_ref(chan); /* must ref it! */
3356  info->causing_channel = chan;
3357  } else if (ast_tvcmp(ast_channel_creationtime(chan), chantime) < 0) {
3358  chantime = ast_channel_creationtime(chan);
3360  ast_channel_ref(chan); /* must ref it! */
3361  info->causing_channel = chan;
3362  }
3363  ast_channel_unlock(chan);
3364  }
3365  ast_channel_iterator_destroy(chan_iter);
3366  }
3367  ao2_iterator_destroy(&iter);
3368 }
3369 
3370 static void device_state_notify_callbacks(struct ast_hint *hint, struct ast_str **hint_app)
3371 {
3372  struct ao2_iterator cb_iter;
3373  struct ast_state_cb *state_cb;
3374  int state;
3375  int same_state;
3376  struct ao2_container *device_state_info;
3377  int first_extended_cb_call = 1;
3380 
3381  ao2_lock(hint);
3382  if (!hint->exten) {
3383  /* The extension has already been destroyed */
3384  ao2_unlock(hint);
3385  return;
3386  }
3387 
3388  /*
3389  * Save off strings in case the hint extension gets destroyed
3390  * while we are notifying the watchers.
3391  */
3392  ast_copy_string(context_name,
3394  sizeof(context_name));
3395  ast_copy_string(exten_name, ast_get_extension_name(hint->exten),
3396  sizeof(exten_name));
3397  ast_str_set(hint_app, 0, "%s", ast_get_extension_app(hint->exten));
3398  ao2_unlock(hint);
3399 
3400  /*
3401  * Get device state for this hint.
3402  *
3403  * NOTE: We cannot hold any locks while determining the hint
3404  * device state or notifying the watchers without causing a
3405  * deadlock. (conlock, hints, and hint)
3406  */
3407 
3408  /* Make a container so state3 can fill it if we wish.
3409  * If that failed we simply do not provide the extended state info.
3410  */
3411  device_state_info = alloc_device_state_info();
3412 
3413  state = ast_extension_state3(*hint_app, device_state_info);
3414  same_state = state == hint->laststate;
3415  if (same_state && (~state & AST_EXTENSION_RINGING)) {
3416  ao2_cleanup(device_state_info);
3417  return;
3418  }
3419 
3420  /* Device state changed since last check - notify the watchers. */
3421  hint->laststate = state; /* record we saw the change */
3422 
3423  /* For general callbacks */
3424  if (!same_state) {
3425  cb_iter = ao2_iterator_init(statecbs, 0);
3426  for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3428  context_name,
3429  exten_name,
3430  state_cb->data,
3432  hint,
3433  NULL);
3434  }
3435  ao2_iterator_destroy(&cb_iter);
3436  }
3437 
3438  /* For extension callbacks */
3439  /* extended callbacks are called when the state changed or when AST_STATE_RINGING is
3440  * included. Normal callbacks are only called when the state changed.
3441  */
3442  cb_iter = ao2_iterator_init(hint->callbacks, 0);
3443  for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3444  if (state_cb->extended && first_extended_cb_call) {
3445  /* Fill detailed device_state_info now that we know it is used by extd. callback */
3446  first_extended_cb_call = 0;
3447  get_device_state_causing_channels(device_state_info);
3448  }
3449  if (state_cb->extended || !same_state) {
3451  context_name,
3452  exten_name,
3453  state_cb->data,
3455  hint,
3456  state_cb->extended ? device_state_info : NULL);
3457  }
3458  }
3459  ao2_iterator_destroy(&cb_iter);
3460 
3461  ao2_cleanup(device_state_info);
3462 }
3463 
3464 static void presence_state_notify_callbacks(struct ast_hint *hint, struct ast_str **hint_app,
3465  struct ast_presence_state_message *presence_state)
3466 {
3467  struct ao2_iterator cb_iter;
3468  struct ast_state_cb *state_cb;
3471 
3472  ao2_lock(hint);
3473  if (!hint->exten) {
3474  /* The extension has already been destroyed */
3475  ao2_unlock(hint);
3476  return;
3477  }
3478 
3479  /*
3480  * Save off strings in case the hint extension gets destroyed
3481  * while we are notifying the watchers.
3482  */
3483  ast_copy_string(context_name,
3485  sizeof(context_name));
3486  ast_copy_string(exten_name, ast_get_extension_name(hint->exten),
3487  sizeof(exten_name));
3488  ast_str_set(hint_app, 0, "%s", ast_get_extension_app(hint->exten));
3489  ao2_unlock(hint);
3490 
3491  /* Check to see if update is necessary */
3492  if ((hint->last_presence_state == presence_state->state) &&
3493  ((hint->last_presence_subtype && presence_state->subtype &&
3494  !strcmp(hint->last_presence_subtype, presence_state->subtype)) ||
3495  (!hint->last_presence_subtype && !presence_state->subtype)) &&
3496  ((hint->last_presence_message && presence_state->message &&
3497  !strcmp(hint->last_presence_message, presence_state->message)) ||
3498  (!hint->last_presence_message && !presence_state->message))) {
3499  /* this update is the same as the last, do nothing */
3500  return;
3501  }
3502 
3503  /* update new values */
3506  hint->last_presence_state = presence_state->state;
3507  hint->last_presence_subtype = presence_state->subtype ? ast_strdup(presence_state->subtype) : NULL;
3508  hint->last_presence_message = presence_state->message ? ast_strdup(presence_state->message) : NULL;
3509 
3510  /* For general callbacks */
3511  cb_iter = ao2_iterator_init(statecbs, 0);
3512  for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3514  context_name,
3515  exten_name,
3516  state_cb->data,
3518  hint,
3519  NULL);
3520  }
3521  ao2_iterator_destroy(&cb_iter);
3522 
3523  /* For extension callbacks */
3524  cb_iter = ao2_iterator_init(hint->callbacks, 0);
3525  for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_cleanup(state_cb)) {
3527  context_name,
3528  exten_name,
3529  state_cb->data,
3531  hint,
3532  NULL);
3533  }
3534  ao2_iterator_destroy(&cb_iter);
3535 }
3536 
3538 {
3539  struct ast_hint *hint;
3540  struct ast_str *hint_app;
3541 
3542  if (hint_change_message_type() != stasis_message_type(msg)) {
3543  return 0;
3544  }
3545 
3546  if (!(hint_app = ast_str_create(1024))) {
3547  return -1;
3548  }
3549 
3550  hint = stasis_message_data(msg);
3551 
3552  switch (reason) {
3554  device_state_notify_callbacks(hint, &hint_app);
3555  break;
3557  {
3558  char *presence_subtype = NULL;
3559  char *presence_message = NULL;
3560  int state;
3561 
3563  hint->exten, &presence_subtype, &presence_message);
3564  {
3565  struct ast_presence_state_message presence_state = {
3566  .state = state > 0 ? state : AST_PRESENCE_INVALID,
3567  .subtype = presence_subtype,
3568  .message = presence_message
3569  };
3570 
3571  presence_state_notify_callbacks(hint, &hint_app, &presence_state);
3572  }
3573 
3574  ast_free(presence_subtype);
3575  ast_free(presence_message);
3576  }
3577  break;
3578  }
3579 
3580  ast_free(hint_app);
3581  return 1;
3582 }
3583 
3584 static void device_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
3585 {
3586  struct ast_device_state_message *dev_state;
3587  struct ast_str *hint_app;
3588  struct ast_hintdevice *device;
3589  struct ast_hintdevice *cmpdevice;
3590  struct ao2_iterator *dev_iter;
3591  struct ao2_iterator auto_iter;
3592  struct ast_autohint *autohint;
3593  char *virtual_device;
3594  char *type;
3595  char *device_name;
3596 
3598  return;
3599  }
3600 
3601  if (hint_remove_message_type() == stasis_message_type(msg)) {
3602  /* The extension has already been destroyed */
3603  struct ast_state_cb *state_cb;
3604  struct ao2_iterator cb_iter;
3605  struct ast_hint *hint = stasis_message_data(msg);
3606 
3607  ao2_lock(hint);
3609  ao2_unlock(hint);
3610 
3611  cb_iter = ao2_iterator_init(hint->callbacks, 0);
3612  for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3614  hint->context_name,
3615  hint->exten_name,
3616  state_cb->data,
3618  hint,
3619  NULL);
3620  }
3621  ao2_iterator_destroy(&cb_iter);
3622  return;
3623  }
3624 
3626  return;
3627  }
3628 
3629  dev_state = stasis_message_data(msg);
3630  if (dev_state->eid) {
3631  /* ignore non-aggregate states */
3632  return;
3633  }
3634 
3635  if (ao2_container_count(hintdevices) == 0 && ao2_container_count(autohints) == 0) {
3636  /* There are no hints monitoring devices. */
3637  return;
3638  }
3639 
3640  hint_app = ast_str_create(1024);
3641  if (!hint_app) {
3642  return;
3643  }
3644 
3645  cmpdevice = ast_alloca(sizeof(*cmpdevice) + strlen(dev_state->device));
3646  strcpy(cmpdevice->hintdevice, dev_state->device);
3647 
3648  ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
3649 
3650  /* Initially we find all hints for the device and notify them */
3651  dev_iter = ao2_t_callback(hintdevices,
3654  cmpdevice,
3655  "find devices in container");
3656  if (dev_iter) {
3657  for (; (device = ao2_iterator_next(dev_iter)); ao2_t_ref(device, -1, "Next device")) {
3658  if (device->hint) {
3659  device_state_notify_callbacks(device->hint, &hint_app);
3660  }
3661  }
3662  ao2_iterator_destroy(dev_iter);
3663  }
3664 
3665  /* Second stage we look for any autohint contexts and if the device is not already in the hints
3666  * we create it.
3667  */
3668  type = ast_strdupa(dev_state->device);
3669  if (ast_strlen_zero(type)) {
3670  goto end;
3671  }
3672 
3673  /* Determine if this is a virtual/custom device or a real device */
3674  virtual_device = strchr(type, ':');
3675  device_name = strchr(type, '/');
3676  if (virtual_device && (!device_name || (virtual_device < device_name))) {
3677  device_name = virtual_device;
3678  }
3679 
3680  /* Invalid device state name - not a virtual/custom device and not a real device */
3681  if (ast_strlen_zero(device_name)) {
3682  goto end;
3683  }
3684 
3685  *device_name++ = '\0';
3686 
3687  auto_iter = ao2_iterator_init(autohints, 0);
3688  for (; (autohint = ao2_iterator_next(&auto_iter)); ao2_t_ref(autohint, -1, "Next autohint")) {
3689  if (ast_get_hint(NULL, 0, NULL, 0, NULL, autohint->context, device_name)) {
3690  continue;
3691  }
3692 
3693  /* The device has no hint in the context referenced by this autohint so create one */
3694  ast_add_extension(autohint->context, 0, device_name,
3695  PRIORITY_HINT, NULL, NULL, dev_state->device,
3696  ast_strdup(dev_state->device), ast_free_ptr, autohint->registrar);
3697 
3698  /* Since this hint was just created there are no watchers, so we don't need to notify anyone */
3699  }
3700  ao2_iterator_destroy(&auto_iter);
3701 
3702 end:
3704  ast_free(hint_app);
3705  return;
3706 }
3707 
3708 /*!
3709  * \internal
3710  * \brief Destroy the given state callback object.
3711  *
3712  * \param doomed State callback to destroy.
3713  *
3714  * \return Nothing
3715  */
3716 static void destroy_state_cb(void *doomed)
3717 {
3718  struct ast_state_cb *state_cb = doomed;
3719 
3720  if (state_cb->destroy_cb) {
3721  state_cb->destroy_cb(state_cb->id, state_cb->data);
3722  }
3723 }
3724 
3725 /*!
3726  * \internal
3727  * \brief Add watcher for extension states with destructor
3728  */
3729 static int extension_state_add_destroy(const char *context, const char *exten,
3731 {
3732  struct ast_hint *hint;
3733  struct ast_state_cb *state_cb;
3734  struct ast_exten *e;
3735  int id;
3736 
3737  /* If there's no context and extension: add callback to statecbs list */
3738  if (!context && !exten) {
3739  /* Prevent multiple adds from adding the same change_cb at the same time. */
3740  ao2_lock(statecbs);
3741 
3742  /* Remove any existing change_cb. */
3743  ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
3744 
3745  /* Now insert the change_cb */
3746  if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
3747  ao2_unlock(statecbs);
3748  return -1;
3749  }
3750  state_cb->id = 0;
3751  state_cb->change_cb = change_cb;
3752  state_cb->destroy_cb = destroy_cb;
3753  state_cb->data = data;
3754  state_cb->extended = extended;
3755  ao2_link(statecbs, state_cb);
3756 
3757  ao2_ref(state_cb, -1);
3758  ao2_unlock(statecbs);
3759  return 0;
3760  }
3761 
3762  if (!context || !exten)
3763  return -1;
3764 
3765  /* This callback type is for only one hint, so get the hint */
3766  e = ast_hint_extension(NULL, context, exten);
3767  if (!e) {
3768  return -1;
3769  }
3770 
3771  /* If this is a pattern, dynamically create a new extension for this
3772  * particular match. Note that this will only happen once for each
3773  * individual extension, because the pattern will no longer match first.
3774  */
3775  if (e->exten[0] == '_') {
3776  ao2_lock(hints);
3777  ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
3778  e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
3779  e->registrar);
3780  ao2_unlock(hints);
3781  e = ast_hint_extension(NULL, context, exten);
3782  if (!e || e->exten[0] == '_') {
3783  return -1;
3784  }
3785  }
3786 
3787  /* Find the hint in the hints container */
3788  ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
3789  hint = ao2_find(hints, e, 0);
3790  if (!hint) {
3791  ao2_unlock(hints);
3792  return -1;
3793  }
3794 
3795  /* Now insert the callback in the callback list */
3796  if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
3797  ao2_ref(hint, -1);
3798  ao2_unlock(hints);
3799  return -1;
3800  }
3801  do {
3802  id = stateid++; /* Unique ID for this callback */
3803  /* Do not allow id to ever be -1 or 0. */
3804  } while (id == -1 || id == 0);
3805  state_cb->id = id;
3806  state_cb->change_cb = change_cb; /* Pointer to callback routine */
3807  state_cb->destroy_cb = destroy_cb;
3808  state_cb->data = data; /* Data for the callback */
3809  state_cb->extended = extended;
3810  ao2_link(hint->callbacks, state_cb);
3811 
3812  ao2_ref(state_cb, -1);
3813  ao2_ref(hint, -1);
3814  ao2_unlock(hints);
3815 
3816  return id;
3817 }
3818 
3819 int ast_extension_state_add_destroy(const char *context, const char *exten,
3820  ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
3821 {
3822  return extension_state_add_destroy(context, exten, change_cb, destroy_cb, data, 0);
3823 }
3824 
3825 int ast_extension_state_add(const char *context, const char *exten,
3826  ast_state_cb_type change_cb, void *data)
3827 {
3828  return extension_state_add_destroy(context, exten, change_cb, NULL, data, 0);
3829 }
3830 
3831 int ast_extension_state_add_destroy_extended(const char *context, const char *exten,
3832  ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
3833 {
3834  return extension_state_add_destroy(context, exten, change_cb, destroy_cb, data, 1);
3835 }
3836 
3837 int ast_extension_state_add_extended(const char *context, const char *exten,
3838  ast_state_cb_type change_cb, void *data)
3839 {
3840  return extension_state_add_destroy(context, exten, change_cb, NULL, data, 1);
3841 }
3842 
3843 /*! \brief Find Hint by callback id */
3844 static int find_hint_by_cb_id(void *obj, void *arg, int flags)
3845 {
3846  struct ast_state_cb *state_cb;
3847  const struct ast_hint *hint = obj;
3848  int *id = arg;
3849 
3850  if ((state_cb = ao2_find(hint->callbacks, id, 0))) {
3851  ao2_ref(state_cb, -1);
3852  return CMP_MATCH | CMP_STOP;
3853  }
3854 
3855  return 0;
3856 }
3857 
3859 {
3860  struct ast_state_cb *p_cur;
3861  int ret = -1;
3862 
3863  if (!id) { /* id == 0 is a callback without extension */
3864  if (!change_cb) {
3865  return ret;
3866  }
3867  p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK);
3868  if (p_cur) {
3869  ret = 0;
3870  ao2_ref(p_cur, -1);
3871  }
3872  } else { /* callback with extension, find the callback based on ID */
3873  struct ast_hint *hint;
3874 
3875  ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
3876  hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
3877  if (hint) {
3878  p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
3879  if (p_cur) {
3880  ret = 0;
3881  ao2_ref(p_cur, -1);
3882  }
3883  ao2_ref(hint, -1);
3884  }
3885  ao2_unlock(hints);
3886  }
3887 
3888  return ret;
3889 }
3890 
3891 static int hint_id_cmp(void *obj, void *arg, int flags)
3892 {
3893  const struct ast_state_cb *cb = obj;
3894  int *id = arg;
3895 
3896  return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0;
3897 }
3898 
3899 /*!
3900  * \internal
3901  * \brief Destroy the given hint object.
3902  *
3903  * \param obj Hint to destroy.
3904  *
3905  * \return Nothing
3906  */
3907 static void destroy_hint(void *obj)
3908 {
3909  struct ast_hint *hint = obj;
3910  int i;
3911 
3912  ao2_cleanup(hint->callbacks);
3913 
3914  for (i = 0; i < AST_VECTOR_SIZE(&hint->devices); i++) {
3915  char *device = AST_VECTOR_GET(&hint->devices, i);
3916  ast_free(device);
3917  }
3918  AST_VECTOR_FREE(&hint->devices);
3921 }
3922 
3923 /*! \brief Publish a hint removed event */
3924 static int publish_hint_remove(struct ast_hint *hint)
3925 {
3926  struct stasis_message *message;
3927 
3928  if (!hint_remove_message_type()) {
3929  return -1;
3930  }
3931 
3932  if (!(message = stasis_message_create(hint_remove_message_type(), hint))) {
3933  ao2_ref(hint, -1);
3934  return -1;
3935  }
3936 
3938 
3939  ao2_ref(message, -1);
3940 
3941  return 0;
3942 }
3943 
3944 /*! \brief Remove hint from extension */
3945 static int ast_remove_hint(struct ast_exten *e)
3946 {
3947  /* Cleanup the Notifys if hint is removed */
3948  struct ast_hint *hint;
3949 
3950  if (!e) {
3951  return -1;
3952  }
3953 
3954  hint = ao2_find(hints, e, OBJ_UNLINK);
3955  if (!hint) {
3956  return -1;
3957  }
3958 
3959  remove_hintdevice(hint);
3960 
3961  /*
3962  * The extension is being destroyed so we must save some
3963  * information to notify that the extension is deactivated.
3964  */
3965  ao2_lock(hint);
3968  sizeof(hint->context_name));
3970  sizeof(hint->exten_name));
3971  hint->exten = NULL;
3972  ao2_unlock(hint);
3973 
3974  publish_hint_remove(hint);
3975 
3976  ao2_ref(hint, -1);
3977 
3978  return 0;
3979 }
3980 
3981 /*! \brief Add hint to hint list, check initial extension state */
3982 static int ast_add_hint(struct ast_exten *e)
3983 {
3984  struct ast_hint *hint_new;
3985  struct ast_hint *hint_found;
3986  char *message = NULL;
3987  char *subtype = NULL;
3988  int presence_state;
3989 
3990  if (!e) {
3991  return -1;
3992  }
3993 
3994  /*
3995  * We must create the hint we wish to add before determining if
3996  * it is already in the hints container to avoid possible
3997  * deadlock when getting the current extension state.
3998  */
3999  hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint);
4000  if (!hint_new) {
4001  return -1;
4002  }
4003  AST_VECTOR_INIT(&hint_new->devices, 8);
4004 
4005  /* Initialize new hint. */
4007  if (!hint_new->callbacks) {
4008  ao2_ref(hint_new, -1);
4009  return -1;
4010  }
4011  hint_new->exten = e;
4012  if (strstr(e->app, "${") && e->exten[0] == '_') {
4013  /* The hint is dynamic and hasn't been evaluted yet */
4014  hint_new->laststate = AST_DEVICE_INVALID;
4016  } else {
4017  hint_new->laststate = ast_extension_state2(e, NULL);
4018  if ((presence_state = extension_presence_state_helper(e, &subtype, &message)) > 0) {
4019  hint_new->last_presence_state = presence_state;
4020  hint_new->last_presence_subtype = subtype;
4021  hint_new->last_presence_message = message;
4022  }
4023  }
4024 
4025  /* Prevent multiple add hints from adding the same hint at the same time. */
4026  ao2_lock(hints);
4027 
4028  /* Search if hint exists, do nothing */
4029  hint_found = ao2_find(hints, e, 0);
4030  if (hint_found) {
4031  ao2_ref(hint_found, -1);
4032  ao2_unlock(hints);
4033  ao2_ref(hint_new, -1);
4034  ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n",
4036  return -1;
4037  }
4038 
4039  /* Add new hint to the hints container */
4040  ast_debug(2, "HINTS: Adding hint %s: %s\n",
4042  ao2_link(hints, hint_new);
4043  if (add_hintdevice(hint_new, ast_get_extension_app(e))) {
4044  ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
4047  }
4048 
4049  /* if not dynamic */
4050  if (!(strstr(e->app, "${") && e->exten[0] == '_')) {
4051  struct ast_state_cb *state_cb;
4052  struct ao2_iterator cb_iter;
4053 
4054  /* For general callbacks */
4055  cb_iter = ao2_iterator_init(statecbs, 0);
4056  for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
4060  state_cb->data,
4062  hint_new,
4063  NULL);
4064  }
4065  ao2_iterator_destroy(&cb_iter);
4066  }
4067  ao2_unlock(hints);
4068  ao2_ref(hint_new, -1);
4069 
4070  return 0;
4071 }
4072 
4073 /*! \brief Publish a hint changed event */
4074 static int publish_hint_change(struct ast_hint *hint, struct ast_exten *ne)
4075 {
4076  struct stasis_message *message;
4077 
4078  if (!hint_change_message_type()) {
4079  return -1;
4080  }
4081 
4082  if (!(message = stasis_message_create(hint_change_message_type(), hint))) {
4083  ao2_ref(hint, -1);
4084  return -1;
4085  }
4086 
4089 
4090  ao2_ref(message, -1);
4091 
4092  return 0;
4093 }
4094 
4095 /*! \brief Change hint for an extension */
4096 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
4097 {
4098  struct ast_hint *hint;
4099 
4100  if (!oe || !ne) {
4101  return -1;
4102  }
4103 
4104  ao2_lock(hints);/* Locked to hold off others while we move the hint around. */
4105 
4106  /*
4107  * Unlink the hint from the hints container as the extension
4108  * name (which is the hash value) could change.
4109  */
4110  hint = ao2_find(hints, oe, OBJ_UNLINK);
4111  if (!hint) {
4112  ao2_unlock(hints);
4114  return -1;
4115  }
4116 
4117  remove_hintdevice(hint);
4118 
4119  /* Update the hint and put it back in the hints container. */
4120  ao2_lock(hint);
4121  hint->exten = ne;
4122 
4123  ao2_unlock(hint);
4124 
4125  ao2_link(hints, hint);
4126  if (add_hintdevice(hint, ast_get_extension_app(ne))) {
4127  ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
4130  }
4131  ao2_unlock(hints);
4132 
4133  publish_hint_change(hint, ne);
4134 
4135  ao2_ref(hint, -1);
4136 
4137  return 0;
4138 }
4139 
4140 /*! \brief Get hint for channel */
4141 int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
4142 {
4143  struct ast_exten *e = ast_hint_extension(c, context, exten);
4144 
4145  if (e) {
4146  if (hint)
4147  ast_copy_string(hint, ast_get_extension_app(e), hintsize);
4148  if (name) {
4149  const char *tmp = ast_get_extension_app_data(e);
4150  if (tmp)
4151  ast_copy_string(name, tmp, namesize);
4152  }
4153  return -1;
4154  }
4155  return 0;
4156 }
4157 
4158 /*! \brief Get hint for channel */
4159 int ast_str_get_hint(struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten)
4160 {
4161  struct ast_exten *e = ast_hint_extension(c, context, exten);
4162 
4163  if (!e) {
4164  return 0;
4165  }
4166 
4167  if (hint) {
4168  ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
4169  }
4170  if (name) {
4171  const char *tmp = ast_get_extension_app_data(e);
4172  if (tmp) {
4173  ast_str_set(name, namesize, "%s", tmp);
4174  }
4175  }
4176  return -1;
4177 }
4178 
4179 int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
4180 {
4181  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
4182 }
4183 
4184 int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
4185 {
4186  return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
4187 }
4188 
4189 int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
4190 {
4191  return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
4192 }
4193 
4194 int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
4195 {
4196  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
4197 }
4198 
4199 int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
4200 {
4201  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
4202 }
4203 
4204 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)
4205 {
4206  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
4207 }
4208 
4209 void ast_pbx_h_exten_run(struct ast_channel *chan, const char *context)
4210 {
4211  int autoloopflag;
4212  int found;
4213  int spawn_error;
4214 
4215  ast_channel_lock(chan);
4216 
4217  /*
4218  * Make sure that the channel is marked as hungup since we are
4219  * going to run the h exten on it.
4220  */
4222 
4223  /* Set h exten location */
4224  if (context != ast_channel_context(chan)) {
4225  ast_channel_context_set(chan, context);
4226  }
4227  ast_channel_exten_set(chan, "h");
4228  ast_channel_priority_set(chan, 1);
4229 
4230  /* Save autoloop flag */
4231  autoloopflag = ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
4233  ast_channel_unlock(chan);
4234 
4235  for (;;) {
4236  spawn_error = ast_spawn_extension(chan, ast_channel_context(chan),
4238  S_COR(ast_channel_caller(chan)->id.number.valid,
4239  ast_channel_caller(chan)->id.number.str, NULL), &found, 1);
4240 
4241  ast_channel_lock(chan);
4242  if (spawn_error) {
4243  /* The code after the loop needs the channel locked. */
4244  break;
4245  }
4247  ast_channel_unlock(chan);
4248  }
4249  if (found && spawn_error) {
4250  /* Something bad happened, or a hangup has been requested. */
4251  ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n",
4253  ast_channel_priority(chan), ast_channel_name(chan));
4254  ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n",
4256  ast_channel_priority(chan), ast_channel_name(chan));
4257  }
4258 
4259  /* An "h" exten has been run, so indicate that one has been run. */
4261 
4262  /* Restore autoloop flag */
4264  ast_channel_unlock(chan);
4265 }
4266 
4267 /*! helper function to set extension and priority */
4268 void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
4269 {
4270  ast_channel_lock(c);
4271  ast_channel_exten_set(c, exten);
4272  ast_channel_priority_set(c, pri);
4273  ast_channel_unlock(c);
4274 }
4275 
4276 /*!
4277  * \brief collect digits from the channel into the buffer.
4278  * \param c, buf, buflen, pos
4279  * \param waittime is in milliseconds
4280  * \retval 0 on timeout or done.
4281  * \retval -1 on error.
4282 */
4283 static int collect_digits(struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
4284 {
4285  int digit;
4286 
4287  buf[pos] = '\0'; /* make sure it is properly terminated */
4288  while (ast_matchmore_extension(c, ast_channel_context(c), buf, 1,
4289  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4290  /* As long as we're willing to wait, and as long as it's not defined,
4291  keep reading digits until we can't possibly get a right answer anymore. */
4292  digit = ast_waitfordigit(c, waittime);
4294  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
4295  } else {
4296  if (!digit) /* No entry */
4297  break;
4298  if (digit < 0) /* Error, maybe a hangup */
4299  return -1;
4300  if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
4301  buf[pos++] = digit;
4302  buf[pos] = '\0';
4303  }
4304  waittime = ast_channel_pbx(c)->dtimeoutms;
4305  }
4306  }
4307  return 0;
4308 }
4309 
4311  struct ast_pbx_args *args)
4312 {
4313  int found = 0; /* set if we find at least one match */
4314  int res = 0;
4315  int autoloopflag;
4316  int error = 0; /* set an error conditions */
4317  struct ast_pbx *pbx;
4318  ast_callid callid;
4319 
4320  /* A little initial setup here */
4321  if (ast_channel_pbx(c)) {
4322  ast_log(LOG_WARNING, "%s already has PBX structure??\n", ast_channel_name(c));
4323  /* XXX and now what ? */
4325  }
4326  if (!(pbx = ast_calloc(1, sizeof(*pbx)))) {
4327  return AST_PBX_FAILED;
4328  }
4329 
4330  callid = ast_read_threadstorage_callid();
4331  /* If the thread isn't already associated with a callid, we should create that association. */
4332  if (!callid) {
4333  /* Associate new PBX thread with the channel call id if it is availble.
4334  * If not, create a new one instead.
4335  */
4336  callid = ast_channel_callid(c);
4337  if (!callid) {
4338  callid = ast_create_callid();
4339  if (callid) {
4340  ast_channel_lock(c);
4341  ast_channel_callid_set(c, callid);
4342  ast_channel_unlock(c);
4343  }
4344  }
4346  callid = 0;
4347  }
4348 
4349  ast_channel_pbx_set(c, pbx);
4350  /* Set reasonable defaults */
4351  ast_channel_pbx(c)->rtimeoutms = 10000;
4352  ast_channel_pbx(c)->dtimeoutms = 5000;
4353 
4354  ast_channel_lock(c);
4355  autoloopflag = ast_test_flag(ast_channel_flags(c), AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */
4357  ast_channel_unlock(c);
4358 
4360  /* If not successful fall back to 's' - but only if there is no given exten */
4361  ast_verb(2, "Starting %s at %s,%s,%d failed so falling back to exten 's'\n", ast_channel_name(c), ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c));
4362  /* XXX the original code used the existing priority in the call to
4363  * ast_exists_extension(), and reset it to 1 afterwards.
4364  * I believe the correct thing is to set it to 1 immediately.
4365  */
4366  set_ext_pri(c, "s", 1);
4367  }
4368 
4369  for (;;) {
4370  char dst_exten[256]; /* buffer to accumulate digits */
4371  int pos = 0; /* XXX should check bounds */
4372  int digit = 0;
4373  int invalid = 0;
4374  int timeout = 0;
4375 
4376  /* No digits pressed yet */
4377  dst_exten[pos] = '\0';
4378 
4379  /* loop on priorities in this context/exten */
4381  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL),
4382  &found, 1))) {
4383 
4384  if (!ast_check_hangup(c)) {
4386  continue;
4387  }
4388 
4389  /* Check softhangup flags. */
4391  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
4392  continue;
4393  }
4395  if (ast_exists_extension(c, ast_channel_context(c), "T", 1,
4396  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4397  set_ext_pri(c, "T", 1);
4398  /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4399  memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
4400  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
4401  continue;
4402  } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4403  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4404  raise_exception(c, "ABSOLUTETIMEOUT", 1);
4405  /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4406  memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
4407  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
4408  continue;
4409  }
4410 
4411  /* Call timed out with no special extension to jump to. */
4412  error = 1;
4413  break;
4414  }
4415  ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
4417  error = 1;
4418  break;
4419  } /* end while - from here on we can use 'break' to go out */
4420  if (found && res) {
4421  /* Something bad happened, or a hangup has been requested. */
4422  if (strchr("0123456789ABCDEF*#", res)) {
4423  ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
4424  pos = 0;
4425  dst_exten[pos++] = digit = res;
4426  dst_exten[pos] = '\0';
4427  } else if (res == AST_PBX_INCOMPLETE) {
4428  ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_name(c));
4429  ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_name(c));
4430 
4431  /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
4433  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4434  invalid = 1;
4435  } else {
4436  ast_copy_string(dst_exten, ast_channel_exten(c), sizeof(dst_exten));
4437  digit = 1;
4438  pos = strlen(dst_exten);
4439  }
4440  } else {
4441  ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_name(c));
4442  ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_name(c));
4443 
4444  if ((res == AST_PBX_ERROR)
4445  && ast_exists_extension(c, ast_channel_context(c), "e", 1,
4446  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4447  /* if we are already on the 'e' exten, don't jump to it again */
4448  if (!strcmp(ast_channel_exten(c), "e")) {
4449  ast_verb(2, "Spawn extension (%s, %s, %d) exited ERROR while already on 'e' exten on '%s'\n", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_name(c));
4450  error = 1;
4451  } else {
4452  raise_exception(c, "ERROR", 1);
4453  continue;
4454  }
4455  }
4456 
4458  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
4459  continue;
4460  }
4462  if (ast_exists_extension(c, ast_channel_context(c), "T", 1,
4463  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4464  set_ext_pri(c, "T", 1);
4465  /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4466  memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
4467  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
4468  continue;
4469  } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4470  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4471  raise_exception(c, "ABSOLUTETIMEOUT", 1);
4472  /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4473  memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
4474  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
4475  continue;
4476  }
4477  /* Call timed out with no special extension to jump to. */
4478  }
4479  error = 1;
4480  break;
4481  }
4482  }
4483  if (error)
4484  break;
4485 
4486  /*!\note
4487  * We get here on a failure of some kind: non-existing extension or
4488  * hangup. We have options, here. We can either catch the failure
4489  * and continue, or we can drop out entirely. */
4490 
4491  if (invalid
4492  || (ast_strlen_zero(dst_exten) &&
4494  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL)))) {
4495  /*!\note
4496  * If there is no match at priority 1, it is not a valid extension anymore.
4497  * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
4498  * neither exist.
4499  */
4500  if (ast_exists_extension(c, ast_channel_context(c), "i", 1,
4501  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4502  ast_verb(3, "Channel '%s' sent to invalid extension: context,exten,priority=%s,%s,%d\n",
4504  pbx_builtin_setvar_helper(c, "INVALID_EXTEN", ast_channel_exten(c));
4505  set_ext_pri(c, "i", 1);
4506  } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4507  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4508  raise_exception(c, "INVALID", 1);
4509  } else {
4510  ast_log(LOG_WARNING, "Channel '%s' sent to invalid extension but no invalid handler: context,exten,priority=%s,%s,%d\n",
4512  error = 1; /* we know what to do with it */
4513  break;
4514  }
4516  /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
4517  ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
4518  } else { /* keypress received, get more digits for a full extension */
4519  int waittime = 0;
4520  if (digit)
4521  waittime = ast_channel_pbx(c)->dtimeoutms;
4522  else if (!autofallthrough)
4523  waittime = ast_channel_pbx(c)->rtimeoutms;
4524  if (!waittime) {
4525  const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
4526  if (!status)
4527  status = "UNKNOWN";
4528  ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", ast_channel_name(c), status);
4529  if (!strcasecmp(status, "CONGESTION"))
4530  res = indicate_congestion(c, "10");
4531  else if (!strcasecmp(status, "CHANUNAVAIL"))
4532  res = indicate_congestion(c, "10");
4533  else if (!strcasecmp(status, "BUSY"))
4534  res = indicate_busy(c, "10");
4535  error = 1; /* XXX disable message */
4536  break; /* exit from the 'for' loop */
4537  }
4538 
4539  if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
4540  break;
4541  if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
4542  timeout = 1;
4543  if (!timeout
4544  && ast_exists_extension(c, ast_channel_context(c), dst_exten, 1,
4545  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) { /* Prepare the next cycle */
4546  set_ext_pri(c, dst_exten, 1);
4547  } else {
4548  /* No such extension */
4549  if (!timeout && !ast_strlen_zero(dst_exten)) {
4550  /* An invalid extension */
4551  if (ast_exists_extension(c, ast_channel_context(c), "i", 1,
4552  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4553  ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, ast_channel_context(c), ast_channel_name(c));
4554  pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
4555  set_ext_pri(c, "i", 1);
4556  } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4557  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4558  raise_exception(c, "INVALID", 1);
4559  } else {
4561  "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
4562  dst_exten, ast_channel_context(c));
4563  found = 1; /* XXX disable message */
4564  break;
4565  }
4566  } else {
4567  /* A simple timeout */
4568  if (ast_exists_extension(c, ast_channel_context(c), "t", 1,
4569  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4570  ast_verb(3, "Timeout on %s\n", ast_channel_name(c));
4571  set_ext_pri(c, "t", 1);
4572  } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4573  S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4574  raise_exception(c, "RESPONSETIMEOUT", 1);
4575  } else {
4577  "Timeout, but no rule 't' or 'e' in context '%s'\n",
4578  ast_channel_context(c));
4579  found = 1; /* XXX disable message */
4580  break;
4581  }
4582  }
4583  }
4584  }
4585  }
4586 
4587  if (!found && !error) {
4588  ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", ast_channel_name(c));
4589  }
4590 
4591  if (!args || !args->no_hangup_chan) {
4594  && ast_exists_extension(c, ast_channel_context(c), "h", 1,
4595  S_COR(ast_channel_caller(c)->id.number.valid,
4596  ast_channel_caller(c)->id.number.str, NULL))) {
4598  }
4600  }
4601 
4602  ast_channel_lock(c);
4604  ast_clear_flag(ast_channel_flags(c), AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
4605  ast_channel_unlock(c);
4608 
4609  if (!args || !args->no_hangup_chan) {
4610  ast_hangup(c);
4611  }
4612 
4613  return AST_PBX_SUCCESS;
4614 }
4615 
4616 /*!
4617  * \brief Increase call count for channel
4618  * \retval 0 on success
4619  * \retval non-zero if a configured limit (maxcalls, maxload, minmemfree) was reached
4620 */
4621 static int increase_call_count(const struct ast_channel *c)
4622 {
4623  int failed = 0;
4624  double curloadavg;
4625 #if defined(HAVE_SYSINFO)
4626  struct sysinfo sys_info;
4627 #endif
4628 
4630  if (ast_option_maxcalls) {
4631  if (countcalls >= ast_option_maxcalls) {
4632  ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", ast_option_maxcalls, ast_channel_name(c));
4633  failed = -1;
4634  }
4635  }
4636  if (ast_option_maxload) {
4637  getloadavg(&curloadavg, 1);
4638  if (curloadavg >= ast_option_maxload) {
4639  ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", ast_option_maxload, ast_channel_name(c), curloadavg);
4640  failed = -1;
4641  }
4642  }
4643 #if defined(HAVE_SYSINFO)
4644  if (option_minmemfree) {
4645  /* Make sure that the free system memory is above the configured low watermark */
4646  if (!sysinfo(&sys_info)) {
4647  /* Convert the amount of available RAM from mem_units to MB. The calculation
4648  * was done this way to avoid overflow problems */
4649  uint64_t curfreemem = sys_info.freeram + sys_info.bufferram;
4650  curfreemem *= sys_info.mem_unit;
4651  curfreemem /= 1024 * 1024;
4652  if (curfreemem < option_minmemfree) {
4653  ast_log(LOG_WARNING, "Available system memory (~%" PRIu64 "MB) is below the configured low watermark (%ldMB)\n",
4654  curfreemem, option_minmemfree);
4655  failed = -1;
4656  }
4657  }
4658  }
4659 #endif
4660 
4661  if (!failed) {
4662  countcalls++;
4663  totalcalls++;
4664  }
4666 
4667  return failed;
4668 }
4669 
4670 static void decrease_call_count(void)
4671 {
4673  if (countcalls > 0)
4674  countcalls--;
4676 }
4677 
4678 static void destroy_exten(struct ast_exten *e)
4679 {
4680  if (e->priority == PRIORITY_HINT)
4681  ast_remove_hint(e);
4682 
4683  if (e->peer_table)
4685  if (e->peer_label_table)
4687  if (e->datad)
4688  e->datad(e->data);
4689  ast_free(e);
4690 }
4691 
4692 static void *pbx_thread(void *data)
4693 {
4694  /* Oh joyeous kernel, we're a new thread, with nothing to do but
4695  answer this channel and get it going.
4696  */
4697  /* NOTE:
4698  The launcher of this function _MUST_ increment 'countcalls'
4699  before invoking the function; it will be decremented when the
4700  PBX has finished running on the channel
4701  */
4702  struct ast_channel *c = data;
4703 
4704  __ast_pbx_run(c, NULL);
4706 
4707  pthread_exit(NULL);
4708 
4709  return NULL;
4710 }
4711 
4713 {
4714  pthread_t t;
4715 
4716  if (!c) {
4717  ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
4718  return AST_PBX_FAILED;
4719  }
4720 
4722  ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
4723  return AST_PBX_FAILED;
4724  }
4725 
4726  if (increase_call_count(c))
4727  return AST_PBX_CALL_LIMIT;
4728 
4729  /* Start a new thread, and get something handling this channel. */
4731  ast_log(LOG_WARNING, "Failed to create new channel thread\n");
4733  return AST_PBX_FAILED;
4734  }
4735 
4736  return AST_PBX_SUCCESS;
4737 }
4738 
4740 {
4741  enum ast_pbx_result res = AST_PBX_SUCCESS;
4742 
4744  ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
4745  return AST_PBX_FAILED;
4746  }
4747 
4748  if (increase_call_count(c)) {
4749  return AST_PBX_CALL_LIMIT;
4750  }
4751 
4752  res = __ast_pbx_run(c, args);
4753 
4755 
4756  return res;
4757 }
4758 
4760 {
4761  return ast_pbx_run_args(c, NULL);
4762 }
4763 
4765 {
4766  return countcalls;
4767 }
4768 
4770 {
4771  return totalcalls;
4772 }
4773 
4775 {
4776  int oldval = autofallthrough;
4777  autofallthrough = newval;
4778  return oldval;
4779 }
4780 
4782 {
4783  int oldval = extenpatternmatchnew;
4784  extenpatternmatchnew = newval;
4785  return oldval;
4786 }
4787 
4788 void pbx_set_overrideswitch(const char *newval)
4789 {
4790  if (overrideswitch) {
4791  ast_free(overrideswitch);
4792  }
4793  if (!ast_strlen_zero(newval)) {
4794  overrideswitch = ast_strdup(newval);
4795  } else {
4796  overrideswitch = NULL;
4797  }
4798 }
4799 
4800 /*!
4801  * \brief lookup for a context with a given name,
4802  * \retval found context or NULL if not found.
4803  */
4804 static struct ast_context *find_context(const char *context)
4805 {
4806  struct fake_context item;
4807 
4808  ast_copy_string(item.name, context, sizeof(item.name));
4809 
4810  return ast_hashtab_lookup(contexts_table, &item);
4811 }
4812 
4813 /*!
4814  * \brief lookup for a context with a given name,
4815  * \retval with conlock held if found.
4816  * \retval NULL if not found.
4817  */
4818 static struct ast_context *find_context_locked(const char *context)
4819 {
4820  struct ast_context *c;
4821  struct fake_context item;
4822 
4823  ast_copy_string(item.name, context, sizeof(item.name));
4824 
4826  c = ast_hashtab_lookup(contexts_table, &item);
4827  if (!c) {
4829  }
4830 
4831  return c;
4832 }
4833 
4834 /*!
4835  * \brief Remove included contexts.
4836  * This function locks contexts list by &conlist, search for the right context
4837  * structure, leave context list locked and call ast_context_remove_include2
4838  * which removes include, unlock contexts list and return ...
4839  */
4840 int ast_context_remove_include(const char *context, const char *include, const char *registrar)
4841 {
4842  int ret = -1;
4843  struct ast_context *c;
4844 
4845  c = find_context_locked(context);
4846  if (c) {
4847  /* found, remove include from this context ... */
4848  ret = ast_context_remove_include2(c, include, registrar);
4850  }
4851  return ret;
4852 }
4853 
4854 /*!
4855  * \brief Locks context, remove included contexts, unlocks context.
4856  * When we call this function, &conlock lock must be locked, because when
4857  * we giving *con argument, some process can remove/change this context
4858  * and after that there can be segfault.
4859  *
4860  * \retval 0 on success.
4861  * \retval -1 on failure.
4862  */
4863 int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
4864 {
4865  int ret = -1;
4866  int idx;
4867 
4868  ast_wrlock_context(con);
4869 
4870  /* find our include */
4871  for (idx = 0; idx < ast_context_includes_count(con); idx++) {
4872  struct ast_include *i = AST_VECTOR_GET(&con->includes, idx);
4873 
4874  if (!strcmp(ast_get_include_name(i), include) &&
4875  (!registrar || !strcmp(ast_get_include_registrar(i), registrar))) {
4876 
4877  /* remove from list */
4878  ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
4879  AST_VECTOR_REMOVE_ORDERED(&con->includes, idx);
4880 
4881  /* free include and return */
4882  include_free(i);
4883  ret = 0;
4884  break;
4885  }
4886  }
4887 
4888  ast_unlock_context(con);
4889 
4890  return ret;
4891 }
4892 
4893 /*!
4894  * \note This function locks contexts list by &conlist, search for the rigt context
4895  * structure, leave context list locked and call ast_context_remove_switch2
4896  * which removes switch, unlock contexts list and return ...
4897  */
4898 int ast_context_remove_switch(const char *context, const char *sw, const char *data, const char *registrar)
4899 {
4900  int ret = -1; /* default error return */
4901  struct ast_context *c;
4902 
4903  c = find_context_locked(context);
4904  if (c) {
4905  /* remove switch from this context ... */
4906  ret = ast_context_remove_switch2(c, sw, data, registrar);
4908  }
4909  return ret;
4910 }
4911 
4912 /*!
4913  * \brief This function locks given context, removes switch, unlock context and
4914  * return.
4915  * \note When we call this function, &conlock lock must be locked, because when
4916  * we giving *con argument, some process can remove/change this context
4917  * and after that there can be segfault.
4918  *
4919  */
4920 int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
4921 {
4922  int idx;
4923  int ret = -1;
4924 
4925  ast_wrlock_context(con);
4926 
4927  /* walk switches */
4928  for (idx = 0; idx < ast_context_switches_count(con); idx++) {
4929  struct ast_sw *i = AST_VECTOR_GET(&con->alts, idx);
4930 
4931  if (!strcmp(ast_get_switch_name(i), sw) &&
4932  !strcmp(ast_get_switch_data(i), data) &&
4933  (!registrar || !strcmp(ast_get_switch_registrar(i), registrar))) {
4934 
4935  /* found, remove from list */
4936  ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
4937  AST_VECTOR_REMOVE_ORDERED(&con->alts, idx);
4938 
4939  /* free switch and return */
4940  sw_free(i);
4941  ret = 0;
4942  break;
4943  }
4944  }
4945 
4946  ast_unlock_context(con);
4947 
4948  return ret;
4949 }
4950 
4951 /*! \note This function will lock conlock. */
4952 int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
4953 {
4954  return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar);
4955 }
4956 
4957 int ast_context_remove_extension_callerid(const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar)
4958 {
4959  int ret = -1; /* default error return */
4960  struct ast_context *c;
4961 
4962  c = find_context_locked(context);
4963  if (c) { /* ... remove extension ... */
4964  ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid,
4965  matchcallerid, registrar, 0);
4967  }
4968 
4969  return ret;
4970 }
4971 
4972 /*!
4973  * \brief This functionc locks given context, search for the right extension and
4974  * fires out all peer in this extensions with given priority. If priority
4975  * is set to 0, all peers are removed. After that, unlock context and
4976  * return.
4977  * \note When do you want to call this function, make sure that &conlock is locked,
4978  * because some process can handle with your *con context before you lock
4979  * it.
4980  *
4981  */
4982 int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
4983 {
4984  return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked);
4985 }
4986 
4987 int ast_context_remove_extension_callerid2(struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked)
4988 {
4989  struct ast_exten *exten, *prev_exten = NULL;
4990  struct ast_exten *peer;
4991  struct ast_exten ex, *exten2, *exten3;
4992  char dummy_name[1024];
4993  char dummy_cid[1024];
4994  struct ast_exten *previous_peer = NULL;
4995  struct ast_exten *next_peer = NULL;
4996  int found = 0;
4997 
4998  if (!already_locked)
4999  ast_wrlock_context(con);
5000 
5001 #ifdef NEED_DEBUG
5002  ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
5003 #endif
5004 #ifdef CONTEXT_DEBUG
5005  check_contexts(__FILE__, __LINE__);
5006 #endif
5007  /* find this particular extension */
5008  ex.exten = dummy_name;
5009  ext_strncpy(dummy_name, extension, sizeof(dummy_name), 1);
5010  ex.matchcid = matchcallerid;
5011  if (callerid) {
5012  ex.cidmatch = dummy_cid;
5013  ext_strncpy(dummy_cid, callerid, sizeof(dummy_cid), 1);
5014  } else {
5015  ex.cidmatch = NULL;
5016  }
5017  exten = ast_hashtab_lookup(con->root_table, &ex);
5018  if (exten) {
5019  if (priority == 0) {
5020  exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
5021  if (!exten2)
5022  ast_log(LOG_ERROR,"Trying to delete the exten %s from context %s, but could not remove from the root_table\n", extension, con->name);
5023  if (con->pattern_tree) {
5024  struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
5025 
5026  if (x->exten) { /* this test for safety purposes */
5027  x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
5028  x->exten = 0; /* get rid of what will become a bad pointer */
5029  } else {
5030  ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
5031  }
5032  }
5033  } else {
5034  ex.priority = priority;
5035  exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
5036  if (exten2) {
5037  if (exten2->label) { /* if this exten has a label, remove that, too */
5038  exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
5039  if (!exten3) {
5040  ast_log(LOG_ERROR, "Did not remove this priority label (%d/%s) "
5041  "from the peer_label_table of context %s, extension %s!\n",
5042  priority, exten2->label, con->name, exten2->name);
5043  }
5044  }
5045 
5046  exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
5047  if (!exten3) {
5048  ast_log(LOG_ERROR, "Did not remove this priority (%d) from the "
5049  "peer_table of context %s, extension %s!\n",
5050  priority, con->name, exten2->name);
5051  }
5052  if (exten2 == exten && exten2->peer) {
5053  exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
5055  }
5056  if (ast_hashtab_size(exten->peer_table) == 0) {
5057  /* well, if the last priority of an exten is to be removed,
5058  then, the extension is removed, too! */
5059  exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
5060  if (!exten3) {
5061  ast_log(LOG_ERROR, "Did not remove this exten (%s) from the "
5062  "context root_table (%s) (priority %d)\n",
5063  exten->name, con->name, priority);
5064  }
5065  if (con->pattern_tree) {
5066  struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
5067  if (x->exten) { /* this test for safety purposes */
5068  x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
5069  x->exten = 0; /* get rid of what will become a bad pointer */
5070  }
5071  }
5072  }
5073  } else {
5074  ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
5075  priority, exten->name, con->name);
5076  }
5077  }
5078  } else {
5079  /* hmmm? this exten is not in this pattern tree? */
5080  ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
5081  extension, con->name);
5082  }
5083 #ifdef NEED_DEBUG
5084  if (con->pattern_tree) {
5085  ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
5086  log_match_char_tree(con->pattern_tree, " ");
5087  }
5088 #endif
5089 
5090  /* scan the extension list to find first matching extension-registrar */
5091  for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
5092  if (!strcmp(exten->exten, ex.exten) &&
5093  (!matchcallerid ||
5094  (!ast_strlen_zero(ex.cidmatch) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, ex.cidmatch)) ||
5095  (ast_strlen_zero(ex.cidmatch) && ast_strlen_zero(exten->cidmatch)))) {
5096  break;
5097  }
5098  }
5099  if (!exten) {
5100  /* we can't find right extension */
5101  if (!already_locked)
5102  ast_unlock_context(con);
5103  return -1;
5104  }
5105 
5106  /* scan the priority list to remove extension with exten->priority == priority */
5107  for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
5108  peer && !strcmp(peer->exten, ex.exten) &&
5109  (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, ex.cidmatch))) ;
5110  peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
5111 
5112  if ((priority == 0 || peer->priority == priority) &&
5113  (!registrar || !strcmp(peer->registrar, registrar) )) {
5114  found = 1;
5115 
5116  /* we are first priority extension? */
5117  if (!previous_peer) {
5118  /*
5119  * We are first in the priority chain, so must update the extension chain.
5120  * The next node is either the next priority or the next extension
5121  */
5122  struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
5123  if (peer->peer) {
5124  /* move the peer_table and peer_label_table down to the next peer, if
5125  it is there */
5126  peer->peer->peer_table = peer->peer_table;
5127  peer->peer->peer_label_table = peer->peer_label_table;
5128  peer->peer_table = NULL;
5129  peer->peer_label_table = NULL;
5130  }
5131  if (!prev_exten) { /* change the root... */
5132  con->root = next_node;
5133  } else {
5134  prev_exten->next = next_node; /* unlink */
5135  }
5136  if (peer->peer) { /* update the new head of the pri list */
5137  peer->peer->next = peer->next;
5138  }
5139  } else { /* easy, we are not first priority in extension */
5140  previous_peer->peer = peer->peer;
5141  }
5142 
5143 
5144  /* now, free whole priority extension */
5145  destroy_exten(peer);
5146  } else {
5147  previous_peer = peer;
5148  }
5149  }
5150  if (!already_locked)
5151  ast_unlock_context(con);
5152  return found ? 0 : -1;
5153 }
5154 
5155 
5156 /*!
5157  * \note This function locks contexts list by &conlist, searches for the right context
5158  * structure, and locks the macrolock mutex in that context.
5159  * macrolock is used to limit a macro to be executed by one call at a time.
5160  * \param context The context
5161  */
5162 int ast_context_lockmacro(const char *context)
5163 {
5164  struct ast_context *c;
5165  int ret = -1;
5166 
5167  c = find_context_locked(context);
5168  if (c) {
5170 
5171  /* if we found context, lock macrolock */
5172  ret = ast_mutex_lock(&c->macrolock);
5173  }
5174 
5175  return ret;
5176 }
5177 
5178 /*!
5179  * \note This function locks contexts list by &conlist, searches for the right context
5180  * structure, and unlocks the macrolock mutex in that context.
5181  * macrolock is used to limit a macro to be executed by one call at a time.
5182  * \param context The context
5183  */
5184 int ast_context_unlockmacro(const char *context)
5185 {
5186  struct ast_context *c;
5187  int ret = -1;
5188 
5189  c = find_context_locked(context);
5190  if (c) {
5192 
5193  /* if we found context, unlock macrolock */
5194  ret = ast_mutex_unlock(&c->macrolock);
5195  }
5196 
5197  return ret;
5198 }
5199 
5200 /*
5201  * Help for CLI commands ...
5202  */
5203 
5204 /*! \brief handle_show_hints: CLI support for listing registered dial plan hints */
5205 static char *handle_show_hints(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5206 {
5207  struct ast_hint *hint;
5208  int num = 0;
5209  int watchers;
5210  struct ao2_iterator i;
5212 
5213  switch (cmd) {
5214  case CLI_INIT:
5215  e->command = "core show hints";
5216  e->usage =
5217  "Usage: core show hints\n"
5218  " List registered hints.\n"
5219  " Hint details are shown in five columns. In order from left to right, they are:\n"
5220  " 1. Hint extension URI.\n"
5221  " 2. List of mapped device or presence state identifiers.\n"
5222  " 3. Current extension state. The aggregate of mapped device states.\n"
5223  " 4. Current presence state for the mapped presence state provider.\n"
5224  " 5. Watchers - number of subscriptions and other entities watching this hint.\n";
5225  return NULL;
5226  case CLI_GENERATE:
5227  return NULL;
5228  }
5229 
5230  if (ao2_container_count(hints) == 0) {
5231  ast_cli(a->fd, "There are no registered dialplan hints\n");
5232  return CLI_SUCCESS;
5233  }
5234  /* ... we have hints ... */
5235  ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n");
5236 
5237  i = ao2_iterator_init(hints, 0);
5238  for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
5239  ao2_lock(hint);
5240  if (!hint->exten) {
5241  /* The extension has already been destroyed */
5242  ao2_unlock(hint);
5243  continue;
5244  }
5245  watchers = ao2_container_count(hint->callbacks);
5246  snprintf(buf, sizeof(buf), "%s@%s",
5249 
5250  ast_cli(a->fd, "%-20.20s: %-20.20s State:%-15.15s Presence:%-15.15s Watchers %2d\n",
5251  buf,
5255  watchers);
5256 
5257  ao2_unlock(hint);
5258  num++;
5259  }
5261 
5262  ast_cli(a->fd, "----------------\n");
5263  ast_cli(a->fd, "- %d hints registered\n", num);
5264  return CLI_SUCCESS;
5265 }
5266 
5267 /*! \brief autocomplete for CLI command 'core show hint' */
5268 static char *complete_core_show_hint(const char *line, const char *word, int pos, int state)
5269 {
5270  struct ast_hint *hint;
5271  char *ret = NULL;
5272  int which = 0;
5273  int wordlen;
5274  struct ao2_iterator i;
5275 
5276  if (pos != 3)
5277  return NULL;
5278 
5279  wordlen = strlen(word);
5280 
5281  /* walk through all hints */
5282  i = ao2_iterator_init(hints, 0);
5283  for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
5284  ao2_lock(hint);
5285  if (!hint->exten) {
5286  /* The extension has already been destroyed */
5287  ao2_unlock(hint);
5288  continue;
5289  }
5290  if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
5291  ret = ast_strdup(ast_get_extension_name(hint->exten));
5292  ao2_unlock(hint);
5293  ao2_ref(hint, -1);
5294  break;
5295  }
5296  ao2_unlock(hint);
5297  }
5299 
5300  return ret;
5301 }
5302 
5303 /*! \brief handle_show_hint: CLI support for listing registered dial plan hint */
5304 static char *handle_show_hint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5305 {
5306  struct ast_hint *hint;
5307  int watchers;
5308  int num = 0, extenlen;
5309  struct ao2_iterator i;
5311 
5312  switch (cmd) {
5313  case CLI_INIT:
5314  e->command = "core show hint";
5315  e->usage =
5316  "Usage: core show hint <exten>\n"
5317  " List registered hint.\n"
5318  " Hint details are shown in five columns. In order from left to right, they are:\n"
5319  " 1. Hint extension URI.\n"
5320  " 2. List of mapped device or presence state identifiers.\n"
5321  " 3. Current extension state. The aggregate of mapped device states.\n"
5322  " 4. Current presence state for the mapped presence state provider.\n"
5323  " 5. Watchers - number of subscriptions and other entities watching this hint.\n";
5324  return NULL;
5325  case CLI_GENERATE:
5326  return complete_core_show_hint(a->line, a->word, a->pos, a->n);
5327  }
5328 
5329  if (a->argc < 4)
5330  return CLI_SHOWUSAGE;
5331 
5332  if (ao2_container_count(hints) == 0) {
5333  ast_cli(a->fd, "There are no registered dialplan hints\n");
5334  return CLI_SUCCESS;
5335  }
5336 
5337  extenlen = strlen(a->argv[3]);
5338  i = ao2_iterator_init(hints, 0);
5339  for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
5340  ao2_lock(hint);
5341  if (!hint->exten) {
5342  /* The extension has already been destroyed */
5343  ao2_unlock(hint);
5344  continue;
5345  }
5346  if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
5347  watchers = ao2_container_count(hint->callbacks);
5348  sprintf(buf, "%s@%s",
5351  ast_cli(a->fd, "%-20.20s: %-20.20s State:%-15.15s Presence:%-15.15s Watchers %2d\n",
5352  buf,
5356  watchers);
5357  num++;
5358  }
5359  ao2_unlock(hint);
5360  }
5362  if (!num)
5363  ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
5364  else
5365  ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
5366  return CLI_SUCCESS;
5367 }
5368 
5369 #if 0
5370 /* This code can be used to test if the system survives running out of memory.
5371  * It might be an idea to put this in only if ENABLE_AUTODESTRUCT_TESTS is enabled.
5372  *
5373  * If you want to test this, these Linux sysctl flags might be appropriate:
5374  * vm.overcommit_memory = 2
5375  * vm.swappiness = 0
5376  *
5377  * <@Corydon76-home> I envision 'core eat disk space' and 'core eat file descriptors' now
5378  * <@mjordan> egads
5379  * <@mjordan> it's literally the 'big red' auto-destruct button
5380  * <@mjordan> if you were wondering who even builds such a thing.... well, now you know
5381  * ...
5382  * <@Corydon76-home> What about if they lived only if you defined TEST_FRAMEWORK? Shouldn't have those on production machines
5383  * <@mjordan> I think accompanied with an update to one of our README files that "no, really, TEST_FRAMEWORK isn't for you", I'd be fine
5384  */
5385 static char *handle_eat_memory(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5386 {
5387  void **blocks;
5388  int blocks_pos = 0;
5389  const int blocks_max = 50000;
5390  long long int allocated = 0;
5391  int sizes[] = {
5392  100 * 1024 * 1024,
5393  100 * 1024,
5394  2 * 1024,
5395  400,
5396  0
5397  };
5398  int i;
5399 
5400  switch (cmd) {
5401  case CLI_INIT:
5402  /* To do: add method to free memory again? 5 minutes? */
5403  e->command = "core eat memory";
5404  e->usage =
5405  "Usage: core eat memory\n"
5406  " Eats all available memory so you can test if the system survives\n";
5407  return NULL;
5408  case CLI_GENERATE:
5409  return NULL;
5410  }
5411 
5412  blocks = ast_malloc(sizeof(void*) * blocks_max);
5413  if (!blocks) {
5414  ast_log(LOG_ERROR, "Already out of mem?\n");
5415  return CLI_SUCCESS;
5416  }
5417 
5418  for (i = 0; sizes[i]; ++i) {
5419  int alloc_size = sizes[i];
5420  ast_log(LOG_WARNING, "Allocating %d sized blocks (got %d blocks already)\n", alloc_size, blocks_pos);
5421  while (1) {
5422  void *block;
5423  if (blocks_pos >= blocks_max) {
5424  ast_log(LOG_ERROR, "Memory buffer too small? Run me again :)\n");
5425  break;
5426  }
5427 
5428  block = ast_malloc(alloc_size);
5429  if (!block) {
5430  break;
5431  }
5432 
5433  blocks[blocks_pos++] = block;
5434  allocated += alloc_size;
5435  }
5436  }
5437 
5438  /* No freeing of the mem! */
5439  ast_log(LOG_WARNING, "Allocated %lld bytes total!\n", allocated);
5440  return CLI_SUCCESS;
5441 }
5442 #endif
5443 
5444 /*
5445  * 'show dialplan' CLI command implementation functions ...
5446  */
5447 static char *complete_show_dialplan_context(const char *line, const char *word, int pos,
5448  int state)
5449 {
5450  struct ast_context *c = NULL;
5451  char *ret = NULL;
5452  int which = 0;
5453  int wordlen;
5454 
5455  /* we are do completion of [exten@]context on second position only */
5456  if (pos != 2)
5457  return NULL;
5458 
5460 
5461  wordlen = strlen(word);
5462 
5463  /* walk through all contexts and return the n-th match */
5464  while ( (c = ast_walk_contexts(c)) ) {
5465  if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
5466  ret = ast_strdup(ast_get_context_name(c));
5467  break;
5468  }
5469  }
5470 
5472 
5473  return ret;
5474 }
5475 
5476 /*! \brief Counters for the show dialplan manager command */
5484 };
5485 
5486 /*! \brief helper function to print an extension */
5487 static void print_ext(struct ast_exten *e, char * buf, int buflen)
5488 {
5489  int prio = ast_get_extension_priority(e);
5490  if (prio == PRIORITY_HINT) {
5491  snprintf(buf, buflen, "hint: %s",
5493  } else {
5494  snprintf(buf, buflen, "%d. %s(%s)",
5495  prio, ast_get_extension_app(e),
5497  }
5498 }
5499 
5500 /*! \brief Writes CLI output of a single extension for show dialplan */
5501 static void show_dialplan_helper_extension_output(int fd, char *buf1, char *buf2, struct ast_exten *exten)
5502 {
5503  if (ast_get_extension_registrar_file(exten)) {
5504  ast_cli(fd, " %-17s %-45s [%s:%d]\n",
5505  buf1, buf2,
5508  return;
5509  }
5510 
5511  ast_cli(fd, " %-17s %-45s [%s]\n",
5512  buf1, buf2, ast_get_extension_registrar(exten));
5513 }
5514 
5515 /* XXX not verified */
5516 static int show_dialplan_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, const struct ast_include *rinclude, int includecount, const char *includes[])
5517 {
5518  struct ast_context *c = NULL;
5519  int res = 0, old_total_exten = dpc->total_exten;
5520 
5522 
5523  /* walk all contexts ... */
5524  while ( (c = ast_walk_contexts(c)) ) {
5525  int idx;
5526  struct ast_exten *e;
5527 #ifndef LOW_MEMORY
5528  char buf[1024], buf2[1024];
5529 #else
5530  char buf[256], buf2[256];
5531 #endif
5532  int context_info_printed = 0;
5533 
5534  if (context && strcmp(ast_get_context_name(c), context))
5535  continue; /* skip this one, name doesn't match */
5536 
5537  dpc->context_existence = 1;
5538 
5539  ast_rdlock_context(c);
5540 
5541  /* are we looking for exten too? if yes, we print context
5542  * only if we find our extension.
5543  * Otherwise print context even if empty ?
5544  * XXX i am not sure how the rinclude is handled.
5545  * I think it ought to go inside.
5546  */
5547  if (!exten) {
5548  dpc->total_context++;
5549  ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
5551  if (c->autohints) {
5552  ast_cli(fd, "Autohints support enabled\n");
5553  }
5554  context_info_printed = 1;
5555  }
5556 
5557  /* walk extensions ... */
5558  e = NULL;
5559  while ( (e = ast_walk_context_extensions(c, e)) ) {
5560  struct ast_exten *p;
5561 
5562  if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
5563  continue; /* skip, extension match failed */
5564 
5565  dpc->extension_existence = 1;
5566 
5567  /* may we print context info? */
5568  if (!context_info_printed) {
5569  dpc->total_context++;
5570  if (rinclude) { /* TODO Print more info about rinclude */
5571  ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
5573  } else {
5574  ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
5576  if (c->autohints) {
5577  ast_cli(fd, "Autohints support enabled\n");
5578  }
5579  }
5580  context_info_printed = 1;
5581  }
5582  dpc->total_prio++;
5583 
5584  /* write extension name and first peer */
5585  if (e->matchcid == AST_EXT_MATCHCID_ON)
5586  snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
5587  else
5588  snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
5589 
5590  print_ext(e, buf2, sizeof(buf2));
5591 
5592  show_dialplan_helper_extension_output(fd, buf, buf2, e);
5593 
5594  dpc->total_exten++;
5595  /* walk next extension peers */
5596  p = e; /* skip the first one, we already got it */
5597  while ( (p = ast_walk_extension_priorities(e, p)) ) {
5598  const char *el = ast_get_extension_label(p);
5599  dpc->total_prio++;
5600  if (el)
5601  snprintf(buf, sizeof(buf), " [%s]", el);
5602  else
5603  buf[0] = '\0';
5604  print_ext(p, buf2, sizeof(buf2));
5605 
5606  show_dialplan_helper_extension_output(fd, buf, buf2, p);
5607  }
5608  }
5609 
5610  /* walk included and write info ... */
5611  for (idx = 0; idx < ast_context_includes_count(c); idx++) {
5612  const struct ast_include *i = ast_context_includes_get(c, idx);
5613 
5614  snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
5615  if (exten) {
5616  /* Check all includes for the requested extension */
5617  if (includecount >= AST_PBX_MAX_STACK) {
5618  ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
5619  } else {
5620  int dupe = 0;
5621  int x;
5622  for (x = 0; x < includecount; x++) {
5623  if (!strcasecmp(includes[x], ast_get_include_name(i))) {
5624  dupe++;
5625  break;
5626  }
5627  }
5628  if (!dupe) {
5629  includes[includecount] = ast_get_include_name(i);
5630  show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
5631  } else {
5632  ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
5633  }
5634  }
5635  } else {
5636  ast_cli(fd, " Include => %-45s [%s]\n",
5637  buf, ast_get_include_registrar(i));
5638  }
5639  }
5640 
5641  /* walk ignore patterns and write info ... */
5642  for (idx = 0; idx < ast_context_ignorepats_count(c); idx++) {
5643  const struct ast_ignorepat *ip = ast_context_ignorepats_get(c, idx);
5644  const char *ipname = ast_get_ignorepat_name(ip);
5645  char ignorepat[AST_MAX_EXTENSION];
5646 
5647  snprintf(buf, sizeof(buf), "'%s'", ipname);
5648  snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
5649  if (!exten || ast_extension_match(ignorepat, exten)) {
5650  ast_cli(fd, " Ignore pattern => %-45s [%s]\n",
5651  buf, ast_get_ignorepat_registrar(ip));
5652  }
5653  }
5654  if (!rinclude) {
5655  for (idx = 0; idx < ast_context_switches_count(c); idx++) {
5656  const struct ast_sw *sw = ast_context_switches_get(c, idx);
5657 
5658  snprintf(buf, sizeof(buf), "'%s/%s'",
5659  ast_get_switch_name(sw),
5660  ast_get_switch_data(sw));
5661  ast_cli(fd, " Alt. Switch => %-45s [%s]\n",
5662  buf, ast_get_switch_registrar(sw));
5663  }
5664  }
5665 
5666  ast_unlock_context(c);
5667 
5668  /* if we print something in context, make an empty line */
5669  if (context_info_printed)
5670  ast_cli(fd, "\n");
5671  }
5673 
5674  return (dpc->total_exten == old_total_exten) ? -1 : res;
5675 }
5676 
5677 static int show_debug_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
5678 {
5679  struct ast_context *c = NULL;
5680  int res = 0, old_total_exten = dpc->total_exten;
5681 
5682  ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
5683 
5684  ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
5685  ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
5686  ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
5687  ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
5688  ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
5689  ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
5690  ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
5692 
5693  /* walk all contexts ... */
5694  while ( (c = ast_walk_contexts(c)) ) {
5695  int context_info_printed = 0;
5696 
5697  if (context && strcmp(ast_get_context_name(c), context))
5698  continue; /* skip this one, name doesn't match */
5699 
5700  dpc->context_existence = 1;
5701 
5702  if (!c->pattern_tree) {
5703  /* Ignore check_return warning from Coverity for ast_exists_extension below */
5704  ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
5705  }
5706 
5707  ast_rdlock_context(c);
5708 
5709  dpc->total_context++;
5710  ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
5712  context_info_printed = 1;
5713 
5714  if (c->pattern_tree)
5715  {
5716  cli_match_char_tree(c->pattern_tree, " ", fd);
5717  } else {
5718  ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
5719  }
5720 
5721  ast_unlock_context(c);
5722 
5723  /* if we print something in context, make an empty line */
5724  if (context_info_printed)
5725  ast_cli(fd, "\n");
5726  }
5728 
5729  return (dpc->total_exten == old_total_exten) ? -1 : res;
5730 }
5731 
5732 static char *handle_show_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5733 {
5734  char *exten = NULL, *context = NULL;
5735  /* Variables used for different counters */
5736  struct dialplan_counters counters;
5737  const char *incstack[AST_PBX_MAX_STACK];
5738 
5739  switch (cmd) {
5740  case CLI_INIT:
5741  e->command = "dialplan show";
5742  e->usage =
5743  "Usage: dialplan show [[exten@]context]\n"
5744  " Show dialplan\n";
5745  return NULL;
5746  case CLI_GENERATE:
5747  return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
5748  }
5749 
5750  memset(&counters, 0, sizeof(counters));
5751 
5752  if (a->argc != 2 && a->argc != 3)
5753  return CLI_SHOWUSAGE;
5754 
5755  /* we obtain [exten@]context? if yes, split them ... */
5756  if (a->argc == 3) {
5757  if (strchr(a->argv[2], '@')) { /* split into exten & context */
5758  context = ast_strdupa(a->argv[2]);
5759  exten = strsep(&context, "@");
5760  /* change empty strings to NULL */
5761  if (ast_strlen_zero(exten))
5762  exten = NULL;
5763  } else { /* no '@' char, only context given */
5764  context = ast_strdupa(a->argv[2]);
5765  }
5766  if (ast_strlen_zero(context))
5767  context = NULL;
5768  }
5769  /* else Show complete dial plan, context and exten are NULL */
5770  show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
5771 
5772  /* check for input failure and throw some error messages */
5773  if (context && !counters.context_existence) {
5774  ast_cli(a->fd, "There is no existence of '%s' context\n", context);
5775  return CLI_FAILURE;
5776  }
5777 
5778  if (exten && !counters.extension_existence) {
5779  if (context)
5780  ast_cli(a->fd, "There is no existence of %s@%s extension\n",
5781  exten, context);
5782  else
5783  ast_cli(a->fd,
5784  "There is no existence of '%s' extension in all contexts\n",
5785  exten);
5786  return CLI_FAILURE;
5787  }
5788 
5789  ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
5790  counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
5791  counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
5792  counters.total_context, counters.total_context == 1 ? "context" : "contexts");
5793 
5794  /* everything ok */
5795  return CLI_SUCCESS;
5796 }
5797 
5798 /*! \brief Send ack once */
5799 static char *handle_debug_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
5800 {
5801  char *exten = NULL, *context = NULL;
5802  /* Variables used for different counters */
5803  struct dialplan_counters counters;
5804  const char *incstack[AST_PBX_MAX_STACK];
5805 
5806  switch (cmd) {
5807  case CLI_INIT:
5808  e->command = "dialplan debug";
5809  e->usage =
5810  "Usage: dialplan debug [context]\n"
5811  " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
5812  return NULL;
5813  case CLI_GENERATE:
5814  return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
5815  }
5816 
5817  memset(&counters, 0, sizeof(counters));
5818 
5819  if (a->argc != 2 && a->argc != 3)
5820  return CLI_SHOWUSAGE;
5821 
5822  /* we obtain [exten@]context? if yes, split them ... */
5823  /* note: we ignore the exten totally here .... */
5824  if (a->argc == 3) {
5825  if (strchr(a->argv[2], '@')) { /* split into exten & context */
5826  context = ast_strdupa(a->argv[2]);
5827  exten = strsep(&context, "@");
5828  /* change empty strings to NULL */
5829  if (ast_strlen_zero(exten))
5830  exten = NULL;
5831  } else { /* no '@' char, only context given */
5832  context = ast_strdupa(a->argv[2]);
5833  }
5834  if (ast_strlen_zero(context))
5835  context = NULL;
5836  }
5837  /* else Show complete dial plan, context and exten are NULL */
5838  show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
5839 
5840  /* check for input failure and throw some error messages */
5841  if (context && !counters.context_existence) {
5842  ast_cli(a->fd, "There is no existence of '%s' context\n", context);
5843  return CLI_FAILURE;
5844  }
5845 
5846 
5847  ast_cli(a->fd,"-= %d %s. =-\n",
5848  counters.total_context, counters.total_context == 1 ? "context" : "contexts");
5849 
5850  /* everything ok */
5851  return CLI_SUCCESS;
5852 }
5853 
5854 /*! \brief Send ack once */
5855 static void manager_dpsendack(struct mansession *s, const struct message *m)
5856 {
5857  astman_send_listack(s, m, "DialPlan list will follow", "start");
5858 }
5859 
5860 /*! \brief Show dialplan extensions
5861  * XXX this function is similar but not exactly the same as the CLI's
5862  * show dialplan. Must check whether the difference is intentional or not.
5863  */
5864 static int manager_show_dialplan_helper(struct mansession *s, const struct message *m,
5865  const char *actionidtext, const char *context,
5866  const char *exten, struct dialplan_counters *dpc,
5867  const struct ast_include *rinclude,
5868  int includecount, const char *includes[])
5869 {
5870  struct ast_context *c;
5871  int res = 0, old_total_exten = dpc->total_exten;
5872 
5873  if (ast_strlen_zero(exten))
5874  exten = NULL;
5875  if (ast_strlen_zero(context))
5876  context = NULL;
5877 
5878  ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
5879 
5880  /* try to lock contexts */
5881  if (ast_rdlock_contexts()) {
5882  astman_send_error(s, m, "Failed to lock contexts");
5883  ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
5884  return -1;
5885  }
5886 
5887  c = NULL; /* walk all contexts ... */
5888  while ( (c = ast_walk_contexts(c)) ) {
5889  int idx;
5890  struct ast_exten *e;
5891 
5892  if (context && strcmp(ast_get_context_name(c), context) != 0)
5893  continue; /* not the name we want */
5894 
5895  dpc->context_existence = 1;
5896  dpc->total_context++;
5897 
5898  ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
5899 
5900  if (ast_rdlock_context(c)) { /* failed to lock */
5901  ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
5902  continue;
5903  }
5904 
5905  /* XXX note- an empty context is not printed */
5906  e = NULL; /* walk extensions in context */
5907  while ( (e = ast_walk_context_extensions(c, e)) ) {
5908  struct ast_exten *p;
5909 
5910  /* looking for extension? is this our extension? */
5911  if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) {
5912  /* not the one we are looking for, continue */
5913  ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
5914  continue;
5915  }
5916  ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
5917 
5918  dpc->extension_existence = 1;
5919 
5920  dpc->total_exten++;
5921 
5922  p = NULL; /* walk next extension peers */
5923  while ( (p = ast_walk_extension_priorities(e, p)) ) {
5924  int prio = ast_get_extension_priority(p);
5925 
5926  dpc->total_prio++;
5927  if (!dpc->total_items++)
5928  manager_dpsendack(s, m);
5929  astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
5930  astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
5931 
5932  /* XXX maybe make this conditional, if p != e ? */
5933  if (ast_get_extension_label(p))
5934  astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
5935 
5936  if (prio == PRIORITY_HINT) {
5937  astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
5938  } else {
5939  astman_append(s, "Priority: %d\r\nApplication: %s\r\nAppData: %s\r\n", prio, ast_get_extension_app(p), (char *) ast_get_extension_app_data(p));
5940  }
5941  astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
5942  }
5943  }
5944 
5945  for (idx = 0; idx < ast_context_includes_count(c); idx++) {
5946  const struct ast_include *i = ast_context_includes_get(c, idx);
5947 
5948  if (exten) {
5949  /* Check all includes for the requested extension */
5950  if (includecount >= AST_PBX_MAX_STACK) {
5951  ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
5952  } else {
5953  int dupe = 0;
5954  int x;
5955  for (x = 0; x < includecount; x++) {
5956  if (!strcasecmp(includes[x], ast_get_include_name(i))) {
5957  dupe++;
5958  break;
5959  }
5960  }
5961  if (!dupe) {
5962  includes[includecount] = ast_get_include_name(i);
5963  manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
5964  } else {
5965  ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
5966  }
5967  }
5968  } else {
5969  if (!dpc->total_items++)
5970  manager_dpsendack(s, m);
5971  astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
5972  astman_append(s, "Context: %s\r\nIncludeContext: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_include_name(i), ast_get_include_registrar(i));
5973  astman_append(s, "\r\n");
5974  ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
5975  }
5976  }
5977 
5978  for (idx = 0; idx < ast_context_ignorepats_count(c); idx++) {
5979  const struct ast_ignorepat *ip = ast_context_ignorepats_get(c, idx);
5980  const char *ipname = ast_get_ignorepat_name(ip);
5981  char ignorepat[AST_MAX_EXTENSION];
5982 
5983  snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
5984  if (!exten || ast_extension_match(ignorepat, exten)) {
5985  if (!dpc->total_items++)
5986  manager_dpsendack(s, m);
5987  astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
5988  astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
5989  astman_append(s, "\r\n");
5990  }
5991  }
5992  if (!rinclude) {
5993  for (idx = 0; idx < ast_context_switches_count(c); idx++) {
5994  const struct ast_sw *sw = ast_context_switches_get(c, idx);
5995 
5996  if (!dpc->total_items++)
5997  manager_dpsendack(s, m);
5998  astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
5999  astman_append(s, "Context: %s\r\nSwitch: %s/%s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_switch_name(sw), ast_get_switch_data(sw), ast_get_switch_registrar(sw));
6000  astman_append(s, "\r\n");
6001  ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
6002  }
6003  }
6004 
6005  ast_unlock_context(c);
6006  }
6008 
6009  if (dpc->total_exten == old_total_exten) {
6010  ast_debug(3, "manager_show_dialplan: Found nothing new\n");
6011  /* Nothing new under the sun */
6012  return -1;
6013  } else {
6014  return res;
6015  }
6016 }
6017 
6018 /*! \brief Manager listing of dial plan */
6019 static int manager_show_dialplan(struct mansession *s, const struct message *m)
6020 {
6021  const char *exten, *context;
6022  const char *id = astman_get_header(m, "ActionID");
6023  const char *incstack[AST_PBX_MAX_STACK];
6024  char idtext[256];
6025 
6026  /* Variables used for different counters */
6027  struct dialplan_counters counters;
6028 
6029  if (!ast_strlen_zero(id))
6030  snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
6031  else
6032  idtext[0] = '\0';
6033 
6034  memset(&counters, 0, sizeof(counters));
6035 
6036  exten = astman_get_header(m, "Extension");
6037  context = astman_get_header(m, "Context");
6038 
6039  manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL, 0, incstack);
6040 
6041  if (!ast_strlen_zero(context) && !counters.context_existence) {
6042  char errorbuf[BUFSIZ];
6043 
6044  snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
6045  astman_send_error(s, m, errorbuf);
6046  return 0;
6047  }
6048  if (!ast_strlen_zero(exten) && !counters.extension_existence) {
6049  char errorbuf[BUFSIZ];
6050 
6051  if (!ast_strlen_zero(context))
6052  snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
6053  else
6054  snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
6055  astman_send_error(s, m, errorbuf);
6056  return 0;
6057  }
6058 
6059  if (!counters.total_items) {
6060  manager_dpsendack(s, m);
6061  }
6062 
6063  astman_send_list_complete_start(s, m, "ShowDialPlanComplete", counters.total_items);
6064  astman_append(s,
6065  "ListExtensions: %d\r\n"
6066  "ListPriorities: %d\r\n"
6067  "ListContexts: %d\r\n",
6068  counters.total_exten, counters.total_prio, counters.total_context);
6070 
6071  /* everything ok */
6072  return 0;
6073 }
6074 
6075 #ifdef AST_DEVMODE
6076 static char *handle_show_device2extenstate(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
6077 {
6078  struct ast_devstate_aggregate agg;
6079  int i, j, exten, combined;
6080 
6081  switch (cmd) {
6082  case CLI_INIT:
6083  e->command = "core show device2extenstate";
6084  e->usage =
6085  "Usage: core show device2extenstate\n"
6086  " Lists device state to extension state combinations.\n";
6087  case CLI_GENERATE:
6088  return NULL;
6089  }
6090  for (i = 0; i < AST_DEVICE_TOTAL; i++) {
6091  for (j = 0; j < AST_DEVICE_TOTAL; j++) {
6093  ast_devstate_aggregate_add(&agg, i);
6094  ast_devstate_aggregate_add(&agg, j);
6095  combined = ast_devstate_aggregate_result(&agg);
6096  exten = ast_devstate_to_extenstate(combined);
6097  ast_cli(a->fd, "\n Exten:%14s CombinedDevice:%12s Dev1:%12s Dev2:%12s", ast_extension_state2str(exten), ast_devstate_str(combined), ast_devstate_str(j), ast_devstate_str(i));
6098  }
6099  }
6100  ast_cli(a->fd, "\n");
6101  return CLI_SUCCESS;
6102 }
6103 #endif
6104 
6105 static char *handle_set_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
6106 {
6107  int oldval = 0;
6108 
6109  switch (cmd) {
6110  case CLI_INIT:
6111  e->command = "dialplan set extenpatternmatchnew true";
6112  e->usage =
6113  "Usage: dialplan set extenpatternmatchnew true|false\n"
6114  " Use the NEW extension pattern matching algorithm, true or false.\n";
6115  return NULL;
6116  case CLI_GENERATE:
6117  return NULL;
6118  }
6119 
6120  if (a->argc != 4)
6121  return CLI_SHOWUSAGE;
6122 
6123  oldval = pbx_set_extenpatternmatchnew(1);
6124 
6125  if (oldval)
6126  ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
6127  else
6128  ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
6129 
6130  return CLI_SUCCESS;
6131 }
6132 
6133 static char *handle_unset_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
6134 {
6135  int oldval = 0;
6136 
6137  switch (cmd) {
6138  case CLI_INIT:
6139  e->command = "dialplan set extenpatternmatchnew false";
6140  e->usage =
6141  "Usage: dialplan set extenpatternmatchnew true|false\n"
6142  " Use the NEW extension pattern matching algorithm, true or false.\n";
6143  return NULL;
6144  case CLI_GENERATE:
6145  return NULL;
6146  }
6147 
6148  if (a->argc != 4)
6149  return CLI_SHOWUSAGE;
6150 
6151  oldval = pbx_set_extenpatternmatchnew(0);
6152 
6153  if (!oldval)
6154  ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
6155  else
6156  ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
6157 
6158  return CLI_SUCCESS;
6159 }
6160 
6161 /*
6162  * CLI entries for upper commands ...
6163  */
6164 static struct ast_cli_entry pbx_cli[] = {
6165 #if 0
6166  AST_CLI_DEFINE(handle_eat_memory, "Eats all available memory"),
6167 #endif
6168  AST_CLI_DEFINE(handle_show_hints, "Show dialplan hints"),
6169  AST_CLI_DEFINE(handle_show_hint, "Show dialplan hint"),
6170 #ifdef AST_DEVMODE
6171  AST_CLI_DEFINE(handle_show_device2extenstate, "Show expected exten state from multiple device states"),
6172 #endif
6173  AST_CLI_DEFINE(handle_show_dialplan, "Show dialplan"),
6174  AST_CLI_DEFINE(handle_debug_dialplan, "Show fast extension pattern matching data structures"),
6175  AST_CLI_DEFINE(handle_unset_extenpatternmatchnew, "Use the Old extension pattern matching algorithm."),
6176  AST_CLI_DEFINE(handle_set_extenpatternmatchnew, "Use the New extension pattern matching algorithm."),
6177 };
6178 
6180 {
6181  struct ast_context *context = NULL;
6182  struct ast_exten *eroot = NULL, *e = NULL;
6183 
6185  while ((context = ast_walk_contexts(context))) {
6186  while ((eroot = ast_walk_context_extensions(context, eroot))) {
6187  while ((e = ast_walk_extension_priorities(eroot, e))) {
6188  if (e->cached_app == app)
6189  e->cached_app = NULL;
6190  }
6191  }
6192  }
6194 
6195  return;
6196 }
6197 
6198 struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
6199 {
6200  struct ast_context *tmp, **local_contexts;
6201  struct fake_context search;
6202  int length = sizeof(struct ast_context) + strlen(name) + 1;
6203 
6204  if (!contexts_table) {
6205  /* Protect creation of contexts_table from reentrancy. */
6207  if (!contexts_table) {
6208  contexts_table = ast_hashtab_create(17,
6213  0);
6214  }
6216  }
6217 
6218  ast_copy_string(search.name, name, sizeof(search.name));
6219  if (!extcontexts) {
6221  local_contexts = &contexts;
6222  tmp = ast_hashtab_lookup(contexts_table, &search);
6223  if (tmp) {
6224  tmp->refcount++;
6226  return tmp;
6227  }
6228  } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
6229  local_contexts = extcontexts;
6230  tmp = ast_hashtab_lookup(exttable, &search);
6231  if (tmp) {
6232  tmp->refcount++;
6233  return tmp;
6234  }
6235  }
6236 
6237  if ((tmp = ast_calloc(1, length))) {
6238  ast_rwlock_init(&tmp->lock);
6239  ast_mutex_init(&tmp->macrolock);
6240  strcpy(tmp->name, name);
6241  tmp->root = NULL;
6242  tmp->root_table = NULL;
6243  tmp->registrar = ast_strdup(registrar);
6244  AST_VECTOR_INIT(&tmp->includes, 0);
6245  AST_VECTOR_INIT(&tmp->ignorepats, 0);
6246  AST_VECTOR_INIT(&tmp->alts, 0);
6247  tmp->refcount = 1;
6248  } else {
6249  ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
6250  if (!extcontexts) {
6252  }
6253  return NULL;
6254  }
6255 
6256  if (!extcontexts) {
6257  tmp->next = *local_contexts;
6258  *local_contexts = tmp;
6259  ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
6261  } else {
6262  tmp->next = *local_contexts;
6263  if (exttable)
6264  ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
6265 
6266  *local_contexts = tmp;
6267  }
6268  ast_debug(1, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
6269  return tmp;
6270 }
6271 
6273 {
6274  con->autohints = enabled;
6275 }
6276 
6277 void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar);
6278 
6279 struct store_hint {
6280  char *context;
6281  char *exten;
6287 
6289  char data[0];
6290 };
6291 
6293 
6294 static void context_merge_incls_swits_igps_other_registrars(struct ast_context *new, struct ast_context *old, const char *registrar)
6295 {
6296  int idx;
6297 
6298  ast_debug(1, "merging incls/swits/igpats from old(%s) to new(%s) context, registrar = %s\n", ast_get_context_name(old), ast_get_context_name(new), registrar);
6299  /* copy in the includes, switches, and ignorepats */
6300  /* walk through includes */
6301  for (idx = 0; idx < ast_context_includes_count(old); idx++) {
6302  const struct ast_include *i = ast_context_includes_get(old, idx);
6303 
6304  if (!strcmp(ast_get_include_registrar(i), registrar)) {
6305  continue; /* not mine */
6306  }
6308  }
6309 
6310  /* walk through switches */
6311  for (idx = 0; idx < ast_context_switches_count(old); idx++) {
6312  const struct ast_sw *sw = ast_context_switches_get(old, idx);
6313 
6314  if (!strcmp(ast_get_switch_registrar(sw), registrar)) {
6315  continue; /* not mine */
6316  }
6318  }
6319 
6320  /* walk thru ignorepats ... */
6321  for (idx = 0; idx < ast_context_ignorepats_count(old); idx++) {
6322  const struct ast_ignorepat *ip = ast_context_ignorepats_get(old, idx);
6323 
6324  if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) {
6325  continue; /* not mine */
6326  }
6328  }
6329 }
6330 
6331 /*! Set up an autohint placeholder in the hints container */
6333 {
6334  struct ast_context *con;
6335  struct ast_hashtab_iter *iter;
6336 
6337  /* Remove all autohints as the below iteration will recreate them */
6339 
6340  iter = ast_hashtab_start_traversal(table);
6341  while ((con = ast_hashtab_next(iter))) {
6342  size_t name_len = strlen(con->name) + 1;
6343  size_t registrar_len = strlen(con->registrar) + 1;
6344  struct ast_autohint *autohint;
6345 
6346  if (!con->autohints) {
6347  continue;
6348  }
6349 
6350  autohint = ao2_alloc_options(sizeof(*autohint) + name_len + registrar_len, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
6351  if (!autohint) {
6352  continue;
6353  }
6354 
6355  ast_copy_string(autohint->context, con->name, name_len);
6356  autohint->registrar = autohint->context + name_len;
6357  ast_copy_string(autohint->registrar, con->registrar, registrar_len);
6358 
6359  ao2_link(autohints, autohint);
6360  ao2_ref(autohint, -1);
6361 
6362  ast_verb(3, "Enabled autohints support on context '%s'\n", con->name);
6363  }
6365 }
6366 
6367 /* the purpose of this routine is to duplicate a context, with all its substructure,
6368  except for any extens that have a matching registrar */
6369 static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
6370 {
6371  struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
6372  struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
6373  struct ast_hashtab_iter *exten_iter;
6374  struct ast_hashtab_iter *prio_iter;
6375  int insert_count = 0;
6376  int first = 1;
6377 
6378  /* We'll traverse all the extensions/prios, and see which are not registrar'd with
6379  the current registrar, and copy them to the new context. If the new context does not
6380  exist, we'll create it "on demand". If no items are in this context to copy, then we'll
6381  only create the empty matching context if the old one meets the criteria */
6382 
6383  if (context->root_table) {
6384  exten_iter = ast_hashtab_start_traversal(context->root_table);
6385  while ((exten_item=ast_hashtab_next(exten_iter))) {
6386  if (new) {
6387  new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
6388  } else {
6389  new_exten_item = NULL;
6390  }
6391  prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
6392  while ((prio_item=ast_hashtab_next(prio_iter))) {
6393  int res1;
6394  char *dupdstr;
6395 
6396  if (new_exten_item) {
6397  new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
6398  } else {
6399  new_prio_item = NULL;
6400  }
6401  if (strcmp(prio_item->registrar,registrar) == 0) {
6402  continue;
6403  }
6404  /* make sure the new context exists, so we have somewhere to stick this exten/prio */
6405  if (!new) {
6406  new = ast_context_find_or_create(extcontexts, exttable, context->name, prio_item->registrar); /* a new context created via priority from a different context in the old dialplan, gets its registrar from the prio's registrar */
6407  if (new) {
6408  new->autohints = context->autohints;
6409  }
6410  }
6411 
6412  /* copy in the includes, switches, and ignorepats */
6413  if (first) { /* but, only need to do this once */
6414  context_merge_incls_swits_igps_other_registrars(new, context, registrar);
6415  first = 0;
6416  }
6417 
6418  if (!new) {
6419  ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
6420  ast_hashtab_end_traversal(prio_iter);
6421  ast_hashtab_end_traversal(exten_iter);
6422  return; /* no sense continuing. */
6423  }
6424  /* we will not replace existing entries in the new context with stuff from the old context.
6425  but, if this is because of some sort of registrar conflict, we ought to say something... */
6426 
6427  dupdstr = ast_strdup(prio_item->data);
6428 
6429  res1 = ast_add_extension2(new, 0, prio_item->name, prio_item->priority, prio_item->label,
6430  prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, ast_free_ptr, prio_item->registrar,
6431  prio_item->registrar_file, prio_item->registrar_line);
6432  if (!res1 && new_exten_item && new_prio_item){
6433  ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
6434  context->name, prio_item->name, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
6435  } else {
6436  /* we do NOT pass the priority data from the old to the new -- we pass a copy of it, so no changes to the current dialplan take place,
6437  and no double frees take place, either! */
6438  insert_count++;
6439  }
6440  }
6441  ast_hashtab_end_traversal(prio_iter);
6442  }
6443  ast_hashtab_end_traversal(exten_iter);
6444  } else if (new) {
6445  /* If the context existed but had no extensions, we still want to merge
6446  * the includes, switches and ignore patterns.
6447  */
6448  context_merge_incls_swits_igps_other_registrars(new, context, registrar);
6449  }
6450 
6451  if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
6452  (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
6453  /* we could have given it the registrar of the other module who incremented the refcount,
6454  but that's not available, so we give it the registrar we know about */
6455  new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
6456 
6457  if (new) {
6458  new->autohints = context->autohints;
6459  }
6460 
6461  /* copy in the includes, switches, and ignorepats */
6462  context_merge_incls_swits_igps_other_registrars(new, context, registrar);
6463  }
6464 }
6465 
6466 
6467 /* XXX this does not check that multiple contexts are merged */
6468 void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
6469 {
6470  double ft;
6471  struct ast_context *tmp;
6472  struct ast_context *oldcontextslist;
6473  struct ast_hashtab *oldtable;
6474  struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
6475  struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
6476  struct store_hint *saved_hint;
6477  struct ast_hint *hint;
6478  struct ast_exten *exten;
6479  int length;
6480  struct ast_state_cb *thiscb;
6481  struct ast_hashtab_iter *iter;
6482  struct ao2_iterator i;
6483  int ctx_count = 0;
6484  struct timeval begintime;
6485  struct timeval writelocktime;
6486  struct timeval endlocktime;
6487  struct timeval enddeltime;
6488 
6489  /*
6490  * It is very important that this function hold the hints
6491  * container lock _and_ the conlock during its operation; not
6492  * only do we need to ensure that the list of contexts and
6493  * extensions does not change, but also that no hint callbacks
6494  * (watchers) are added or removed during the merge/delete
6495  * process
6496  *
6497  * In addition, the locks _must_ be taken in this order, because
6498  * there are already other code paths that use this order
6499  */
6500 
6501  begintime = ast_tvnow();
6502  ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
6504 
6505  if (!contexts_table) {
6506  /* Create any autohint contexts */
6508 
6509  /* Well, that's odd. There are no contexts. */
6510  contexts_table = exttable;
6511  contexts = *extcontexts;
6514  return;
6515  }
6516 
6517  iter = ast_hashtab_start_traversal(contexts_table);
6518  while ((tmp = ast_hashtab_next(iter))) {
6519  ++ctx_count;
6520  context_merge(extcontexts, exttable, tmp, registrar);
6521  }
6523 
6524  ao2_lock(hints);
6525  writelocktime = ast_tvnow();
6526 
6527  /* preserve all watchers for hints */
6529  for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
6530  if (ao2_container_count(hint->callbacks)) {
6531  size_t exten_len;
6532 
6533  ao2_lock(hint);
6534  if (!hint->exten) {
6535  /* The extension has already been destroyed. (Should never happen here) */
6536  ao2_unlock(hint);
6537  continue;
6538  }
6539 
6540  exten_len = strlen(hint->exten->exten) + 1;
6541  length = exten_len + strlen(hint->exten->parent->name) + 1
6542  + sizeof(*saved_hint);
6543  if (!(saved_hint = ast_calloc(1, length))) {
6544  ao2_unlock(hint);
6545  continue;
6546  }
6547 
6548  /* This removes all the callbacks from the hint into saved_hint. */
6549  while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
6550  AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
6551  /*
6552  * We intentionally do not unref thiscb to account for the
6553  * non-ao2 reference in saved_hint->callbacks
6554  */
6555  }
6556 
6557  saved_hint->laststate = hint->laststate;
6558  saved_hint->context = saved_hint->data;
6559  strcpy(saved_hint->data, hint->exten->parent->name);
6560  saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
6561  ast_copy_string(saved_hint->exten, hint->exten->exten, exten_len);
6562  if (hint->last_presence_subtype) {
6563  saved_hint->last_presence_subtype = ast_strdup(hint->last_presence_subtype);
6564  }
6565  if (hint->last_presence_message) {
6566  saved_hint->last_presence_message = ast_strdup(hint->last_presence_message);
6567  }
6568  saved_hint->last_presence_state = hint->last_presence_state;
6569  ao2_unlock(hint);
6570  AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
6571  }
6572  }
6574 
6575  /* save the old table and list */
6576  oldtable = contexts_table;
6577  oldcontextslist = contexts;
6578 
6579  /* move in the new table and list */
6580  contexts_table = exttable;
6581  contexts = *extcontexts;
6582 
6583  /*
6584  * Restore the watchers for hints that can be found; notify
6585  * those that cannot be restored.
6586  */
6587  while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
6588  struct pbx_find_info q = { .stacklen = 0 };
6589 
6590  exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
6591  PRIORITY_HINT, NULL, "", E_MATCH);
6592  /*
6593  * If this is a pattern, dynamically create a new extension for this
6594  * particular match. Note that this will only happen once for each
6595  * individual extension, because the pattern will no longer match first.
6596  */
6597  if (exten && exten->exten[0] == '_') {
6598  ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
6599  PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
6600  exten->registrar);
6601  /* rwlocks are not recursive locks */
6602  exten = ast_hint_extension_nolock(NULL, saved_hint->context,
6603  saved_hint->exten);
6604  }
6605 
6606  /* Find the hint in the hints container */
6607  hint = exten ? ao2_find(hints, exten, 0) : NULL;
6608  if (!hint) {
6609  /*
6610  * Notify watchers of this removed hint later when we aren't
6611  * encumberd by so many locks.
6612  */
6613  AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
6614  } else {
6615  ao2_lock(hint);
6616  while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
6617  ao2_link(hint->callbacks, thiscb);
6618  /* Ref that we added when putting into saved_hint->callbacks */
6619  ao2_ref(thiscb, -1);
6620  }
6621  hint->laststate = saved_hint->laststate;
6622  hint->last_presence_state = saved_hint->last_presence_state;
6623  hint->last_presence_subtype = saved_hint->last_presence_subtype;
6624  hint->last_presence_message = saved_hint->last_presence_message;
6625  ao2_unlock(hint);
6626  ao2_ref(hint, -1);
6627  /*
6628  * The free of saved_hint->last_presence_subtype and
6629  * saved_hint->last_presence_message is not necessary here.
6630  */
6631  ast_free(saved_hint);
6632  }
6633  }
6634 
6635  /* Create all applicable autohint contexts */
6636  context_table_create_autohints(contexts_table);
6637 
6638  ao2_unlock(hints);
6640 
6641  /*
6642  * Notify watchers of all removed hints with the same lock
6643  * environment as device_state_cb().
6644  */
6645  while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
6646  /* this hint has been removed, notify the watchers */
6647  while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
6649  saved_hint->context,
6650  saved_hint->exten,
6651  thiscb->data,
6653  NULL,
6654  NULL);
6655  /* Ref that we added when putting into saved_hint->callbacks */
6656  ao2_ref(thiscb, -1);
6657  }
6658  ast_free(saved_hint->last_presence_subtype);
6659  ast_free(saved_hint->last_presence_message);
6660  ast_free(saved_hint);
6661  }
6662 
6664  endlocktime = ast_tvnow();
6665 
6666  /*
6667  * The old list and hashtab no longer are relevant, delete them
6668  * while the rest of asterisk is now freely using the new stuff
6669  * instead.
6670  */
6671 
6672  ast_hashtab_destroy(oldtable, NULL);
6673 
6674  for (tmp = oldcontextslist; tmp; ) {
6675  struct ast_context *next; /* next starting point */
6676 
6677  next = tmp->next;
6679  tmp = next;
6680  }
6681  enddeltime = ast_tvnow();
6682 
6683  ft = ast_tvdiff_us(writelocktime, begintime);
6684  ft /= 1000000.0;
6685  ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
6686 
6687  ft = ast_tvdiff_us(endlocktime, writelocktime);
6688  ft /= 1000000.0;
6689  ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
6690 
6691  ft = ast_tvdiff_us(enddeltime, endlocktime);
6692  ft /= 1000000.0;
6693  ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
6694 
6695  ft = ast_tvdiff_us(enddeltime, begintime);
6696  ft /= 1000000.0;
6697  ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
6698  ast_verb(3, "%s successfully loaded %d contexts (enable debug for details).\n", registrar, ctx_count);
6699 }
6700 
6701 /*
6702  * errno values
6703  * EBUSY - can't lock
6704  * ENOENT - no existence of context
6705  */
6706 int ast_context_add_include(const char *context, const char *include, const char *registrar)
6707 {
6708  int ret = -1;
6709  struct ast_context *c;
6710 
6711  c = find_context_locked(context);
6712  if (c) {
6713  ret = ast_context_add_include2(c, include, registrar);
6715  }
6716  return ret;
6717 }
6718 
6719 /*
6720  * errno values
6721  * ENOMEM - out of memory
6722  * EBUSY - can't lock
6723  * EEXIST - already included
6724  * EINVAL - there is no existence of context for inclusion
6725  */
6726 int ast_context_add_include2(struct ast_context *con, const char *value,
6727  const char *registrar)
6728 {
6729  struct ast_include *new_include;
6730  int idx;
6731 
6732  /* allocate new include structure ... */
6733  new_include = include_alloc(value, registrar);
6734  if (!new_include) {
6735  return -1;
6736  }
6737 
6738  ast_wrlock_context(con);
6739 
6740  /* ... go to last include and check if context is already included too... */
6741  for (idx = 0; idx < ast_context_includes_count(con); idx++) {
6742  const struct ast_include *i = ast_context_includes_get(con, idx);
6743 
6744  if (!strcasecmp(ast_get_include_name(i), ast_get_include_name(new_include))) {
6745  include_free(new_include);
6746  ast_unlock_context(con);
6747  errno = EEXIST;
6748  return -1;
6749  }
6750  }
6751 
6752  /* ... include new context into context list, unlock, return */
6753  if (AST_VECTOR_APPEND(&con->includes, new_include)) {
6754  include_free(new_include);
6755  ast_unlock_context(con);
6756  return -1;
6757  }
6758  ast_debug(1, "Including context '%s' in context '%s'\n",
6759  ast_get_include_name(new_include), ast_get_context_name(con));
6760 
6761  ast_unlock_context(con);
6762 
6763  return 0;
6764 }
6765 
6766 /*
6767  * errno values
6768  * EBUSY - can't lock
6769  * ENOENT - no existence of context
6770  */
6771 int ast_context_add_switch(const char *context, const char *sw, const char *data, int eval, const char *registrar)
6772 {
6773  int ret = -1;
6774  struct ast_context *c;
6775 
6776  c = find_context_locked(context);
6777  if (c) { /* found, add switch to this context */
6778  ret = ast_context_add_switch2(c, sw, data, eval, registrar);
6780  }
6781  return ret;
6782 }
6783 
6784 /*
6785  * errno values
6786  * ENOMEM - out of memory
6787  * EBUSY - can't lock
6788  * EEXIST - already included
6789  * EINVAL - there is no existence of context for inclusion
6790  */
6791 int ast_context_add_switch2(struct ast_context *con, const char *value,
6792  const char *data, int eval, const char *registrar)
6793 {
6794  int idx;
6795  struct ast_sw *new_sw;
6796 
6797  /* allocate new sw structure ... */
6798  if (!(new_sw = sw_alloc(value, data, eval, registrar))) {
6799  return -1;
6800  }
6801 
6802  /* ... try to lock this context ... */
6803  ast_wrlock_context(con);
6804 
6805  /* ... go to last sw and check if context is already swd too... */
6806  for (idx = 0; idx < ast_context_switches_count(con); idx++) {
6807  const struct ast_sw *i = ast_context_switches_get(con, idx);
6808 
6809  if (!strcasecmp(ast_get_switch_name(i), ast_get_switch_name(new_sw)) &&
6810  !strcasecmp(ast_get_switch_data(i), ast_get_switch_data(new_sw))) {
6811  sw_free(new_sw);
6812  ast_unlock_context(con);
6813  errno = EEXIST;
6814  return -1;
6815  }
6816  }
6817 
6818  /* ... sw new context into context list, unlock, return */
6819  if (AST_VECTOR_APPEND(&con->alts, new_sw)) {
6820  sw_free(new_sw);
6821  ast_unlock_context(con);
6822  return -1;
6823  }
6824 
6825  ast_verb(3, "Including switch '%s/%s' in context '%s'\n",
6827 
6828  ast_unlock_context(con);
6829 
6830  return 0;
6831 }
6832 
6833 /*
6834  * EBUSY - can't lock
6835  * ENOENT - there is not context existence
6836  */
6837 int ast_context_remove_ignorepat(const char *context, const char *ignorepat, const char *registrar)
6838 {
6839  int ret = -1;
6840  struct ast_context *c;
6841 
6842  c = find_context_locked(context);
6843  if (c) {
6844  ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
6846  }
6847  return ret;
6848 }
6849 
6850 int ast_context_remove_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
6851 {
6852  int idx;
6853 
6854  ast_wrlock_context(con);
6855 
6856  for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6857  struct ast_ignorepat *ip = AST_VECTOR_GET(&con->ignorepats, idx);
6858 
6859  if (!strcmp(ast_get_ignorepat_name(ip), ignorepat) &&
6860  (!registrar || (registrar == ast_get_ignorepat_registrar(ip)))) {
6862  ignorepat_free(ip);
6863  ast_unlock_context(con);
6864  return 0;
6865  }
6866  }
6867 
6868  ast_unlock_context(con);
6869  errno = EINVAL;
6870  return -1;
6871 }
6872 
6873 /*
6874  * EBUSY - can't lock
6875  * ENOENT - there is no existence of context
6876  */
6877 int ast_context_add_ignorepat(const char *context, const char *value, const char *registrar)
6878 {
6879  int ret = -1;
6880  struct ast_context *c;
6881 
6882  c = find_context_locked(context);
6883  if (c) {
6884  ret = ast_context_add_ignorepat2(c, value, registrar);
6886  }
6887  return ret;
6888 }
6889 
6890 int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
6891 {
6892  struct ast_ignorepat *ignorepat = ignorepat_alloc(value, registrar);
6893  int idx;
6894 
6895  if (!ignorepat) {
6896  return -1;
6897  }
6898 
6899  ast_wrlock_context(con);
6900  for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6901  const struct ast_ignorepat *i = ast_context_ignorepats_get(con, idx);
6902 
6903  if (!strcasecmp(ast_get_ignorepat_name(i), value)) {
6904  /* Already there */
6905  ast_unlock_context(con);
6906  ignorepat_free(ignorepat);
6907  errno = EEXIST;
6908  return -1;
6909  }
6910  }
6911  if (AST_VECTOR_APPEND(&con->ignorepats, ignorepat)) {
6912  ignorepat_free(ignorepat);
6913  ast_unlock_context(con);
6914  return -1;
6915  }
6916  ast_unlock_context(con);
6917 
6918  return 0;
6919 }
6920 
6921 int ast_ignore_pattern(const char *context, const char *pattern)
6922 {
6923  int ret = 0;
6924  struct ast_context *con;
6925 
6927  con = ast_context_find(context);
6928  if (con) {
6929  int idx;
6930 
6931  for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6932  const struct ast_ignorepat *pat = ast_context_ignorepats_get(con, idx);
6933 
6934  if (ast_extension_match(ast_get_ignorepat_name(pat), pattern)) {
6935  ret = 1;
6936  break;
6937  }
6938  }
6939  }
6941 
6942  return ret;
6943 }
6944 
6945 /*
6946  * ast_add_extension_nolock -- use only in situations where the conlock is already held
6947  * ENOENT - no existence of context
6948  *
6949  */
6950 static int ast_add_extension_nolock(const char *context, int replace, const char *extension,
6951  int priority, const char *label, const char *callerid,
6952  const char *application, void *data, void (*datad)(void *), const char *registrar)
6953 {
6954  int ret = -1;
6955  struct ast_context *c;
6956 
6957  c = find_context(context);
6958  if (c) {
6959  ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
6960  application, data, datad, registrar, NULL, 0, 1);
6961  }
6962 
6963  return ret;
6964 }
6965 /*
6966  * EBUSY - can't lock
6967  * ENOENT - no existence of context
6968  *
6969  */
6970 int ast_add_extension(const char *context, int replace, const char *extension,
6971  int priority, const char *label, const char *callerid,
6972  const char *application, void *data, void (*datad)(void *), const char *registrar)
6973 {
6974  int ret = -1;
6975  struct ast_context *c;
6976 
6977  c = find_context_locked(context);
6978  if (c) {
6979  ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
6980  application, data, datad, registrar, NULL, 0);
6982  }
6983 
6984  return ret;
6985 }
6986 
6987 int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
6988 {
6989  if (!chan)
6990  return -1;
6991 
6992  ast_channel_lock(chan);
6993 
6994  if (!ast_strlen_zero(context))
6995  ast_channel_context_set(chan, context);
6996  if (!ast_strlen_zero(exten))
6997  ast_channel_exten_set(chan, exten);
6998  if (priority > -1) {
6999  /* see flag description in channel.h for explanation */
7001  --priority;
7002  }
7003  ast_channel_priority_set(chan, priority);
7004  }
7005 
7006  ast_channel_unlock(chan);
7007 
7008  return 0;
7009 }
7010 
7011 int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
7012 {
7013  struct ast_channel *newchan;
7014 
7015  ast_channel_lock(chan);
7016  /* Channels in a bridge or running a PBX can be sent directly to the specified destination */
7017  if (ast_channel_is_bridged(chan) || ast_channel_pbx(chan)) {
7019  priority += 1;
7020  }
7021  ast_explicit_goto(chan, context, exten, priority);
7023  ast_channel_unlock(chan);
7024  return 0;
7025  }
7026  ast_channel_unlock(chan);
7027 
7028  /* Otherwise, we need to gain control of the channel first */
7029  newchan = ast_channel_yank(chan);
7030  if (!newchan) {
7031  ast_log(LOG_WARNING, "Unable to gain control of channel %s\n", ast_channel_name(chan));
7032  return -1;
7033  }
7034  ast_explicit_goto(newchan, context, exten, priority);
7035  if (ast_pbx_start(newchan)) {
7036  ast_hangup(newchan);
7037  ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(newchan));
7038  return -1;
7039  }
7040 
7041  return 0;
7042 }
7043 
7044 int ast_async_goto_by_name(const char *channame, const char *context, const char *exten, int priority)
7045 {
7046  struct ast_channel *chan;
7047  int res = -1;
7048 
7049  if ((chan = ast_channel_get_by_name(channame))) {
7050  res = ast_async_goto(chan, context, exten, priority);
7051  chan = ast_channel_unref(chan);
7052  }
7053 
7054  return res;
7055 }
7056 
7057 /*!
7058  * \internal
7059  * \brief Copy a string skipping whitespace and optionally dashes.
7060  *
7061  * \param dst Destination buffer to copy src string.
7062  * \param src Null terminated string to copy.
7063  * \param dst_size Number of bytes in the dst buffer.
7064  * \param nofluf Nonzero if '-' chars are not copied.
7065  *
7066  * \return Number of bytes written to dst including null terminator.
7067  */
7068 static unsigned int ext_strncpy(char *dst, const char *src, size_t dst_size, int nofluff)
7069 {
7070  unsigned int count;
7071  unsigned int insquares;
7072  unsigned int is_pattern;
7073 
7074  if (!dst_size--) {
7075  /* There really is no dst buffer */
7076  return 0;
7077  }
7078 
7079  count = 0;
7080  insquares = 0;
7081  is_pattern = *src == '_';
7082  while (*src && count < dst_size) {
7083  if (*src == '[') {
7084  if (is_pattern) {
7085  insquares = 1;
7086  }
7087  } else if (*src == ']') {
7088  insquares = 0;
7089  } else if (*src == ' ' && !insquares) {
7090  ++src;
7091  continue;
7092  } else if (*src == '-' && !insquares && nofluff) {
7093  ++src;
7094  continue;
7095  }
7096  *dst++ = *src++;
7097  ++count;
7098  }
7099  *dst = '\0';
7100 
7101  return count + 1;
7102 }
7103 
7104 /*!
7105  * \brief add the extension in the priority chain.
7106  * \retval 0 on success.
7107  * \retval -1 on failure.
7108 */
7109 static int add_priority(struct ast_context *con, struct ast_exten *tmp,
7110  struct ast_exten *el, struct ast_exten *e, int replace)
7111 {
7112  struct ast_exten *ep;
7113  struct ast_exten *eh=e;
7114  int repeated_label = 0; /* Track if this label is a repeat, assume no. */
7115 
7116  for (ep = NULL; e ; ep = e, e = e->peer) {
7117  if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
7118  if (strcmp(e->name, tmp->name)) {
7120  "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n",
7121  tmp->name, tmp->priority, con->name, tmp->label, e->name, e->priority);
7122  } else {
7124  "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n",
7125  tmp->name, tmp->priority, con->name, tmp->label, e->priority);
7126  }
7127  repeated_label = 1;
7128  }
7129  if (e->priority >= tmp->priority) {
7130  break;
7131  }
7132  }
7133 
7134  if (repeated_label) { /* Discard the label since it's a repeat. */
7135  tmp->label = NULL;
7136  }
7137 
7138  if (!e) { /* go at the end, and ep is surely set because the list is not empty */
7140 
7141  if (tmp->label) {
7143  }
7144  ep->peer = tmp;
7145  return 0; /* success */
7146  }
7147  if (e->priority == tmp->priority) {
7148  /* Can't have something exactly the same. Is this a
7149  replacement? If so, replace, otherwise, bonk. */
7150  if (!replace) {
7151  if (strcmp(e->name, tmp->name)) {
7153  "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n",
7154  tmp->name, tmp->priority, con->name, e->name);
7155  } else {
7157  "Unable to register extension '%s' priority %d in '%s', already in use\n",
7158  tmp->name, tmp->priority, con->name);
7159  }
7160 
7161  return -1;
7162  }
7163  /* we are replacing e, so copy the link fields and then update
7164  * whoever pointed to e to point to us
7165  */
7166  tmp->next = e->next; /* not meaningful if we are not first in the peer list */
7167  tmp->peer = e->peer; /* always meaningful */
7168  if (ep) { /* We're in the peer list, just insert ourselves */
7170 
7171  if (e->label) {
7173  }
7174 
7176  if (tmp->label) {
7178  }
7179 
7180  ep->peer = tmp;
7181  } else if (el) { /* We're the first extension. Take over e's functions */
7182  struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
7183  tmp->peer_table = e->peer_table;
7184  tmp->peer_label_table = e->peer_label_table;
7187  if (e->label) {
7189  }
7190  if (tmp->label) {
7192  }
7193 
7196  el->next = tmp;
7197  /* The pattern trie points to this exten; replace the pointer,
7198  and all will be well */
7199  if (x) { /* if the trie isn't formed yet, don't sweat this */
7200  if (x->exten) { /* this test for safety purposes */
7201  x->exten = tmp; /* replace what would become a bad pointer */
7202  } else {
7203  ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
7204  }
7205  }
7206  } else { /* We're the very first extension. */
7207  struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
7210  tmp->peer_table = e->peer_table;
7211  tmp->peer_label_table = e->peer_label_table;
7214  if (e->label) {
7216  }
7217  if (tmp->label) {
7219  }
7220 
7223  con->root = tmp;
7224  /* The pattern trie points to this exten; replace the pointer,
7225  and all will be well */
7226  if (x) { /* if the trie isn't formed yet; no problem */
7227  if (x->exten) { /* this test for safety purposes */
7228  x->exten = tmp; /* replace what would become a bad pointer */
7229  } else {
7230  ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
7231  }
7232  }
7233  }
7234  if (tmp->priority == PRIORITY_HINT)
7235  ast_change_hint(e,tmp);
7236  /* Destroy the old one */
7237  if (e->datad)
7238  e->datad(e->data);
7239  ast_free(e);
7240  } else { /* Slip ourselves in just before e */
7241  tmp->peer = e;
7242  tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
7243  if (ep) { /* Easy enough, we're just in the peer list */
7244  if (tmp->label) {
7246  }
7248  ep->peer = tmp;
7249  } else { /* we are the first in some peer list, so link in the ext list */
7250  tmp->peer_table = e->peer_table;
7251  tmp->peer_label_table = e->peer_label_table;
7252  e->peer_table = 0;
7253  e->peer_label_table = 0;
7255  if (tmp->label) {
7257  }
7260  if (el)
7261  el->next = tmp; /* in the middle... */
7262  else
7263  con->root = tmp; /* ... or at the head */
7264  e->next = NULL; /* e is no more at the head, so e->next must be reset */
7265  }
7266  /* And immediately return success. */
7267  if (tmp->priority == PRIORITY_HINT) {
7268  ast_add_hint(tmp);
7269  }
7270  }
7271  return 0;
7272 }
7273 
7274 /*! \brief
7275  * Main interface to add extensions to the list for out context.
7276  *
7277  * We sort extensions in order of matching preference, so that we can
7278  * stop the search as soon as we find a suitable match.
7279  * This ordering also takes care of wildcards such as '.' (meaning
7280  * "one or more of any character") and '!' (which is 'earlymatch',
7281  * meaning "zero or more of any character" but also impacts the
7282  * return value from CANMATCH and EARLYMATCH.
7283  *
7284  * The extension match rules defined in the devmeeting 2006.05.05 are
7285  * quite simple: WE SELECT THE LONGEST MATCH.
7286  * In detail, "longest" means the number of matched characters in
7287  * the extension. In case of ties (e.g. _XXX and 333) in the length
7288  * of a pattern, we give priority to entries with the smallest cardinality
7289  * (e.g, [5-9] comes before [2-8] before the former has only 5 elements,
7290  * while the latter has 7, etc.
7291  * In case of same cardinality, the first element in the range counts.
7292  * If we still have a tie, any final '!' will make this as a possibly
7293  * less specific pattern.
7294  *
7295  * EBUSY - can't lock
7296  * EEXIST - extension with the same priority exist and no replace is set
7297  *
7298  */
7300  int replace, const char *extension, int priority, const char *label, const char *callerid,
7301  const char *application, void *data, void (*datad)(void *),
7302  const char *registrar, const char *registrar_file, int registrar_line)
7303 {
7304  return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
7305  application, data, datad, registrar, registrar_file, registrar_line, 1);
7306 }
7307 
7309  int replace, const char *extension, int priority, const char *label, const char *callerid,
7310  const char *application, void *data, void (*datad)(void *),
7311  const char *registrar, const char *registrar_file, int registrar_line)
7312 {
7313  return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
7314  application, data, datad, registrar, registrar_file, registrar_line, 0);
7315 }
7316 
7317 
7318 /*!
7319  * \brief Same as ast_add_extension2() but controls the context locking.
7320  *
7321  * \details
7322  * Does all the work of ast_add_extension2, but adds an arg to
7323  * determine if context locking should be done.
7324  */
7326  int replace, const char *extension, int priority, const char *label, const char *callerid,
7327  const char *application, void *data, void (*datad)(void *),
7328  const char *registrar, const char *registrar_file, int registrar_line, int lock_context)
7329 {
7330  /*
7331  * Sort extensions (or patterns) according to the rules indicated above.
7332  * These are implemented by the function ext_cmp()).
7333  * All priorities for the same ext/pattern/cid are kept in a list,
7334  * using the 'peer' field as a link field..
7335  */
7336  struct ast_exten *tmp, *tmp2, *e, *el = NULL;
7337  int res;
7338  int length;
7339  char *p;
7340  char expand_buf[VAR_BUF_SIZE];
7341  struct ast_exten dummy_exten = {0};
7342  char dummy_name[1024];
7343  int exten_fluff;
7344  int callerid_fluff;
7345 
7346  if (ast_strlen_zero(extension)) {
7347  ast_log(LOG_ERROR,"You have to be kidding-- add exten '' to context %s? Figure out a name and call me back. Action ignored.\n",
7348  con->name);
7349  /* We always need to deallocate 'data' on failure */
7350  if (datad) {
7351  datad(data);
7352  }
7353  return -1;
7354  }
7355 
7356  /* If we are adding a hint evalulate in variables and global variables */
7357  if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') {
7358  int inhibited;
7360 
7361  if (c) {
7362  ast_channel_exten_set(c, extension);
7363  ast_channel_context_set(c, con->name);
7364  }
7365 
7366  /*
7367  * We can allow dangerous functions when adding a hint since
7368  * altering dialplan is itself a privileged activity. Otherwise,
7369  * we could never execute dangerous functions.
7370  */
7371  inhibited = ast_thread_inhibit_escalations_swap(0);
7372  pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
7373  if (0 < inhibited) {
7375  }
7376 
7377  application = expand_buf;
7378  if (c) {
7379  ast_channel_unref(c);
7380  }
7381  }
7382 
7383  exten_fluff = ext_fluff_count(extension);
7384  callerid_fluff = callerid ? ext_fluff_count(callerid) : 0;
7385 
7386  length = sizeof(struct ast_exten);
7387  length += strlen(extension) + 1;
7388  if (exten_fluff) {
7389  length += strlen(extension) + 1 - exten_fluff;
7390  }
7391  length += strlen(application) + 1;
7392  if (label) {
7393  length += strlen(label) + 1;
7394  }
7395  if (callerid) {
7396  length += strlen(callerid) + 1;
7397  if (callerid_fluff) {
7398  length += strlen(callerid) + 1 - callerid_fluff;
7399  }
7400  } else {
7401  length ++; /* just the '\0' */
7402  }
7403  if (registrar_file) {
7404  length += strlen(registrar_file) + 1;
7405  }
7406 
7407  /* Be optimistic: Build the extension structure first */
7408  tmp = ast_calloc(1, length);
7409  if (!tmp) {
7410  /* We always need to deallocate 'data' on failure */
7411  if (datad) {
7412  datad(data);
7413  }
7414  return -1;
7415  }
7416 
7417  if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
7418  label = 0;
7419 
7420  /* use p as dst in assignments, as the fields are const char * */
7421  p = tmp->stuff;
7422  if (label) {
7423  tmp->label = p;
7424  strcpy(p, label);
7425  p += strlen(label) + 1;
7426  }
7427  tmp->name = p;
7428  p += ext_strncpy(p, extension, strlen(extension) + 1, 0);
7429  if (exten_fluff) {
7430  tmp->exten = p;
7431  p += ext_strncpy(p, extension, strlen(extension) + 1 - exten_fluff, 1);
7432  } else {
7433  /* no fluff, we don't need a copy. */
7434  tmp->exten = tmp->name;
7435  }
7436  tmp->priority = priority;
7437  tmp->cidmatch_display = tmp->cidmatch = p; /* but use p for assignments below */
7438 
7439  /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */
7440  if (callerid) {
7441  p += ext_strncpy(p, callerid, strlen(callerid) + 1, 0);
7442  if (callerid_fluff) {
7443  tmp->cidmatch = p;
7444  p += ext_strncpy(p, callerid, strlen(callerid) + 1 - callerid_fluff, 1);
7445  }
7447  } else {
7448  *p++ = '\0';
7450  }
7451 
7452  if (registrar_file) {
7453  tmp->registrar_file = p;
7454  strcpy(p, registrar_file);
7455  p += strlen(registrar_file) + 1;
7456  } else {
7457  tmp->registrar_file = NULL;
7458  }
7459 
7460  tmp->app = p;
7461  strcpy(p, application);
7462  tmp->parent = con;
7463  tmp->data = data;
7464  tmp->datad = datad;
7465  tmp->registrar = registrar;
7467 
7468  if (lock_context) {
7469  ast_wrlock_context(con);
7470  }
7471 
7472  if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
7473  an extension, and the trie exists, then we need to incrementally add this pattern to it. */
7474  ext_strncpy(dummy_name, tmp->exten, sizeof(dummy_name), 1);
7475  dummy_exten.exten = dummy_name;
7476  dummy_exten.matchcid = AST_EXT_MATCHCID_OFF;
7477  dummy_exten.cidmatch = 0;
7478  tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
7479  if (!tmp2) {
7480  /* hmmm, not in the trie; */
7481  add_exten_to_pattern_tree(con, tmp, 0);
7482  ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
7483  }
7484  }
7485  res = 0; /* some compilers will think it is uninitialized otherwise */
7486  for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */
7487  res = ext_cmp(e->exten, tmp->exten);
7488  if (res == 0) { /* extension match, now look at cidmatch */
7490  res = 0;
7491  else if (tmp->matchcid == AST_EXT_MATCHCID_ON && e->matchcid == AST_EXT_MATCHCID_OFF)
7492  res = 1;
7493  else if (e->matchcid == AST_EXT_MATCHCID_ON && tmp->matchcid == AST_EXT_MATCHCID_OFF)
7494  res = -1;
7495  else
7496  res = ext_cmp(e->cidmatch, tmp->cidmatch);
7497  }
7498  if (res >= 0)
7499  break;
7500  }
7501  if (e && res == 0) { /* exact match, insert in the priority chain */
7502  res = add_priority(con, tmp, el, e, replace);
7503  if (res < 0) {
7504  if (con->pattern_tree) {
7505  struct match_char *x = add_exten_to_pattern_tree(con, tmp, 1);
7506 
7507  if (x->exten) {
7508  x->deleted = 1;
7509  x->exten = 0;
7510  }
7511 
7513  }
7514 
7515  if (tmp->datad) {
7516  tmp->datad(tmp->data);
7517  /* if you free this, null it out */
7518  tmp->data = NULL;
7519  }
7520 
7521  ast_free(tmp);
7522  }
7523  if (lock_context) {
7524  ast_unlock_context(con);
7525  }
7526  if (res < 0) {
7527  errno = EEXIST;
7528  return -1;
7529  }
7530  } else {
7531  /*
7532  * not an exact match, this is the first entry with this pattern,
7533  * so insert in the main list right before 'e' (if any)
7534  */
7535  tmp->next = e;
7536  tmp->peer_table = ast_hashtab_create(13,
7541  0);
7547  0);
7548 
7549  if (el) { /* there is another exten already in this context */
7550  el->next = tmp;
7551  } else { /* this is the first exten in this context */
7552  if (!con->root_table) {
7553  con->root_table = ast_hashtab_create(27,
7558  0);
7559  }
7560  con->root = tmp;
7561  }
7562  if (label) {
7564  }
7567 
7568  if (lock_context) {
7569  ast_unlock_context(con);
7570  }
7571  if (tmp->priority == PRIORITY_HINT) {
7572  ast_add_hint(tmp);
7573  }
7574  }
7575  if (DEBUG_ATLEAST(1)) {
7576  if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
7577  ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
7578  tmp->name, tmp->priority, tmp->cidmatch_display, con->name, con);
7579  } else {
7580  ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s (%p)\n",
7581  tmp->name, tmp->priority, con->name, con);
7582  }
7583  }
7584 
7585  return 0;
7586 }
7587 
7588 /*! \brief Structure which contains information about an outgoing dial */
7590  /*! \brief Dialing structure being used */
7591  struct ast_dial *dial;
7592  /*! \brief Condition for synchronous dialing */
7594  /*! \brief Application to execute */
7596  /*! \brief Application data to pass to application */
7597  char *appdata;
7598  /*! \brief Dialplan context */
7599  char context[AST_MAX_CONTEXT];
7600  /*! \brief Dialplan extension */
7602  /*! \brief Dialplan priority */
7604  /*! \brief Result of the dial operation when dialed is set */
7606  /*! \brief Set when dialing is completed */
7607  unsigned int dialed:1;
7608  /*! \brief Set if we've spawned a thread to do our work */
7609  unsigned int in_separate_thread:1;
7610 };
7611 
7612 /*! \brief Destructor for outgoing structure */
7613 static void pbx_outgoing_destroy(void *obj)
7614 {
7615  struct pbx_outgoing *outgoing = obj;
7616 
7617  if (outgoing->dial) {
7618  ast_dial_destroy(outgoing->dial);
7619  }
7620 
7621  ast_cond_destroy(&outgoing->cond);
7622 
7623  ast_free(outgoing->appdata);
7624 }
7625 
7626 /*! \brief Internal function which dials an outgoing leg and sends it to a provided extension or application */
7627 static void *pbx_outgoing_exec(void *data)
7628 {
7629  RAII_VAR(struct pbx_outgoing *, outgoing, data, ao2_cleanup);
7630  enum ast_dial_result res;
7631  struct ast_channel *chan;
7632 
7633  res = ast_dial_run(outgoing->dial, NULL, 0);
7634 
7635  if (outgoing->in_separate_thread) {
7636  /* Notify anyone interested that dialing is complete */
7637  ao2_lock(outgoing);
7638  outgoing->dial_res = res;
7639  outgoing->dialed = 1;
7640  ast_cond_signal(&outgoing->cond);
7642  } else {
7643  /* We still need the dial result, but we don't need to lock */
7644  outgoing->dial_res = res;
7645  }
7646 
7647  /* If the outgoing leg was not answered we can immediately return and go no further */
7648  if (res != AST_DIAL_RESULT_ANSWERED) {
7649  return NULL;
7650  }
7651 
7652  /* We steal the channel so we get ownership of when it is hung up */
7653  chan = ast_dial_answered_steal(outgoing->dial);
7654 
7655  if (!ast_strlen_zero(outgoing->app)) {
7656  struct ast_app *app = pbx_findapp(outgoing->app);
7657 
7658  if (app) {
7659  ast_verb(4, "Launching %s(%s) on %s\n", outgoing->app, S_OR(outgoing->appdata, ""),
7660  ast_channel_name(chan));
7661  pbx_exec(chan, app, outgoing->appdata);
7662  } else {
7663  ast_log(LOG_WARNING, "No such application '%s'\n", outgoing->app);
7664  }
7665 
7666  ast_hangup(chan);
7667  } else {
7668  if (!ast_strlen_zero(outgoing->context)) {
7670  }
7671 
7672  if (!ast_strlen_zero(outgoing->exten)) {
7674  }
7675 
7676  if (outgoing->priority > 0) {
7678  }
7679 
7680  if (ast_pbx_run(chan)) {
7681  ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(chan));
7682  ast_hangup(chan);
7683  }
7684  }
7685 
7686  return NULL;
7687 }
7688 
7689 /*! \brief Internal dialing state callback which causes early media to trigger an answer */
7690 static void pbx_outgoing_state_callback(struct ast_dial *dial)
7691 {
7692  struct ast_channel *channel;
7693 
7695  return;
7696  }
7697 
7698  if (!(channel = ast_dial_get_channel(dial, 0))) {
7699  return;
7700  }
7701 
7702  ast_verb(4, "Treating progress as answer on '%s' due to early media option\n",
7703  ast_channel_name(channel));
7704 
7706 }
7707 
7708 /*!
7709  * \brief Attempt to convert disconnect cause to old originate reason.
7710  *
7711  * \todo XXX The old originate reasons need to be trashed and replaced
7712  * with normal disconnect cause codes if the call was not answered.
7713  * The internal consumers of the reason values would also need to be
7714  * updated: app_originate, call files, and AMI OriginateResponse.
7715  */
7716 static enum ast_control_frame_type pbx_dial_reason(enum ast_dial_result dial_result, int cause)
7717 {
7718  enum ast_control_frame_type pbx_reason;
7719 
7720  if (dial_result == AST_DIAL_RESULT_ANSWERED) {
7721  /* Remote end answered. */
7722  pbx_reason = AST_CONTROL_ANSWER;
7723  } else if (dial_result == AST_DIAL_RESULT_HANGUP) {
7724  /* Caller hungup */
7725  pbx_reason = AST_CONTROL_HANGUP;
7726  } else {
7727  switch (cause) {
7728  case AST_CAUSE_USER_BUSY:
7729  pbx_reason = AST_CONTROL_BUSY;
7730  break;
7737  pbx_reason = AST_CONTROL_CONGESTION;
7738  break;
7740  case AST_CAUSE_NO_ANSWER:
7741  /* Remote end was ringing (but isn't anymore) */
7742  pbx_reason = AST_CONTROL_RINGING;
7743  break;
7744  case AST_CAUSE_UNALLOCATED:
7745  default:
7746  /* Call Failure (not BUSY, and not NO_ANSWER, maybe Circuit busy or down?) */
7747  pbx_reason = 0;
7748  break;
7749  }
7750  }
7751 
7752  return pbx_reason;
7753 }
7754 
7755 static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap,
7756  const char *addr, int timeout, const char *context, const char *exten, int priority,
7757  const char *app, const char *appdata, int *reason, int synchronous,
7758  const char *cid_num, const char *cid_name, struct ast_variable *vars,
7759  const char *account, struct ast_channel **locked_channel, int early_media,
7760  const struct ast_assigned_ids *assignedids, const char *predial_callee)
7761 {
7763  struct ast_channel *dialed;
7764  pthread_t thread;
7765  char tmp_cid_name[128];
7766  char tmp_cid_num[128];
7767 
7769  if (!outgoing) {
7770  return -1;
7771  }
7772  ast_cond_init(&outgoing->cond, NULL);
7773 
7774  if (!ast_strlen_zero(app)) {
7775  ast_copy_string(outgoing->app, app, sizeof(outgoing->app));
7776  outgoing->appdata = ast_strdup(appdata);
7777  } else {
7778  ast_copy_string(outgoing->context, context, sizeof(outgoing->context));
7779  ast_copy_string(outgoing->exten, exten, sizeof(outgoing->exten));
7781  }
7782 
7783  if (!(outgoing->dial = ast_dial_create())) {
7784  return -1;
7785  }
7786 
7787  if (ast_dial_append(outgoing->dial, type, addr, assignedids)) {
7788  return -1;
7789  }
7790 
7791  ast_dial_set_global_timeout(outgoing->dial, timeout);
7792 
7793  if (!ast_strlen_zero(predial_callee)) {
7794  /* note casting to void * here to suppress compiler warning message (passing const to non-const function) */
7795  ast_dial_option_global_enable(outgoing->dial, AST_DIAL_OPTION_PREDIAL, (void *)predial_callee);
7796  }
7797 
7798  if (ast_dial_prerun(outgoing->dial, NULL, cap)) {
7799  if (synchronous && reason) {
7801  ast_dial_reason(outgoing->dial, 0));
7802  }
7803  return -1;
7804  }
7805 
7806  dialed = ast_dial_get_channel(outgoing->dial, 0);
7807  if (!dialed) {
7808  return -1;
7809  }
7810 
7811  ast_channel_lock(dialed);
7812  if (vars) {
7813  ast_set_variables(dialed, vars);
7814  }
7815  if (!ast_strlen_zero(account)) {
7817  ast_channel_accountcode_set(dialed, account);
7818  ast_channel_peeraccount_set(dialed, account);
7820  }
7822 
7823  if (!ast_strlen_zero(predial_callee)) {
7824  char *tmp = NULL;
7825  /*
7826  * The predial sub routine may have set callerid so set this into the new channel
7827  * Note... cid_num and cid_name parameters to this function will always be NULL if
7828  * predial_callee is non-NULL so we are not overwriting anything here.
7829  */
7830  tmp = S_COR(ast_channel_caller(dialed)->id.number.valid, ast_channel_caller(dialed)->id.number.str, NULL);
7831  if (tmp) {
7832  ast_copy_string(tmp_cid_num, tmp, sizeof(tmp_cid_num));
7833  cid_num = tmp_cid_num;
7834  }
7835  tmp = S_COR(ast_channel_caller(dialed)->id.name.valid, ast_channel_caller(dialed)->id.name.str, NULL);
7836  if (tmp) {
7837  ast_copy_string(tmp_cid_name, tmp, sizeof(tmp_cid_name));
7838  cid_name = tmp_cid_name;
7839  }
7840  }
7841  ast_channel_unlock(dialed);
7842 
7843  if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) {
7844  struct ast_party_connected_line connected;
7845 
7846  /*
7847  * It seems strange to set the CallerID on an outgoing call leg
7848  * to whom we are calling, but this function's callers are doing
7849  * various Originate methods. This call leg goes to the local
7850  * user. Once the called party answers, the dialplan needs to
7851  * be able to access the CallerID from the CALLERID function as
7852  * if the called party had placed this call.
7853  */
7854  ast_set_callerid(dialed, cid_num, cid_name, cid_num);
7855 
7857  if (!ast_strlen_zero(cid_num)) {
7858  connected.id.number.valid = 1;
7859  connected.id.number.str = (char *) cid_num;
7861  }
7862  if (!ast_strlen_zero(cid_name)) {
7863  connected.id.name.valid = 1;
7864  connected.id.name.str = (char *) cid_name;
7866  }
7867  ast_channel_set_connected_line(dialed, &connected, NULL);
7868  }
7869 
7870  if (early_media) {
7872  }
7873 
7874  if (locked_channel) {
7875  /*
7876  * Keep a dialed channel ref since the caller wants
7877  * the channel returned. We must get the ref before
7878  * spawning off pbx_outgoing_exec().
7879  */
7880  ast_channel_ref(dialed);
7881  if (!synchronous) {
7882  /*
7883  * Lock it now to hold off pbx_outgoing_exec() in case the
7884  * calling function needs the channel state/snapshot before
7885  * dialing actually happens.
7886  */
7887  ast_channel_lock(dialed);
7888  }
7889  }
7890 
7891  /* This extra reference is dereferenced by pbx_outgoing_exec */
7892  ao2_ref(outgoing, +1);
7893 
7894  if (synchronous == AST_OUTGOING_WAIT_COMPLETE) {
7895  /*
7896  * Because we are waiting until this is complete anyway, there is no
7897  * sense in creating another thread that we will just need to wait
7898  * for, so instead we commandeer the current thread.
7899  */
7901  } else {
7902  outgoing->in_separate_thread = 1;
7903 
7905  ast_log(LOG_WARNING, "Unable to spawn dialing thread for '%s/%s'\n", type, addr);
7906  ao2_ref(outgoing, -1);
7907  if (locked_channel) {
7908  if (!synchronous) {
7909  ast_channel_unlock(dialed);
7910  }
7911  ast_channel_unref(dialed);
7912  }
7913  return -1;
7914  }
7915 
7916  if (synchronous) {
7917  ao2_lock(outgoing);
7918  /* Wait for dialing to complete */
7919  while (!outgoing->dialed) {
7921  }
7923  }
7924  }
7925 
7926  if (synchronous) {
7927  /* Determine the outcome of the dialing attempt up to it being answered. */
7928  if (reason) {
7929  *reason = pbx_dial_reason(outgoing->dial_res,
7930  ast_dial_reason(outgoing->dial, 0));
7931  }
7932 
7933  if (outgoing->dial_res != AST_DIAL_RESULT_ANSWERED) {
7934  /* The dial operation failed. */
7935  if (locked_channel) {
7936  ast_channel_unref(dialed);
7937  }
7938  return -1;
7939  }
7940  if (locked_channel) {
7941  ast_channel_lock(dialed);
7942  }
7943  }
7944 
7945  if (locked_channel) {
7946  *locked_channel = dialed;
7947  }
7948  return 0;
7949 }
7950 
7951 int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr,
7952  int timeout, const char *context, const char *exten, int priority, int *reason,
7953  int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars,
7954  const char *account, struct ast_channel **locked_channel, int early_media,
7955  const struct ast_assigned_ids *assignedids)
7956 {
7957  return ast_pbx_outgoing_exten_predial(type, cap, addr, timeout, context, exten, priority, reason,
7958  synchronous, cid_num, cid_name, vars, account, locked_channel, early_media, assignedids, NULL);
7959 }
7960 
7961 int ast_pbx_outgoing_exten_predial(const char *type, struct ast_format_cap *cap, const char *addr,
7962  int timeout, const char *context, const char *exten, int priority, int *reason,
7963  int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars,
7964  const char *account, struct ast_channel **locked_channel, int early_media,
7965  const struct ast_assigned_ids *assignedids, const char *predial_callee)
7966 {
7967  int res;
7968  int my_reason;
7969 
7970  if (!reason) {
7971  reason = &my_reason;
7972  }
7973  *reason = 0;
7974  if (locked_channel) {
7975  *locked_channel = NULL;
7976  }
7977 
7978  res = pbx_outgoing_attempt(type, cap, addr, timeout, context, exten, priority,
7979  NULL, NULL, reason, synchronous, cid_num, cid_name, vars, account, locked_channel,
7980  early_media, assignedids, predial_callee);
7981 
7982  if (res < 0 /* Call failed to get connected for some reason. */
7983  && 0 < synchronous
7984  && ast_exists_extension(NULL, context, "failed", 1, NULL)) {
7985  struct ast_channel *failed;
7986 
7987  /* We do not have to worry about a locked_channel if dialing failed. */
7988  ast_assert(!locked_channel || !*locked_channel);
7989 
7990  /*!
7991  * \todo XXX Not good. The channel name is not unique if more than
7992  * one originate fails at a time.
7993  */
7994  failed = ast_channel_alloc(0, AST_STATE_DOWN, cid_num, cid_name, account,
7995  "failed", context, NULL, NULL, 0, "OutgoingSpoolFailed");
7996  if (failed) {
7997  char failed_reason[12];
7998 
7999  ast_set_variables(failed, vars);
8000  snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
8001  pbx_builtin_setvar_helper(failed, "REASON", failed_reason);
8002  ast_channel_unlock(failed);
8003 
8004  if (ast_pbx_run(failed)) {
8005  ast_log(LOG_ERROR, "Unable to run PBX on '%s'\n",
8006  ast_channel_name(failed));
8007  ast_hangup(failed);
8008  }
8009  }
8010  }
8011 
8012  return res;
8013 }
8014 
8015 int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const char *addr,
8016  int timeout, const char *app, const char *appdata, int *reason, int synchronous,
8017  const char *cid_num, const char *cid_name, struct ast_variable *vars,
8018  const char *account, struct ast_channel **locked_channel,
8019  const struct ast_assigned_ids *assignedids)
8020 {
8021  return ast_pbx_outgoing_app_predial(type, cap, addr, timeout, app, appdata, reason, synchronous,
8022  cid_num, cid_name, vars, account, locked_channel, assignedids, NULL);
8023 }
8024 
8025 int ast_pbx_outgoing_app_predial(const char *type, struct ast_format_cap *cap, const char *addr,
8026  int timeout, const char *app, const char *appdata, int *reason, int synchronous,
8027  const char *cid_num, const char *cid_name, struct ast_variable *vars,
8028  const char *account, struct ast_channel **locked_channel,
8029  const struct ast_assigned_ids *assignedids, const char *predial_callee)
8030 {
8031  if (reason) {
8032  *reason = 0;
8033  }
8034  if (locked_channel) {
8035  *locked_channel = NULL;
8036  }
8037  if (ast_strlen_zero(app)) {
8038  return -1;
8039  }
8040 
8041  return pbx_outgoing_attempt(type, cap, addr, timeout, NULL, NULL, 0, app, appdata,
8042  reason, synchronous, cid_num, cid_name, vars, account, locked_channel, 0,
8043  assignedids, predial_callee);
8044 }
8045 
8046 /* this is the guts of destroying a context --
8047  freeing up the structure, traversing and destroying the
8048  extensions, switches, ignorepats, includes, etc. etc. */
8049 
8051 {
8052  struct ast_exten *e, *el, *en;
8053  struct ast_context *tmp = con;
8054 
8055  /* Free includes */
8057  AST_VECTOR_FREE(&tmp->includes);
8058 
8059  /* Free ignorepats */
8061  AST_VECTOR_FREE(&tmp->ignorepats);
8062 
8063  /* Free switches */
8065  AST_VECTOR_FREE(&tmp->alts);
8066 
8067  if (tmp->registrar)
8068  ast_free(tmp->registrar);
8069 
8070  /* destroy the hash tabs */
8071  if (tmp->root_table) {
8073  }
8074  /* and destroy the pattern tree */
8075  if (tmp->pattern_tree)
8077 
8078  for (e = tmp->root; e;) {
8079  for (en = e->peer; en;) {
8080  el = en;
8081  en = en->peer;
8082  destroy_exten(el);
8083  }
8084  el = e;
8085  e = e->next;
8086  destroy_exten(el);
8087  }
8088  tmp->root = NULL;
8089  ast_rwlock_destroy(&tmp->lock);
8091  ast_free(tmp);
8092 }
8093 
8094 
8095 void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
8096 {
8097  struct ast_context *tmp, *tmpl=NULL;
8098  struct ast_exten *exten_item, *prio_item;
8099 
8100  for (tmp = list; tmp; ) {
8101  struct ast_context *next = NULL; /* next starting point */
8102  /* The following code used to skip forward to the next
8103  context with matching registrar, but this didn't
8104  make sense; individual priorities registrar'd to
8105  the matching registrar could occur in any context! */
8106  ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
8107  if (con) {
8108  for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
8109  ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
8110  if ( !strcasecmp(tmp->name, con->name) ) {
8111  break; /* found it */
8112  }
8113  }
8114  }
8115 
8116  if (!tmp) /* not found, we are done */
8117  break;
8118  ast_wrlock_context(tmp);
8119 
8120  if (registrar) {
8121  /* then search thru and remove any extens that match registrar. */
8122  struct ast_hashtab_iter *exten_iter;
8123  struct ast_hashtab_iter *prio_iter;
8124  int idx;
8125 
8126  /* remove any ignorepats whose registrar matches */
8127  for (idx = ast_context_ignorepats_count(tmp) - 1; idx >= 0; idx--) {
8128  struct ast_ignorepat *ip = AST_VECTOR_GET(&tmp->ignorepats, idx);
8129 
8130  if (!strcmp(ast_get_ignorepat_registrar(ip), registrar)) {
8132  ignorepat_free(ip);
8133  }
8134  }
8135  /* remove any includes whose registrar matches */
8136  for (idx = ast_context_includes_count(tmp) - 1; idx >= 0; idx--) {
8137  struct ast_include *i = AST_VECTOR_GET(&tmp->includes, idx);
8138 
8139  if (!strcmp(ast_get_include_registrar(i), registrar)) {
8140  AST_VECTOR_REMOVE_ORDERED(&tmp->includes, idx);
8141  include_free(i);
8142  }
8143  }
8144  /* remove any switches whose registrar matches */
8145  for (idx = ast_context_switches_count(tmp) - 1; idx >= 0; idx--) {
8146  struct ast_sw *sw = AST_VECTOR_GET(&tmp->alts, idx);
8147 
8148  if (!strcmp(ast_get_switch_registrar(sw), registrar)) {
8149  AST_VECTOR_REMOVE_ORDERED(&tmp->alts, idx);
8150  sw_free(sw);
8151  }
8152  }
8153 
8154  if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
8155  exten_iter = ast_hashtab_start_traversal(tmp->root_table);
8156  while ((exten_item=ast_hashtab_next(exten_iter))) {
8157  int end_traversal = 1;
8158 
8159  /*
8160  * If the extension could not be removed from the root_table due to
8161  * a loaded PBX app, it can exist here but have its peer_table be
8162  * destroyed due to a previous pass through this function.
8163  */
8164  if (!exten_item->peer_table) {
8165  continue;
8166  }
8167 
8168  prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
8169  while ((prio_item=ast_hashtab_next(prio_iter))) {
8170  char extension[AST_MAX_EXTENSION];
8172  if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
8173  continue;
8174  }
8175  ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
8176  tmp->name, prio_item->name, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
8177  ast_copy_string(extension, prio_item->exten, sizeof(extension));
8178  if (prio_item->cidmatch) {
8179  ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch));
8180  }
8181  end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, cidmatch, prio_item->matchcid, NULL, 1);
8182  }
8183  /* Explanation:
8184  * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This
8185  * destruction includes destroying the exten's peer_table, which we are currently traversing. If
8186  * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed
8187  * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result
8188  * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply
8189  * free the iterator
8190  */
8191  if (end_traversal) {
8192  ast_hashtab_end_traversal(prio_iter);
8193  } else {
8194  ast_free(prio_iter);
8195  }
8196  }
8197  ast_hashtab_end_traversal(exten_iter);
8198  }
8199 
8200  /* delete the context if it's registrar matches, is empty, has refcount of 1, */
8201  /* it's not empty, if it has includes, ignorepats, or switches that are registered from
8202  another registrar. It's not empty if there are any extensions */
8203  if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !ast_context_ignorepats_count(tmp) && !ast_context_includes_count(tmp) && !ast_context_switches_count(tmp)) {
8204  ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
8205  ast_hashtab_remove_this_object(contexttab, tmp);
8206 
8207  next = tmp->next;
8208  if (tmpl)
8209  tmpl->next = next;
8210  else
8211  contexts = next;
8212  /* Okay, now we're safe to let it go -- in a sense, we were
8213  ready to let it go as soon as we locked it. */
8214  ast_unlock_context(tmp);
8216  } else {
8217  ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
8218  tmp->refcount, tmp->root);
8219  ast_unlock_context(tmp);
8220  next = tmp->next;
8221  tmpl = tmp;
8222  }
8223  } else if (con) {
8224  ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
8225  ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
8226  ast_hashtab_remove_this_object(contexttab, tmp);
8227 
8228  next = tmp->next;
8229  if (tmpl)
8230  tmpl->next = next;
8231  else
8232  contexts = next;
8233  /* Okay, now we're safe to let it go -- in a sense, we were
8234  ready to let it go as soon as we locked it. */
8235  ast_unlock_context(tmp);
8237  }
8238 
8239  /* if we have a specific match, we are done, otherwise continue */
8240  tmp = con ? NULL : next;
8241  }
8242 }
8243 
8244 int ast_context_destroy_by_name(const char *context, const char *registrar)
8245 {
8246  struct ast_context *con;
8247  int ret = -1;
8248 
8250  con = ast_context_find(context);
8251  if (con) {
8252  ast_context_destroy(con, registrar);
8253  ret = 0;
8254  }
8256 
8257  return ret;
8258 }
8259 
8260 void ast_context_destroy(struct ast_context *con, const char *registrar)
8261 {
8263  __ast_context_destroy(contexts, contexts_table, con,registrar);
8265 }
8266 
8267 void wait_for_hangup(struct ast_channel *chan, const void *data)
8268 {
8269  int res;
8270  struct ast_frame *f;
8271  double waitsec;
8272  int waittime;
8273 
8274  if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
8275  waitsec = -1;
8276  if (waitsec > -1) {
8277  waittime = waitsec * 1000.0;
8278  ast_safe_sleep(chan, waittime);
8279  } else do {
8280  res = ast_waitfor(chan, -1);
8281  if (res < 0)
8282  return;
8283  f = ast_read(chan);
8284  if (f)
8285  ast_frfree(f);
8286  } while(f);
8287 }
8288 
8289 /*!
8290  * \ingroup functions
8291  */
8292 static int testtime_write(struct ast_channel *chan, const char *cmd, char *var, const char *value)
8293 {
8294  struct ast_tm tm;
8295  struct timeval tv;
8296  char *remainder, result[30], timezone[80];
8297 
8298  /* Turn off testing? */
8299  if (!pbx_checkcondition(value)) {
8300  pbx_builtin_setvar_helper(chan, "TESTTIME", NULL);
8301  return 0;
8302  }
8303 
8304  /* Parse specified time */
8305  if (!(remainder = ast_strptime(value, "%Y/%m/%d %H:%M:%S", &tm))) {
8306  return -1;
8307  }
8308  sscanf(remainder, "%79s", timezone);
8309  tv = ast_mktime(&tm, S_OR(timezone, NULL));
8310 
8311  snprintf(result, sizeof(result), "%ld", (long) tv.tv_sec);
8312  pbx_builtin_setvar_helper(chan, "__TESTTIME", result);
8313  return 0;
8314 }
8315 
8317  .name = "TESTTIME",
8318  .write = testtime_write,
8319 };
8320 
8321 int pbx_checkcondition(const char *condition)
8322 {
8323  int res;
8324  if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */
8325  return 0;
8326  } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
8327  return res;
8328  } else { /* Strings are true */
8329  return 1;
8330  }
8331 }
8332 
8333 static void presence_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
8334 {
8335  struct ast_presence_state_message *presence_state;
8336  struct ast_str *hint_app = NULL;
8337  struct ast_hintdevice *device;
8338  struct ast_hintdevice *cmpdevice;
8339  struct ao2_iterator *dev_iter;
8340 
8342  return;
8343  }
8344 
8345  presence_state = stasis_message_data(msg);
8346 
8347  if (ao2_container_count(hintdevices) == 0) {
8348  /* There are no hints monitoring devices. */
8349  return;
8350  }
8351 
8352  hint_app = ast_str_create(1024);
8353  if (!hint_app) {
8354  return;
8355  }
8356 
8357  cmpdevice = ast_alloca(sizeof(*cmpdevice) + strlen(presence_state->provider));
8358  strcpy(cmpdevice->hintdevice, presence_state->provider);
8359 
8360  ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
8361  dev_iter = ao2_t_callback(hintdevices,
8364  cmpdevice,
8365  "find devices in container");
8366  if (!dev_iter) {
8368  ast_free(hint_app);
8369  return;
8370  }
8371 
8372  for (; (device = ao2_iterator_next(dev_iter)); ao2_t_ref(device, -1, "Next device")) {
8373  if (device->hint) {
8374  presence_state_notify_callbacks(device->hint, &hint_app, presence_state);
8375  }
8376  }
8377  ao2_iterator_destroy(dev_iter);
8379 
8380  ast_free(hint_app);
8381 }
8382 
8383 static int action_extensionstatelist(struct mansession *s, const struct message *m)
8384 {
8385  const char *action_id = astman_get_header(m, "ActionID");
8386  struct ast_hint *hint;
8387  struct ao2_iterator it_hints;
8388  int hint_count = 0;
8389 
8390  if (!hints) {
8391  astman_send_error(s, m, "No dialplan hints are available");
8392  return 0;
8393  }
8394 
8395  astman_send_listack(s, m, "Extension Statuses will follow", "start");
8396 
8397  ao2_lock(hints);
8398  it_hints = ao2_iterator_init(hints, 0);
8399  for (; (hint = ao2_iterator_next(&it_hints)); ao2_ref(hint, -1)) {
8400 
8401  ao2_lock(hint);
8402 
8403  /* Ignore pattern matching hints; they are stored in the
8404  * hints container but aren't real from the perspective of
8405  * an AMI user
8406  */
8407  if (hint->exten->exten[0] == '_') {
8408  ao2_unlock(hint);
8409  continue;
8410  }
8411 
8412  ++hint_count;
8413 
8414  astman_append(s, "Event: ExtensionStatus\r\n");
8415  if (!ast_strlen_zero(action_id)) {
8416  astman_append(s, "ActionID: %s\r\n", action_id);
8417  }
8418  astman_append(s,
8419  "Exten: %s\r\n"
8420  "Context: %s\r\n"
8421  "Hint: %s\r\n"
8422  "Status: %d\r\n"
8423  "StatusText: %s\r\n\r\n",
8424  hint->exten->exten,
8425  hint->exten->parent->name,
8426  hint->exten->app,
8427  hint->laststate,
8429  ao2_unlock(hint);
8430  }
8431 
8432  ao2_iterator_destroy(&it_hints);
8433  ao2_unlock(hints);
8434 
8435  astman_send_list_complete_start(s, m, "ExtensionStateListComplete", hint_count);
8437 
8438  return 0;
8439 }
8440 
8441 
8442 /*!
8443  * \internal
8444  * \brief Clean up resources on Asterisk shutdown.
8445  *
8446  * \note Cleans up resources allocated in load_pbx
8447  */
8448 static void unload_pbx(void)
8449 {
8450  presence_state_sub = stasis_unsubscribe_and_join(presence_state_sub);
8451  device_state_sub = stasis_unsubscribe_and_join(device_state_sub);
8452 
8453  ast_manager_unregister("ShowDialPlan");
8454  ast_manager_unregister("ExtensionStateList");
8455  ast_cli_unregister_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
8456  ast_custom_function_unregister(&exception_function);
8457  ast_custom_function_unregister(&testtime_function);
8458 }
8459 
8460 int load_pbx(void)
8461 {
8462  int res = 0;
8463 
8465 
8466  /* Initialize the PBX */
8467  ast_verb(1, "Asterisk PBX Core Initializing\n");
8468 
8469  ast_verb(2, "Registering builtin functions:\n");
8470  ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
8471  __ast_custom_function_register(&exception_function, NULL);
8472  __ast_custom_function_register(&testtime_function, NULL);
8473 
8474  /* Register manager application */
8477 
8478  if (res) {
8479  return -1;
8480  }
8481 
8482  if (!(device_state_sub = stasis_subscribe(ast_device_state_topic_all(), device_state_cb, NULL))) {
8483  return -1;
8484  }
8486  stasis_subscription_accept_message_type(device_state_sub, hint_change_message_type());
8487  stasis_subscription_accept_message_type(device_state_sub, hint_remove_message_type());
8489 
8490  if (!(presence_state_sub = stasis_subscribe(ast_presence_state_topic_all(), presence_state_cb, NULL))) {
8491  return -1;
8492  }
8495 
8496  return 0;
8497 }
8498 
8499 /*
8500  * Lock context list functions ...
8501  */
8503 {
8504  return ast_mutex_lock(&conlock);
8505 }
8506 
8508 {
8509  return ast_mutex_lock(&conlock);
8510 }
8511 
8513 {
8514  return ast_mutex_unlock(&conlock);
8515 }
8516 
8517 /*
8518  * Lock context ...
8519  */
8521 {
8522  return ast_rwlock_wrlock(&con->lock);
8523 }
8524 
8526 {
8527  return ast_rwlock_rdlock(&con->lock);
8528 }
8529 
8531 {
8532  return ast_rwlock_unlock(&con->lock);
8533 }
8534 
8535 /*
8536  * Name functions ...
8537  */
8538 const char *ast_get_context_name(struct ast_context *con)
8539 {
8540  return con ? con->name : NULL;
8541 }
8542 
8544 {
8545  return exten ? exten->parent : NULL;
8546 }
8547 
8549 {
8550  return exten ? exten->name : NULL;
8551 }
8552 
8554 {
8555  return exten ? exten->label : NULL;
8556 }
8557 
8559 {
8560  return exten ? exten->priority : -1;
8561 }
8562 
8563 /*
8564  * Registrar info functions ...
8565  */
8567 {
8568  return c ? c->registrar : NULL;
8569 }
8570 
8572 {
8573  return e ? e->registrar : NULL;
8574 }
8575 
8577 {
8578  return e ? e->registrar_file : NULL;
8579 }
8580 
8582 {
8583  return e ? e->registrar_line : 0;
8584 }
8585 
8587 {
8588  return e ? e->matchcid : 0;
8589 }
8590 
8592 {
8593  return e ? e->cidmatch_display : NULL;
8594 }
8595 
8596 const char *ast_get_extension_app(struct ast_exten *e)
8597 {
8598  return e ? e->app : NULL;
8599 }
8600 
8602 {
8603  return e ? e->data : NULL;
8604 }
8605 
8606 /*
8607  * Walking functions ...
8608  */
8610 {
8611  return con ? con->next : contexts;
8612 }
8613 
8615  struct ast_exten *exten)
8616 {
8617  if (!exten)
8618  return con ? con->root : NULL;
8619  else
8620  return exten->next;
8621 }
8622 
8623 const struct ast_sw *ast_walk_context_switches(const struct ast_context *con,
8624  const struct ast_sw *sw)
8625 {
8626  if (sw) {
8627  int idx;
8628  int next = 0;
8629 
8630  for (idx = 0; idx < ast_context_switches_count(con); idx++) {
8631  const struct ast_sw *s = ast_context_switches_get(con, idx);
8632 
8633  if (next) {
8634  return s;
8635  }
8636 
8637  if (sw == s) {
8638  next = 1;
8639  }
8640  }
8641 
8642  return NULL;
8643  }
8644 
8645  if (!ast_context_switches_count(con)) {
8646  return NULL;
8647  }
8648 
8649  return ast_context_switches_get(con, 0);
8650 }
8651 
8653 {
8654  return AST_VECTOR_SIZE(&con->alts);
8655 }
8656 
8657 const struct ast_sw *ast_context_switches_get(const struct ast_context *con, int idx)
8658 {
8659  return AST_VECTOR_GET(&con->alts, idx);
8660 }
8661 
8663  struct ast_exten *priority)
8664 {
8665  return priority ? priority->peer : exten;
8666 }
8667 
8668 const struct ast_include *ast_walk_context_includes(const struct ast_context *con,
8669  const struct ast_include *inc)
8670 {
8671  if (inc) {
8672  int idx;
8673  int next = 0;
8674 
8675  for (idx = 0; idx < ast_context_includes_count(con); idx++) {
8676  const struct ast_include *include = AST_VECTOR_GET(&con->includes, idx);
8677 
8678  if (next) {
8679  return include;
8680  }
8681 
8682  if (inc == include) {
8683  next = 1;
8684  }
8685  }
8686 
8687  return NULL;
8688  }
8689 
8690  if (!ast_context_includes_count(con)) {
8691  return NULL;
8692  }
8693 
8694  return ast_context_includes_get(con, 0);
8695 }
8696 
8698 {
8699  return AST_VECTOR_SIZE(&con->includes);
8700 }
8701 
8702 const struct ast_include *ast_context_includes_get(const struct ast_context *con, int idx)
8703 {
8704  return AST_VECTOR_GET(&con->includes, idx);
8705 }
8706 
8708  const struct ast_ignorepat *ip)
8709 {
8710  if (!con) {
8711  return NULL;
8712  }
8713 
8714  if (ip) {
8715  int idx;
8716  int next = 0;
8717 
8718  for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
8719  const struct ast_ignorepat *i = ast_context_ignorepats_get(con, idx);
8720 
8721  if (next) {
8722  return i;
8723  }
8724 
8725  if (ip == i) {
8726  next = 1;
8727  }
8728  }
8729 
8730  return NULL;
8731  }
8732 
8733  if (!ast_context_ignorepats_count(con)) {
8734  return NULL;
8735  }
8736 
8737  return ast_context_ignorepats_get(con, 0);
8738 }
8739 
8741 {
8742  return AST_VECTOR_SIZE(&con->ignorepats);
8743 }
8744 
8745 const struct ast_ignorepat *ast_context_ignorepats_get(const struct ast_context *con, int idx)
8746 {
8747  return AST_VECTOR_GET(&con->ignorepats, idx);
8748 }
8749 
8751 {
8752  int idx;
8753  int res = 0;
8754 
8755  for (idx = 0; idx < ast_context_includes_count(con); idx++) {
8756  const struct ast_include *inc = ast_context_includes_get(con, idx);
8757 
8758  if (ast_context_find(include_rname(inc))) {
8759  continue;
8760  }
8761 
8762  res = -1;
8763  ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
8764  ast_get_context_name(con), include_rname(inc));
8765  break;
8766  }
8767 
8768  return res;
8769 }
8770 
8771 
8772 static int __ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
8773 {
8774  int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
8775 
8776  if (!chan)
8777  return -2;
8778 
8779  if (context == NULL)
8780  context = ast_channel_context(chan);
8781  if (exten == NULL)
8782  exten = ast_channel_exten(chan);
8783 
8784  goto_func = (async) ? ast_async_goto : ast_explicit_goto;
8785  if (ast_exists_extension(chan, context, exten, priority,
8786  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)))
8787  return goto_func(chan, context, exten, priority);
8788  else {
8789  return AST_PBX_GOTO_FAILED;
8790  }
8791 }
8792 
8793 int ast_goto_if_exists(struct ast_channel *chan, const char* context, const char *exten, int priority)
8794 {
8795  return __ast_goto_if_exists(chan, context, exten, priority, 0);
8796 }
8797 
8798 int ast_async_goto_if_exists(struct ast_channel *chan, const char * context, const char *exten, int priority)
8799 {
8800  return __ast_goto_if_exists(chan, context, exten, priority, 1);
8801 }
8802 
8803 static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string, int async)
8804 {
8805  char *exten, *pri, *context;
8806  char *stringp;
8807  int ipri;
8808  int mode = 0;
8809  char rest[2] = "";
8810 
8811  if (ast_strlen_zero(goto_string)) {
8812  ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
8813  return -1;
8814  }
8815  stringp = ast_strdupa(goto_string);
8816  context = strsep(&stringp, ","); /* guaranteed non-null */
8817  exten = strsep(&stringp, ",");
8818  pri = strsep(&stringp, ",");
8819  if (!exten) { /* Only a priority in this one */
8820  pri = context;
8821  exten = NULL;
8822  context = NULL;
8823  } else if (!pri) { /* Only an extension and priority in this one */
8824  pri = exten;
8825  exten = context;
8826  context = NULL;
8827  }
8828  if (*pri == '+') {
8829  mode = 1;
8830  pri++;
8831  } else if (*pri == '-') {
8832  mode = -1;
8833  pri++;
8834  }
8835  if (sscanf(pri, "%30d%1s", &ipri, rest) != 1) {
8836  ipri = ast_findlabel_extension(chan, context ? context : ast_channel_context(chan),
8837  exten ? exten : ast_channel_exten(chan), pri,
8838  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
8839  if (ipri < 1) {
8840  ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
8841  return -1;
8842  } else
8843  mode = 0;
8844  }
8845  /* At this point we have a priority and maybe an extension and a context */
8846 
8847  if (mode)
8848  ipri = ast_channel_priority(chan) + (ipri * mode);
8849 
8850  if (async)
8851  ast_async_goto(chan, context, exten, ipri);
8852  else
8853  ast_explicit_goto(chan, context, exten, ipri);
8854 
8855  return 0;
8856 
8857 }
8858 
8859 int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
8860 {
8861  return pbx_parseable_goto(chan, goto_string, 0);
8862 }
8863 
8864 int ast_async_parseable_goto(struct ast_channel *chan, const char *goto_string)
8865 {
8866  return pbx_parseable_goto(chan, goto_string, 1);
8867 }
8868 
8869 static int hint_hash(const void *obj, const int flags)
8870 {
8871  const struct ast_hint *hint = obj;
8872  const char *exten_name;
8873  int res;
8874 
8875  exten_name = ast_get_extension_name(hint->exten);
8876  if (ast_strlen_zero(exten_name)) {
8877  /*
8878  * If the exten or extension name isn't set, return 0 so that
8879  * the ao2_find() search will start in the first bucket.
8880  */
8881  res = 0;
8882  } else {
8883  res = ast_str_case_hash(exten_name);
8884  }
8885 
8886  return res;
8887 }
8888 
8889 static int hint_cmp(void *obj, void *arg, int flags)
8890 {
8891  const struct ast_hint *hint = obj;
8892  const struct ast_exten *exten = arg;
8893 
8894  return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
8895 }
8896 
8897 static int statecbs_cmp(void *obj, void *arg, int flags)
8898 {
8899  const struct ast_state_cb *state_cb = obj;
8901 
8902  return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0;
8903 }
8904 
8905 /*!
8906  * \internal
8907  * \brief Clean up resources on Asterisk shutdown
8908  */
8909 static void pbx_shutdown(void)
8910 {
8911  STASIS_MESSAGE_TYPE_CLEANUP(hint_change_message_type);
8912  STASIS_MESSAGE_TYPE_CLEANUP(hint_remove_message_type);
8913 
8914  if (hints) {
8915  ao2_container_unregister("hints");
8916  ao2_ref(hints, -1);
8917  hints = NULL;
8918  }
8919  if (hintdevices) {
8920  ao2_container_unregister("hintdevices");
8921  ao2_ref(hintdevices, -1);
8922  hintdevices = NULL;
8923  }
8924  if (autohints) {
8925  ao2_container_unregister("autohints");
8926  ao2_ref(autohints, -1);
8927  autohints = NULL;
8928  }
8929  if (statecbs) {
8930  ao2_container_unregister("statecbs");
8931  ao2_ref(statecbs, -1);
8932  statecbs = NULL;
8933  }
8934  if (contexts_table) {
8935  ast_hashtab_destroy(contexts_table, NULL);
8936  }
8937 }
8938 
8939 static void print_hints_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
8940 {
8941  struct ast_hint *hint = v_obj;
8942 
8943  if (!hint) {
8944  return;
8945  }
8946  prnt(where, "%s@%s", ast_get_extension_name(hint->exten),
8948 }
8949 
8950 static void print_hintdevices_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
8951 {
8952  struct ast_hintdevice *hintdevice = v_obj;
8953 
8954  if (!hintdevice) {
8955  return;
8956  }
8957  prnt(where, "%s => %s@%s", hintdevice->hintdevice,
8958  ast_get_extension_name(hintdevice->hint->exten),
8960 }
8961 
8962 static void print_autohint_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
8963 {
8964  struct ast_autohint *autohint = v_obj;
8965 
8966  if (!autohint) {
8967  return;
8968  }
8969  prnt(where, "%s", autohint->context);
8970 }
8971 
8972 static void print_statecbs_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
8973 {
8974  struct ast_state_cb *state_cb = v_obj;
8975 
8976  if (!state_cb) {
8977  return;
8978  }
8979  prnt(where, "%d", state_cb->id);
8980 }
8981 
8982 int ast_pbx_init(void)
8983 {
8986  if (hints) {
8987  ao2_container_register("hints", hints, print_hints_key);
8988  }
8991  if (hintdevices) {
8992  ao2_container_register("hintdevices", hintdevices, print_hintdevices_key);
8993  }
8994  /* This is protected by the context_and_merge lock */
8997  if (autohints) {
8998  ao2_container_register("autohints", autohints, print_autohint_key);
8999  }
9001  if (statecbs) {
9002  ao2_container_register("statecbs", statecbs, print_statecbs_key);
9003  }
9004 
9006 
9007  if (STASIS_MESSAGE_TYPE_INIT(hint_change_message_type) != 0) {
9008  return -1;
9009  }
9010  if (STASIS_MESSAGE_TYPE_INIT(hint_remove_message_type) != 0) {
9011  return -1;
9012  }
9013 
9014  return (hints && hintdevices && autohints && statecbs) ? 0 : -1;
9015 }
const char * label
Definition: pbx.c:244
#define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:463
struct ast_hashtab * root_table
Definition: pbx.c:2430
const char * name
Definition: pbx.h:119
static void manager_dpsendack(struct mansession *s, const struct message *m)
Send ack once.
Definition: pbx.c:5855
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
const char * type
Definition: datastore.h:32
ast_include: include= support in extensions.conf
Definition: pbx_include.c:37
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
static int hintdevice_remove_cb(void *obj, void *arg, void *data, int flags)
Definition: pbx.c:504
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Definition: threadstorage.h:84
static struct ast_threadstorage extensionstate_buf
Definition: pbx.c:229
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1574
struct ast_context * ast_get_extension_context(struct ast_exten *exten)
Definition: pbx.c:8543
static void hintdevice_destroy(void *obj)
Definition: pbx.c:540
int ast_pbx_init(void)
Definition: pbx.c:8982
static const char type[]
Definition: chan_ooh323.c:109
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)
Launch a new extension (i.e. new stack)
Definition: pbx.c:4204
enum sip_cc_notify_state state
Definition: chan_sip.c:959
Options for ast_pbx_run()
Definition: pbx.h:391
Tone Indication Support.
int presentation
Q.931 encoded presentation-indicator encoded field.
Definition: channel.h:278
pthread_t thread
Definition: app_meetme.c:1089
const char * ast_get_switch_name(const struct ast_sw *sw)
Definition: pbx_sw.c:48
const char * ast_get_switch_registrar(const struct ast_sw *sw)
Definition: pbx_sw.c:63
char digit
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition: channel.c:7434
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
const char * ast_get_extension_registrar_file(struct ast_exten *e)
Get name of configuration file used by registrar to register this extension.
Definition: pbx.c:8576
#define ast_rwlock_rdlock(a)
Definition: lock.h:233
#define ast_channel_lock(chan)
Definition: channel.h:2945
void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
Definition: pbx.c:8095
char name[256]
Definition: pbx.c:2440
int64_t ast_mark(int, int start1_stop0)
Definition: astman.c:103
Main Channel structure associated with a channel.
Definition: test_heap.c:38
Music on hold handling.
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
ast_device_state
Device States.
Definition: devicestate.h:52
int ast_context_switches_count(const struct ast_context *con)
Definition: pbx.c:8652
int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
This function locks given context, removes switch, unlock context and return.
Definition: pbx.c:4920
struct ast_ignorepats ignorepats
Definition: pbx.c:291
static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids, const char *predial_callee)
Definition: pbx.c:7755
char * str
Subscriber phone number (Malloced)
Definition: channel.h:292
const char pattern[0]
Definition: pbx_ignorepat.c:39
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition: dial.c:1091
char * context
Definition: pbx.c:6280
static void print_autohint_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: pbx.c:8962
int ast_context_remove_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
Definition: pbx.c:6850
int ast_dial_option_global_enable(struct ast_dial *dial, enum ast_dial_option option, void *data)
Enables an option globally.
Definition: dial.c:1151
struct ast_exten * root
Definition: pbx.c:2429
Asterisk locking-related definitions:
ast_extension_states
Extension states.
Definition: pbx.h:61
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Definition: channel.c:1422
Asterisk main include file. File version handling, generic pbx functions.
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition: hashtab.c:486
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
int ast_hashtab_newsize_java(struct ast_hashtab *tab)
Create a prime number roughly 2x the current table size.
Definition: hashtab.c:127
const char * presence_message
Definition: pbx.h:108
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static void __ast_internal_context_destroy(struct ast_context *con)
Definition: pbx.c:8050
int refcount
Definition: pbx.c:2437
static unsigned int ext_strncpy(char *dst, const char *src, size_t dst_size, int nofluff)
Definition: pbx.c:7068
static int __ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
Definition: pbx.c:8772
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8530
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
Private include file for pbx.
static char * parse_hint_presence(struct ast_str *hint_args)
Definition: pbx.c:3037
int ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
Add a context include.
Definition: pbx.c:6726
static int ast_add_hint(struct ast_exten *e)
Add hint to hint list, check initial extension state.
Definition: pbx.c:3982
ast_switch_f * exec
Definition: pbx.h:167
int ast_hint_presence_state(struct ast_channel *c, const char *context, const char *exten, char **subtype, char **message)
Uses hint and presence state callback to get the presence state of an extension.
Definition: pbx.c:3226
static struct ao2_container * alloc_device_state_info(void)
Definition: pbx.c:3076
#define EXT_DATA_SIZE
Definition: pbx.c:216
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
int ast_async_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:8864
static char * handle_debug_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Send ack once.
Definition: pbx.c:5799
static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
Change hint for an extension.
Definition: pbx.c:4096
static void exception_store_free(void *data)
Definition: pbx.c:2783
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
Definition: channel.h:296
struct ast_exten * exten
Definition: pbx.c:268
int total_items
Definition: pbx.c:5478
Main dialing structure. Contains global options, channels being dialed, and more! ...
Definition: dial.c:48
struct ast_include * include_alloc(const char *value, const char *registrar)
Definition: pbx_include.c:74
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
static int ast_add_extension2_lockopt(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, const char *registrar_file, int registrar_line, int lock_context)
Same as ast_add_extension2() but controls the context locking.
Definition: pbx.c:7325
int total_exten
Definition: pbx.c:5480
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Definition: astobj2.h:409
struct ast_exten * root
Definition: pbx.c:286
static int internal_extension_state_extended(struct ast_channel *c, const char *context, const char *exten, struct ao2_container *device_state_info)
Definition: pbx.c:3141
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition: pbx.c:8525
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:563
struct ast_party_id id
Connected party ID.
Definition: channel.h:459
void include_free(struct ast_include *inc)
Definition: pbx_include.c:106
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
void ast_dial_set_global_timeout(struct ast_dial *dial, int timeout)
Set the maximum time (globally) allowed for trying to ring phones.
Definition: dial.c:1313
const struct ast_sw * ast_walk_context_switches(const struct ast_context *con, const struct ast_sw *sw)
Definition: pbx.c:8623
#define AST_CAUSE_NORMAL_TEMPORARY_FAILURE
Definition: causes.h:121
const char * ast_get_ignorepat_registrar(const struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:47
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
const struct ast_ignorepat * ast_context_ignorepats_get(const struct ast_context *con, int idx)
Definition: pbx.c:8745
char * name
Definition: pbx.c:239
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide)
Initialize the given connected line structure using the given guide for a set update operation...
Definition: channel.c:2045
#define ast_test_flag(p, flag)
Definition: utils.h:63
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:6987
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:122
int ast_context_verify_includes(struct ast_context *con)
Verifies includes in an ast_contect structure.
Definition: pbx.c:8750
Device state management.
void * data
Definition: pbx.c:305
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: pbx.c:8609
int ast_extension_close(const char *pattern, const char *data, int needmore)
Definition: pbx.c:2418
#define STATUS_NO_PRIORITY
Definition: pbx.c:2469
static void decrease_call_count(void)
Definition: pbx.c:4670
void ast_context_set_autohints(struct ast_context *con, int enabled)
Enable or disable autohints support on a context.
Definition: pbx.c:6272
#define ast_rwlock_destroy(rwlock)
Definition: lock.h:231
int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
Locks context, remove included contexts, unlocks context. When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault.
Definition: pbx.c:4863
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:699
Time-related functions and macros.
int last_presence_state
Definition: pbx.c:6284
const char * include_rname(const struct ast_include *inc)
Definition: pbx_include.c:55
#define bc
struct ast_party_name name
Subscriber name.
Definition: channel.h:341
static int hint_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:8889
int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, const struct ast_assigned_ids *assignedids)
Synchronously or asynchronously make an outbound call and execute an application on the channel...
Definition: pbx.c:8015
int pbx_set_extenpatternmatchnew(int newval)
Definition: pbx.c:4781
static struct ast_hashtab * contexts_table
Definition: pbx.c:777
static struct match_char * add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
Definition: pbx.c:1657
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
Check extension state for an extension by using hint.
Definition: pbx.c:3170
#define AST_CAUSE_UNALLOCATED
Definition: causes.h:97
static void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action)
Definition: pbx.c:1231
static int extension_presence_state_helper(struct ast_exten *e, char **subtype, char **message)
Definition: pbx.c:3200
int registrar_line
Definition: pbx.c:255
static void show_dialplan_helper_extension_output(int fd, char *buf1, char *buf2, struct ast_exten *exten)
Writes CLI output of a single extension for show dialplan.
Definition: pbx.c:5501
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1501
ast_switch_f * matchmore
Definition: pbx.h:168
char device_name[1]
Definition: pbx.h:99
#define OBJ_POINTER
Definition: astobj2.h:1154
#define AST_CAUSE_NETWORK_OUT_OF_ORDER
Definition: causes.h:120
#define ast_set_flag(p, flag)
Definition: utils.h:70
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3237
int load_pbx(void)
Definition: pbx.c:8460
descriptor for a cli entry.
Definition: cli.h:171
const int argc
Definition: cli.h:160
static int publish_hint_remove(struct ast_hint *hint)
Publish a hint removed event.
Definition: pbx.c:3924
#define LOG_WARNING
Definition: logger.h:274
int extended
Definition: pbx.c:307
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
static void context_merge_incls_swits_igps_other_registrars(struct ast_context *new, struct ast_context *old, const char *registrar)
Definition: pbx.c:6294
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
static struct stasis_subscription * presence_state_sub
Subscription for presence state change events.
Definition: pbx.c:770
int priority
Definition: pbx_spool.c:96
#define VERBOSITY_ATLEAST(level)
Definition: logger.h:461
static int add_hintdevice(struct ast_hint *hint, const char *devicelist)
add hintdevice structure and link it into the container.
Definition: pbx.c:552
struct ast_app * cached_app
Definition: pbx.c:247
ast_state_cb: An extension state notify register item
Definition: pbx.c:301
static int autofallthrough
Definition: pbx.c:763
static void destroy_hint(void *obj)
Definition: pbx.c:3907
char * appdata
Application data to pass to application.
Definition: pbx.c:7597
static int timeout
Definition: cdr_mysql.c:86
static int tmp()
Definition: bt_open.c:389
static int stateid
Definition: pbx.c:792
Generic (perhaps overly so) hashtable implementation Hash Table support in Asterisk.
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1335
enum ast_state_cb_update_reason reason
Definition: pbx.h:103
int ast_context_remove_switch(const char *context, const char *sw, const char *data, const char *registrar)
Remove a switch.
Definition: pbx.c:4898
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:4194
void * ast_get_extension_app_data(struct ast_exten *e)
Definition: pbx.c:8601
void * ast_hashtab_next(struct ast_hashtab_iter *it)
Gets the next object in the list, advances iter one step returns null on end of traversal.
Definition: hashtab.c:683
Structure for variables, used for configurations and for channel variables.
const struct ast_sw * ast_context_switches_get(const struct ast_context *con, int idx)
Definition: pbx.c:8657
static char * handle_show_hints(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
handle_show_hints: CLI support for listing registered dial plan hints
Definition: pbx.c:5205
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
#define var
Definition: ast_expr2f.c:614
void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars)
adds a list of channel variables to a channel
Definition: channel.c:8217
static int testtime_write(struct ast_channel *chan, const char *cmd, char *var, const char *value)
Definition: pbx.c:8292
static struct ao2_container * hintdevices
Container for hint devices.
Definition: pbx.c:363
#define NEW_MATCHER_RECURSE
int dial_res
Result of the dial operation when dialed is set.
Definition: pbx.c:7605
static int hashtab_compare_extens(const void *ha_a, const void *ah_b)
Definition: pbx.c:693
char last_char
Definition: pbx.c:276
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
static char * handle_show_device2extenstate(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx.c:6076
static int hint_hash(const void *obj, const int flags)
Definition: pbx.c:8869
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1523
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: pbx.c:2443
int ast_extension_state_extended(struct ast_channel *c, const char *context, const char *exten, struct ao2_container **device_state_info)
Check extended extension state for an extension by using hint.
Definition: pbx.c:3176
#define EVENT_FLAG_CALL
Definition: manager.h:72
#define INC_DST_OVERFLOW_CHECK
Definition: cli.h:152
static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c, struct ast_pbx_args *args)
Definition: pbx.c:4310
static void print_statecbs_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: pbx.c:8972
static EditLine * el
Definition: asterisk.c:340
enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args)
Execute the PBX in the current thread.
Definition: pbx.c:4739
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:605
char context[1]
Name of the context.
Definition: pbx.c:389
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition: stasis.c:1079
Structure for a data store type.
Definition: datastore.h:31
static void device_state_notify_callbacks(struct ast_hint *hint, struct ast_str **hint_app)
Definition: pbx.c:3370
int extension_state
Definition: pbx.c:607
ast_channel_state
ast_channel states
Definition: channelstate.h:35
#define ao2_t_link(container, obj, tag)
Add an object to a container.
Definition: astobj2.h:1547
char * str
Subscriber name (Malloced)
Definition: channel.h:265
const ast_string_field exten
Definition: pbx.c:625
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:426
#define AST_VECTOR_REMOVE_UNORDERED(vec, idx)
Remove an element from an unordered vector by index.
Definition: vector.h:438
int specificity
Definition: pbx.c:265
Dialing API.
#define STATUS_NO_EXTENSION
Definition: pbx.c:2468
const ast_string_field app
Definition: pbx_spool.c:95
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static struct ast_cli_entry pbx_cli[]
Definition: pbx.c:6164
static struct ast_threadstorage buf2
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static struct match_char * add_pattern_node(struct ast_context *con, struct match_char *current, const struct pattern_node *pattern, int is_pattern, int already, struct match_char **nextcharptr)
Definition: pbx.c:1459
struct ast_hint * hint
Hint this hintdevice belongs to.
Definition: pbx.c:374
int context_existence
Definition: pbx.c:5482
int ast_add_extension2(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, const char *registrar_file, int registrar_line)
Main interface to add extensions to the list for out context.
Definition: pbx.c:7299
const char * ast_get_include_registrar(const struct ast_include *i)
Definition: pbx_include.c:60
ast_control_frame_type
Internal control frame subtype field values.
static int copy(char *infile, char *outfile)
Utility function to copy a file.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
struct match_char * alt_char
Definition: pbx.c:266
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:337
struct ast_channel * ast_channel_yank(struct ast_channel *yankee)
Gain control of a channel in the system.
Definition: channel.c:10794
unsigned int ast_callid
Definition: logger.h:87
char * last_presence_message
Definition: pbx.c:6286
Stasis message payload representing a presence state update.
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ast_assert(a)
Definition: utils.h:695
#define ast_mutex_lock(a)
Definition: lock.h:187
static ast_mutex_t context_merge_lock
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
Definition: pbx.c:790
double ast_option_maxload
Definition: options.c:77
#define ao2_unlock(a)
Definition: astobj2.h:730
static struct test_val c
Definition: muted.c:95
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2315
#define ast_str_alloca(init_len)
Definition: strings.h:800
const char * registrar
Definition: pbx.c:2436
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
const char * str
Definition: app_jack.c:147
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b)
Definition: pbx.c:728
ast_cond_t cond
Condition for synchronous dialing.
Definition: pbx.c:7593
const char * args
ast_mutex_t macrolock
Definition: pbx.c:2439
#define NULL
Definition: resample.c:96
char * incstack[AST_PBX_MAX_STACK]
Definition: extconf.h:237
struct ast_context * local_contexts
static unsigned int hashtab_hash_labels(const void *obj)
Definition: pbx.c:757
const char *const text
Definition: pbx.c:608
char * end
Definition: eagi_proxy.c:73
static enum ast_control_frame_type pbx_dial_reason(enum ast_dial_result dial_result, int cause)
Attempt to convert disconnect cause to old originate reason.
Definition: pbx.c:7716
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:197
int include_valid(const struct ast_include *inc)
Definition: pbx_include.c:65
#define AST_CAUSE_NORMAL_CIRCUIT_CONGESTION
Definition: causes.h:119
int value
Definition: syslog.c:37
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
Definition: pbx.c:8260
char stuff[0]
Definition: pbx.c:257
#define LOG_DEBUG
Definition: logger.h:241
#define ast_rwlock_unlock(a)
Definition: lock.h:232
struct ast_hashtab * peer_table
Definition: pbx.c:251
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8507
const char * ext
Definition: http.c:147
static struct ao2_container * hints
Definition: pbx.c:801
#define AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED
Definition: callerid.h:329
static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string, int async)
Definition: pbx.c:8803
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1771
static void presence_state_notify_callbacks(struct ast_hint *hint, struct ast_str **hint_app, struct ast_presence_state_message *presence_state)
Definition: pbx.c:3464
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:164
#define ast_cond_signal(cond)
Definition: lock.h:201
int ast_channel_priority(const struct ast_channel *chan)
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4759
const ast_string_field context
Definition: pbx_spool.c:95
char x[1]
Definition: pbx.c:269
void ignorepat_free(struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:77
const char * ast_get_extension_registrar(struct ast_exten *e)
Definition: pbx.c:8571
#define ast_verb(level,...)
Definition: logger.h:463
int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
Get hint for channel.
Definition: pbx.c:4141
const char * registrar
Definition: pbx.c:253
static int handle_hint_change_message_type(struct stasis_message *msg, enum ast_state_cb_update_reason reason)
Definition: pbx.c:3537
ast_state_cb_type change_cb
Definition: pbx.c:309
ast_switch_f * exists
Definition: pbx.h:165
unsigned int dialed
Set when dialing is completed.
Definition: pbx.c:7607
int last_presence_state
Definition: pbx.c:338
int autohints
Definition: pbx.c:295
static char * handle_set_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx.c:6105
ast_switch_f * canmatch
Definition: pbx.h:166
const char * line
Definition: cli.h:162
int ast_hashtab_resize_java(struct ast_hashtab *tab)
Determines if a table resize should occur using the Java algorithm (if the table load factor is 75% o...
Definition: hashtab.c:84
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
int ast_option_maxcalls
Definition: options.c:79
static void get_device_state_causing_channels(struct ao2_container *c)
Definition: pbx.c:3296
static void pbx_destroy(struct ast_pbx *p)
Definition: pbx.c:985
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define COLOR_BRCYAN
Definition: term.h:60
#define ast_hashtab_insert_safe(tab, obj)
Definition: hashtab.h:315
enum ast_device_state ast_devstate_aggregate_result(struct ast_devstate_aggregate *agg)
Get the aggregate device state result.
Definition: devicestate.c:663
ast_callid ast_read_threadstorage_callid(void)
extracts the callerid from the thread
Definition: logger.c:1962
#define COLORIZE(fg, bg, str)
Definition: term.h:68
static char * handle_show_hint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
handle_show_hint: CLI support for listing registered dial plan hint
Definition: pbx.c:5304
static struct ast_exten * trie_find_next_match(struct match_char *node)
Definition: pbx.c:1160
static const char context_name[]
Utility functions.
static void device_state_info_dt(void *obj)
Definition: pbx.c:3069
int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
Find the priority of an extension that has the specified label.
Definition: pbx.c:4189
int ast_extension_cmp(const char *a, const char *b)
Determine if one extension should match before another.
Definition: pbx.c:2183
struct ast_context * next
Definition: pbx.c:289
#define ast_hashtab_start_traversal(tab)
Definition: hashtab.h:355
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
void wait_for_hangup(struct ast_channel *chan, const void *data)
Definition: pbx.c:8267
void() ao2_prnt_fn(void *where, const char *fmt,...)
Print output.
Definition: astobj2.h:1442
pthread_cond_t ast_cond_t
Definition: lock.h:176
#define ast_strlen_zero(foo)
Definition: strings.h:52
const char * name
Definition: pbx.h:162
struct timeval * ast_channel_whentohangup(struct ast_channel *chan)
char * exten
Definition: pbx.c:6281
static char * handle_show_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx.c:5732
int matchcid
Definition: pbx.c:240
const ast_string_field exten
Definition: pbx_spool.c:95
int autohints
Definition: pbx.c:2438
Number structure.
Definition: app_followme.c:154
static struct devices devices
ast_mutex_t macrolock
Definition: pbx.c:296
char hintdevice[1]
Definition: pbx.c:376
int ast_get_switch_eval(const struct ast_sw *sw)
Definition: pbx_sw.c:58
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition: logger.c:1984
struct ast_context * next
Definition: pbx.c:2432
int indicate_congestion(struct ast_channel *chan, const char *data)
Definition: pbx_builtins.c:757
static char * table
Definition: cdr_odbc.c:58
int ast_extension_state_add(const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
Add watcher for extension states.
Definition: pbx.c:3825
Call Detail Record API.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
void ast_dial_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback)
Set a callback for state changes.
Definition: dial.c:1293
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition: astobj2.c:476
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8502
struct ast_exten * next
Definition: pbx.c:256
Configuration File Parser.
enum ast_extension_states exten_state
Definition: pbx.h:104
void ao2_container_unregister(const char *name)
Unregister a container for CLI stats and integrity check.
Definition: pbx.h:211
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *exten)
Definition: pbx.c:8614
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
static int hintdevice_cmp_multiple(void *obj, void *arg, int flags)
Definition: pbx.c:421
struct ast_channel * causing_channel
Definition: pbx.h:98
static int statecbs_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:8897
static void * pbx_outgoing_exec(void *data)
Internal function which dials an outgoing leg and sends it to a provided extension or application...
Definition: pbx.c:7627
const char * registrar_file
Definition: pbx.c:254
int ao2_container_register(const char *name, struct ao2_container *self, ao2_prnt_obj_fn *prnt_obj)
Register a container for CLI stats and integrity check.
#define ast_hashtab_insert_immediate(tab, obj)
Definition: hashtab.h:291
#define AST_PBX_ERROR
Definition: pbx.h:50
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
int priority
Definition: pbx.c:243
#define ast_log
Definition: astobj2.c:42
const char * ast_get_context_registrar(struct ast_context *c)
Definition: pbx.c:8566
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
static void presence_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
Definition: pbx.c:8333
struct ast_exten * peer
Definition: pbx.c:250
ast_dial_result
List of return codes for dial run API calls.
Definition: dial.h:54
ast_sw: Switch statement in extensions.conf
Definition: pbx_sw.c:37
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
static int ext_cmp(const char *left, const char *right)
Definition: pbx.c:2126
static int ast_extension_state2(struct ast_exten *e, struct ao2_container *device_state_info)
Check state of extension by using hints.
Definition: pbx.c:3113
int ast_async_goto_by_name(const char *channame, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition: pbx.c:7044
General Asterisk PBX channel definitions.
int raise_exception(struct ast_channel *chan, const char *reason, int priority)
Definition: pbx.c:2806
int priority
Dialplan priority.
Definition: pbx.c:7603
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
static int increase_call_count(const struct ast_channel *c)
Increase call count for channel.
Definition: pbx.c:4621
long option_minmemfree
Definition: options.c:86
static ast_mutex_t maxcalllock
Definition: pbx.c:772
Asterisk file paths, configured in asterisk.conf.
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition: channel.c:2437
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
struct ast_sw * sw_alloc(const char *value, const char *data, int eval, const char *registrar)
Definition: pbx_sw.c:68
const char * data
Definition: extconf.h:241
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
ast_state_cb_update_reason
Definition: pbx.h:89
enum ast_presence_state presence_state
Definition: pbx.h:106
static int ext_cmp_exten_strlen(const char *str)
Definition: pbx.c:1803
static void create_match_char_tree(struct ast_context *con)
Definition: pbx.c:1756
const ast_string_field reason
Definition: pbx.c:625
const int fd
Definition: cli.h:159
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:248
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
static int ext_cmp_pattern_pos(const char **p, unsigned char *bitwise)
helper functions to sort extension patterns in the desired way, so that more specific patterns appear...
Definition: pbx.c:1963
void pbx_set_overrideswitch(const char *newval)
Definition: pbx.c:4788
ast_presence_state
Definition: presencestate.h:26
int id
Definition: pbx.c:303
const int n
Definition: cli.h:165
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1283
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
struct sla_ringing_trunk * last
Definition: app_meetme.c:1092
#define AST_CAUSE_ANSWERED_ELSEWHERE
Definition: causes.h:113
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
int priority
Definition: pbx.c:627
static struct ast_exten * ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
Definition: pbx.c:2997
void(* ast_state_cb_destroy_type)(int id, void *data)
Typedef for devicestate and hint callback removal indication callback.
Definition: pbx.h:115
char * registrar
Definition: pbx.c:293
#define HASH_EXTENHINT_SIZE
Definition: pbx.c:358
int ast_context_add_switch(const char *context, const char *sw, const char *data, int eval, const char *registrar)
Add a switch.
Definition: pbx.c:6771
#define AST_MAX_EXTENSION
Definition: channel.h:135
static struct match_char * already_in_tree(struct match_char *current, char *pat, int is_pattern)
Definition: pbx.c:1397
static int extension_state_add_destroy(const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data, int extended)
Definition: pbx.c:3729
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:299
struct ast_switch * pbx_findswitch(const char *sw)
Definition: pbx_switch.c:40
int ast_extension_state_del(int id, ast_state_cb_type change_cb)
Deletes a state change watcher by ID.
Definition: pbx.c:3858
structure to hold extensions
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:85
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2476
In case you didn&#39;t read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
Definition: manager.c:1625
#define COLORIZE_FMT
Shortcut macros for coloring a set of text.
Definition: term.h:67
const char * presence_subtype
Definition: pbx.h:107
int ast_processed_calls(void)
Retrieve the total number of calls processed through the PBX since last restart.
Definition: pbx.c:4769
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4179
#define AST_VECTOR_REMOVE_ORDERED(vec, idx)
Remove an element from a vector by index while maintaining order.
Definition: vector.h:448
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_exten * canmatch_exten
Definition: pbx.c:279
static int ext_cmp_pattern(const char *left, const char *right)
Definition: pbx.c:2078
static struct ast_custom_function testtime_function
Definition: pbx.c:8316
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static struct ast_threadstorage switch_data
Definition: pbx.c:228
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:8859
int indicate_busy(struct ast_channel *chan, const char *data)
Definition: pbx_builtins.c:739
#define STATUS_SUCCESS
Definition: pbx.c:2471
int ast_context_remove_include(const char *context, const char *include, const char *registrar)
Remove included contexts. This function locks contexts list by &conlist, search for the right context...
Definition: pbx.c:4840
enum ast_device_state device_state
Definition: pbx.h:97
static void print_ext(struct ast_exten *e, char *buf, int buflen)
helper function to print an extension
Definition: pbx.c:5487
struct ast_dial * dial
Dialing structure being used.
Definition: pbx.c:7591
A set of macros to manage forward-linked lists.
static int show_debug_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
Definition: pbx.c:5677
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
void(* datad)(void *)
Definition: pbx.c:249
struct ao2_container * container
Definition: res_fax.c:502
static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
Definition: pbx.c:1111
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44
struct ast_includes includes
Definition: pbx.c:290
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
static const struct ast_datastore_info exception_store_info
Definition: pbx.c:2790
#define AST_CAUSE_NO_ANSWER
Definition: causes.h:108
static ast_mutex_t conlock
Lock for the ast_context list.
Definition: pbx.c:785
AST_LIST_HEAD_NOLOCK(contactliststruct, contact)
#define PRIORITY_HINT
Definition: pbx.h:54
int total_specificity
Definition: pbx.c:274
int() ast_switch_f(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
All switch functions have the same interface, so define a type for them.
Definition: pbx.h:156
struct ast_hashtab * peer_label_table
Definition: pbx.c:252
char * registrar
Name of the registrar.
Definition: pbx.c:387
static void unload_pbx(void)
Definition: pbx.c:8448
void ast_hashtab_end_traversal(struct ast_hashtab_iter *it)
end the traversal, free the iterator, unlock if necc.
Definition: hashtab.c:674
#define STATUS_NO_LABEL
Definition: pbx.c:2470
int ast_context_add_ignorepat(const char *context, const char *value, const char *registrar)
Add an ignorepat.
Definition: pbx.c:6877
const char * ast_channel_exten(const struct ast_channel *chan)
enum ast_dial_result ast_dial_state(struct ast_dial *dial)
Return state of dial.
Definition: dial.c:1012
Core PBX routines and definitions.
char * ast_strptime(const char *s, const char *format, struct ast_tm *tm)
Special version of strptime(3) which places the answer in the common structure ast_tm. Also, unlike strptime(3), ast_strptime() initializes its memory prior to use.
Definition: localtime.c:2550
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition: pbx.c:7011
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
ast_pbx_result
The result codes when starting the PBX on a channel with ast_pbx_start.
Definition: pbx.h:354
enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *chan, int async)
Execute dialing synchronously or asynchronously.
Definition: dial.c:939
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
char * last_presence_subtype
Definition: pbx.c:6285
int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
Definition: pbx.c:6890
#define AST_CAUSE_DESTINATION_OUT_OF_ORDER
Definition: causes.h:114
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:652
const char * ast_get_ignorepat_name(const struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:42
static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
Definition: pbx.c:2400
struct ao2_container * device_state_info
Definition: pbx.h:105
int ast_get_extension_matchcid(struct ast_exten *e)
Definition: pbx.c:8586
static void pbx_outgoing_state_callback(struct ast_dial *dial)
Internal dialing state callback which causes early media to trigger an answer.
Definition: pbx.c:7690
#define COLOR_BRMAGENTA
Definition: term.h:58
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
const char *const * argv
Definition: cli.h:161
void ast_devstate_aggregate_add(struct ast_devstate_aggregate *agg, enum ast_device_state state)
Add a device state to the aggregate device state.
Definition: devicestate.c:636
const char * ast_devstate_str(enum ast_device_state devstate) attribute_pure
Convert device state to text string that is easier to parse.
Definition: devicestate.c:255
struct ast_party_dialed dialed
Dialed/Called information.
static void pbx_shutdown(void)
Definition: pbx.c:8909
int ast_add_profile(const char *, uint64_t scale)
support for event profiling
Definition: astman.c:92
int ast_context_ignorepats_count(const struct ast_context *con)
Definition: pbx.c:8740
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
static int ext_fluff_count(const char *exten)
Definition: pbx.c:2148
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define AST_PBX_INCOMPLETE
Definition: pbx.h:51
struct ast_exten * exten
Hint extension.
Definition: pbx.c:331
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
static int manager_show_dialplan_helper(struct mansession *s, const struct message *m, const char *actionidtext, const char *context, const char *exten, struct dialplan_counters *dpc, const struct ast_include *rinclude, int includecount, const char *includes[])
Show dialplan extensions XXX this function is similar but not exactly the same as the CLI&#39;s show dial...
Definition: pbx.c:5864
static unsigned int hashtab_hash_priority(const void *obj)
Definition: pbx.c:751
Presence state management.
char context_name[AST_MAX_CONTEXT]
Definition: pbx.c:342
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
Definition: pbx.c:4268
static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
Definition: pbx.c:6369
char * exten
Definition: pbx.c:238
ast_rwlock_t lock
Definition: pbx.c:285
static void * pbx_thread(void *data)
Definition: pbx.c:4692
int ast_extension_state_add_destroy(const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
Add watcher for extension states with destructor.
Definition: pbx.c:3819
#define LOG_ERROR
Definition: logger.h:285
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compres two struct timeval instances returning -1, 0, 1 if the first arg is smaller, equal or greater to the second.
Definition: time.h:128
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
#define EVENT_FLAG_CONFIG
Definition: manager.h:78
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
int laststate
Definition: pbx.c:335
struct store_hint::@410 callbacks
Definition: extconf.c:2442
int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
Find the priority of an extension that has the specified label.
Definition: pbx.c:4184
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
#define AST_MAX_APP
Definition: pbx.h:40
ast_callid ast_create_callid(void)
factory function to create a new uniquely identifying callid.
Definition: logger.c:1957
int pbx_set_autofallthrough(int newval)
Definition: pbx.c:4774
int laststate
Definition: pbx.c:6283
#define CLI_SHOWUSAGE
Definition: cli.h:45
static int ast_extension_state3(struct ast_str *hint_app, struct ao2_container *device_state_info)
Definition: pbx.c:3081
void * ast_hashtab_remove_object_via_lookup(struct ast_hashtab *tab, void *obj)
Looks up the object, removes the corresponding bucket.
Definition: hashtab.c:746
static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
Definition: pbx.c:2209
static int manager_show_dialplan(struct mansession *s, const struct message *m)
Manager listing of dial plan.
Definition: pbx.c:6019
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
int ast_get_extension_registrar_line(struct ast_exten *e)
Get line number of configuration file used by registrar to register this extension.
Definition: pbx.c:8581
struct ast_ignorepat * ignorepat_alloc(const char *value, const char *registrar)
Definition: pbx_ignorepat.c:52
static int compare_char(const void *a, const void *b)
Definition: pbx.c:674
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4712
static int autohint_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:474
char name[0]
Definition: pbx.c:297
ast_ignorepat: Ignore patterns in dial plan
Definition: pbx_ignorepat.c:37
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
Definition: lock.h:222
#define STATUS_NO_CONTEXT
Definition: pbx.c:2467
def info(msg)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Structure for dial plan autohints.
Definition: pbx.c:385
static int acf_exception_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
Definition: pbx.c:2832
int errno
int ast_thread_inhibit_escalations_swap(int inhibit)
Swap the current thread escalation inhibit setting.
ast_state_cb_destroy_type destroy_cb
Definition: pbx.c:311
Structure for dial plan hints.
Definition: pbx.c:324
int ast_extension_match(const char *pattern, const char *data)
Determine if a given extension matches a given pattern (in NXX format)
Definition: pbx.c:2413
#define NEW_MATCHER_CHK_MATCH
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:1714
Connected Line/Party information.
Definition: channel.h:457
int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
Append a channel.
Definition: dial.c:282
static void device_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
Definition: pbx.c:3584
struct sla_ringing_trunk * first
Definition: app_meetme.c:1092
#define AST_PBX_MAX_STACK
Definition: extconf.h:226
ast_rwlock_t lock
Definition: pbx.c:2428
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition: pbx.c:6970
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition: pbx.c:8520
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ast_cond_destroy(cond)
Definition: lock.h:200
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct timeval ast_channel_creationtime(struct ast_channel *chan)
#define LOG_NOTICE
Definition: logger.h:263
Structure which contains information about an outgoing dial.
Definition: pbx.c:7589
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
Definition: devicestate.c:668
struct ao2_container * callbacks
Definition: pbx.c:332
static int extenpatternmatchnew
Definition: pbx.c:764
an iterator for traversing the buckets
Definition: hashtab.h:105
static int collect_digits(struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
collect digits from the channel into the buffer.
Definition: pbx.c:4283
int ast_softhangup_nolock(struct ast_channel *chan, int reason)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2463
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10746
static int totalcalls
Definition: pbx.c:774
static int remove_hintdevice(struct ast_hint *hint)
Definition: pbx.c:517
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
static struct ast_threadstorage buf1
int ast_context_destroy_by_name(const char *context, const char *registrar)
Destroy a context by name.
Definition: pbx.c:8244
static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b)
Definition: pbx.c:721
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define CLI_FAILURE
Definition: cli.h:46
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define VAR_BUF_SIZE
Definition: pbx_private.h:68
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
#define AST_MAX_CONTEXT
Definition: channel.h:136
static char * complete_show_dialplan_context(const char *line, const char *word, int pos, int state)
Definition: pbx.c:5447
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
static void destroy_pattern_tree(struct match_char *pattern_tree)
Definition: pbx.c:1779
static int autohint_hash_cb(const void *obj, const int flags)
Definition: pbx.c:453
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct ast_dial * ast_dial_create(void)
New dialing structure.
Definition: dial.c:225
static int ext_cmp_exten_partial(const char *left, const char *right)
Definition: pbx.c:1833
void ast_devstate_aggregate_init(struct ast_devstate_aggregate *agg)
Initialize aggregate device state.
Definition: devicestate.c:630
#define AST_CHANNEL_NAME
Definition: channel.h:172
static char * handle_unset_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx.c:6133
static struct ast_context * find_context(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4804
struct ast_channel * ast_dial_get_channel(struct ast_dial *dial, int num)
Get the dialing channel, if prerun has been executed.
Definition: dial.c:1282
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4818
int ast_context_add_switch2(struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
Adds a switch (first param is a ast_context)
Definition: pbx.c:6791
void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
Merge the temporary contexts into a global contexts list and delete from the global list the ones tha...
Definition: pbx.c:6468
const char * foundcontext
Definition: extconf.h:242
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:6921
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
static int publish_hint_change(struct ast_hint *hint, struct ast_exten *ne)
Publish a hint changed event.
Definition: pbx.c:4074
int stacklen
Definition: extconf.h:238
struct ast_exten * ast_walk_extension_priorities(struct ast_exten *exten, struct ast_exten *priority)
Definition: pbx.c:8662
static int action_extensionstatelist(struct mansession *s, const struct message *m)
Definition: pbx.c:8383
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch) ...
Definition: pbx.c:4199
Asterisk XML Documentation API.
const char * word
Definition: cli.h:163
const char * ast_get_switch_data(const struct ast_sw *sw)
Definition: pbx_sw.c:53
void ast_channel_pbx_set(struct ast_channel *chan, struct ast_pbx *value)
enum ast_extension_states ast_devstate_to_extenstate(enum ast_device_state devstate)
Map devstate to an extension state.
Definition: pbx.c:3006
Prototypes for public functions only of internal interest,.
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1136
int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids)
Synchronously or asynchronously make an outbound call and send it to a particular extension...
Definition: pbx.c:7951
static struct ast_threadstorage hintdevice_data
Definition: pbx.c:352
Vector container support.
int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
This functionc locks given context, search for the right extension and fires out all peer in this ext...
Definition: pbx.c:4982
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
int ast_context_remove_extension_callerid2(struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked)
Definition: pbx.c:4987
unsigned int ast_hashtab_hash_string(const void *obj)
Hashes a string to a number.
Definition: hashtab.c:153
An API for managing task processing threads that can be shared across modules.
static void print_hintdevices_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: pbx.c:8950
static void destroy_state_cb(void *doomed)
Definition: pbx.c:3716
int is_pattern
Definition: pbx.c:263
void sw_free(struct ast_sw *sw)
Definition: pbx_sw.c:101
static int ast_add_extension_nolock(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Definition: pbx.c:6950
static struct ast_custom_function exception_function
Definition: pbx.c:2852
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
Definition: linkedlists.h:251
struct ast_channel_iterator * ast_channel_iterator_by_name_new(const char *name, size_t name_len)
Create a new channel iterator based on name.
Definition: channel.c:1388
#define ast_clear_flag(p, flag)
Definition: utils.h:77
static int find_hint_by_cb_id(void *obj, void *arg, int flags)
Find Hint by callback id.
Definition: pbx.c:3844
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:165
unsigned int in_separate_thread
Set if we&#39;ve spawned a thread to do our work.
Definition: pbx.c:7609
struct match_char * node
Definition: pbx.c:278
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
int ast_pbx_outgoing_exten_predial(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids, const char *predial_callee)
Definition: pbx.c:7961
int ast_pbx_hangup_handler_run(struct ast_channel *chan)
Run all hangup handlers on the channel.
const char * usage
Definition: cli.h:177
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:790
int pbx_checkcondition(const char *condition)
Evaluate a condition.
Definition: pbx.c:8321
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
static const struct cfextension_states extension_states[]
struct ast_channel * ast_dial_answered_steal(struct ast_dial *dial)
Steal the channel that answered.
Definition: dial.c:993
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
const char * cidmatch
Definition: pbx.c:241
#define ast_rwlock_wrlock(a)
Definition: lock.h:234
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3184
void unreference_cached_app(struct ast_app *app)
Definition: pbx.c:6179
struct match_char * pattern_tree
Definition: pbx.c:2431
const struct ast_include * ast_walk_context_includes(const struct ast_context *con, const struct ast_include *inc)
Definition: pbx.c:8668
unsigned int ast_hashtab_hash_int(const int num)
Definition: hashtab.c:205
#define EVENT_FLAG_REPORTING
Definition: manager.h:80
#define CLI_SUCCESS
Definition: cli.h:44
static void context_table_create_autohints(struct ast_hashtab *table)
Definition: pbx.c:6332
Assume that the ao2_container is already locked.
Definition: astobj2.h:1872
int ast_channel_softhangup_internal_flag(struct ast_channel *chan)
void * data
Definition: datastore.h:70
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
int ast_pbx_outgoing_app_predial(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, const struct ast_assigned_ids *assignedids, const char *predial_callee)
Definition: pbx.c:8025
struct ast_flags ast_options
Definition: options.c:61
const char * ast_get_include_name(const struct ast_include *include)
Definition: pbx_include.c:50
static struct ast_exten * ast_hint_extension_nolock(struct ast_channel *c, const char *context, const char *exten)
Find hint for given extension in context.
Definition: pbx.c:2991
Structure for dial plan hint devices.
Definition: pbx.c:369
char * strsep(char **str, const char *delims)
static const char * get_pattern_node(struct pattern_node *node, const char *src, int pattern, const char *extenbuf)
Definition: pbx.c:1513
#define ao2_t_callback_data(container, flags, cb_fn, arg, data, tag)
ao2_callback_data() is a generic function that applies cb_fn() to all objects in a container...
Definition: astobj2.h:1741
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
const char * app
Definition: pbx.c:246
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
const struct ast_ignorepat * ast_walk_context_ignorepats(const struct ast_context *con, const struct ast_ignorepat *ip)
Definition: pbx.c:8707
int dtimeoutms
Definition: pbx.h:212
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
Structure for rwlock and tracking information.
Definition: lock.h:156
struct timeval ast_mktime(struct ast_tm *const tmp, const char *zone)
Timezone-independent version of mktime(3).
Definition: localtime.c:2357
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static char * complete_core_show_hint(const char *line, const char *word, int pos, int state)
autocomplete for CLI command &#39;core show hint&#39;
Definition: pbx.c:5268
Standard Command Line Interface.
void ast_pbx_h_exten_run(struct ast_channel *chan, const char *context)
Run the h exten from the given context.
Definition: pbx.c:4209
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
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)
Definition: pbx.c:1064
ast_app: A registered application
Definition: pbx_app.c:45
int ast_extension_state_add_extended(const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
Add watcher for extended extension states.
Definition: pbx.c:3837
ext_match_t
Definition: extconf.h:215
unsigned int ast_hashtab_hash_contexts(const void *obj)
Definition: pbx.c:735
const char * ast_channel_name(const struct ast_channel *chan)
static int countcalls
Definition: pbx.c:773
static int show_dialplan_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, const struct ast_include *rinclude, int includecount, const char *includes[])
Definition: pbx.c:5516
const int pos
Definition: cli.h:164
#define AST_CAUSE_USER_BUSY
Definition: causes.h:106
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8596
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8793
int ast_async_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8798
#define AST_PBX_GOTO_FAILED
Definition: pbx.h:42
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
Definition: channel.c:1360
int refcount
Definition: pbx.c:294
#define ast_frfree(fr)
static const char * candidate_exten_advance(const char *str)
Definition: pbx.c:1219
int total_prio
Definition: pbx.c:5481
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: ael_main.c:211
static char * overrideswitch
Definition: pbx.c:765
static PGresult * result
Definition: cel_pgsql.c:88
static char * parse_hint_device(struct ast_str *hint_args)
Definition: pbx.c:3056
struct stasis_message_type * ast_presence_state_message_type(void)
Get presence state message type.
int ast_context_remove_ignorepat(const char *context, const char *ignorepat, const char *registrar)
Definition: pbx.c:6837
int ast_thread_inhibit_escalations(void)
Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations...
static unsigned int hashtab_hash_extens(const void *obj)
Definition: pbx.c:741
static int add_priority(struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace)
add the extension in the priority chain.
Definition: pbx.c:7109
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition: stasis.c:1025
static struct ao2_container * statecbs
Definition: pbx.c:803
struct stasis_forward * sub
Definition: res_corosync.c:240
Data structure associated with a single frame of data.
const char * cidmatch_display
Definition: pbx.c:242
static int hintdevice_hash_cb(const void *obj, const int flags)
Definition: pbx.c:395
int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
Register a custom function.
Internal Asterisk hangup causes.
enum ast_presence_state state
static int ast_remove_hint(struct ast_exten *e)
Remove hint from extension.
Definition: pbx.c:3945
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition: pbx.c:2485
struct ast_switch * swo
Definition: extconf.h:240
int ast_context_lockmacro(const char *context)
locks the macrolock in the given context
Definition: pbx.c:5162
int getloadavg(double *list, int nelem)
You shouldn&#39;t care about the contents of this struct.
Definition: devicestate.h:230
struct ast_hashtab * root_table
Definition: pbx.c:287
Counters for the show dialplan manager command.
Definition: pbx.c:5477
int canmatch
Definition: pbx.c:277
static struct ast_context * contexts
Definition: pbx.c:776
static struct test_val b
The structure that contains device state.
Definition: devicestate.h:240
Definition: search.h:40
const char * ast_channel_context(const struct ast_channel *chan)
Handy terminal functions for vt* terms.
int error(const char *format,...)
Definition: utils/frame.c:999
const struct ast_include * ast_context_includes_get(const struct ast_context *con, int idx)
Definition: pbx.c:8702
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:78
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8538
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
#define ast_hashtab_create(initial_buckets, compare, resize, newsize, hash, do_locking)
Definition: hashtab.h:261
struct ast_context * parent
Definition: pbx.c:245
enum queue_result id
Definition: app_queue.c:1507
int ast_context_add_include(const char *context, const char *include, const char *registrar)
Add a context include.
Definition: pbx.c:6706
char * last_presence_message
Definition: pbx.c:340
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:6198
int ast_active_calls(void)
Retrieve the number of active calls.
Definition: pbx.c:4764
#define ast_mutex_init(pmutex)
Definition: lock.h:184
Generic container type.
static int ext_cmp_exten(const char *left, const char *right)
Definition: pbx.c:1876
int total_length
Definition: pbx.c:275
void * data
Definition: pbx.c:248
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:861
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:280
int ast_extension_state_add_destroy_extended(const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
Add watcher for extended extension states with destructor.
Definition: pbx.c:3831
const char * ast_get_extension_label(struct ast_exten *exten)
Definition: pbx.c:8553
Search option field mask.
Definition: astobj2.h:1076
struct match_char * next_char
Definition: pbx.c:267
int(* ast_state_cb_type)(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
Typedef for devicestate and hint callbacks.
Definition: pbx.h:112
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static int execute_state_callback(ast_state_cb_type cb, const char *context, const char *exten, void *data, enum ast_state_cb_update_reason reason, struct ast_hint *hint, struct ao2_container *device_state_info)
Definition: pbx.c:3250
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
Simply remove extension from context.
Definition: pbx.c:4952
#define ast_mutex_destroy(a)
Definition: lock.h:186
static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
The return value depends on the action:
Definition: pbx.c:2875
static const char exten_name[]
STASIS_MESSAGE_TYPE_DEFN_LOCAL(hint_change_message_type)
struct ast_exten * exten
Definition: pbx.c:280
int ast_str_get_hint(struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten)
Get hint for channel.
Definition: pbx.c:4159
static void print_hints_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: pbx.c:8939
int ast_dial_reason(struct ast_dial *dial, int num)
Get the reason an outgoing channel has failed.
Definition: dial.c:1271
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
struct stasis_topic * ast_presence_state_topic_all(void)
Get presence state topic.
Say numbers and dates (maybe words one day too)
#define DEBUG_ATLEAST(level)
Definition: logger.h:441
#define AST_CAUSE_CALL_REJECTED
Definition: causes.h:110
char * last_presence_subtype
Definition: pbx.c:339
void ast_channel_priority_set(struct ast_channel *chan, int value)
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
int ast_context_unlockmacro(const char *context)
Unlocks the macrolock in the given context.
Definition: pbx.c:5184
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1259
struct ast_sws alts
Definition: pbx.c:292
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
Asterisk module definitions.
const ast_string_field context
Definition: pbx.c:625
unsigned int no_hangup_chan
Definition: pbx.h:398
int ast_hashtab_size(struct ast_hashtab *tab)
Returns the number of elements stored in the hashtab.
Definition: hashtab.c:577
void ast_hashtab_get_stats(struct ast_hashtab *tab, int *biggest_bucket_size, int *resize_count, int *num_objects, int *num_buckets)
Returns key stats for the table.
Definition: hashtab.c:563
char exten_name[AST_MAX_EXTENSION]
Definition: pbx.c:343
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390
int specif
Definition: pbx.c:1454
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
int total_context
Definition: pbx.c:5479
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:298
static int hint_id_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:3891
ast_callid ast_channel_callid(const struct ast_channel *chan)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
int ast_get_extension_priority(struct ast_exten *exten)
Definition: pbx.c:8558
static struct ao2_container * autohints
Container for autohint contexts.
Definition: pbx.c:380
int extension_existence
Definition: pbx.c:5483
void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Set the connected line information in the Asterisk channel.
Definition: channel.c:8404
int ast_context_remove_extension_callerid(const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar)
Definition: pbx.c:4957
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:518
static void pbx_outgoing_destroy(void *obj)
Destructor for outgoing structure.
Definition: pbx.c:7613
const char * ast_extension_state2str(int extension_state)
Return extension_state as string.
Definition: pbx.c:3126
Structure for mutex and tracking information.
Definition: lock.h:135
char buf[256]
Definition: pbx.c:1456
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:1250
struct match_char * pattern_tree
Definition: pbx.c:288
int ast_add_extension2_nolock(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, const char *registrar_file, int registrar_line)
Same as ast_add_extension2, but assumes you have already locked context.
Definition: pbx.c:7308
int ast_context_includes_count(const struct ast_context *con)
Definition: pbx.c:8697
const char * ast_presence_state2str(enum ast_presence_state state)
Convert presence state to text string for output.
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition: vector.h:865
jack_status_t status
Definition: app_jack.c:146
const char * ast_get_extension_cidmatch(struct ast_exten *e)
Definition: pbx.c:8591
#define BITS_PER
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
short word
#define ast_mutex_unlock(a)
Definition: lock.h:188
static struct stasis_subscription * device_state_sub
Subscription for device state change events.
Definition: pbx.c:768
static struct ast_exten * get_canmatch_exten(struct match_char *node)
Definition: pbx.c:1141
static uint16_t t1
Definition: res_pktccops.c:157
static char prefix[MAX_PREFIX]
Definition: http.c:141
static void destroy_exten(struct ast_exten *e)
Definition: pbx.c:4678
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
hashtable functions for contexts
Definition: pbx.c:683
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
int rtimeoutms
Definition: pbx.h:213
int deleted
Definition: pbx.c:264
match_char: forms a syntax tree for quick matching of extension patterns
Definition: pbx.c:261
static int enabled
Definition: dnsmgr.c:91
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3201
void ast_hashtab_destroy(struct ast_hashtab *tab, void(*objdestroyfunc)(void *obj))
This func will free the hash table and all its memory.
Definition: hashtab.c:363
static void insert_in_next_chars_alt_char_list(struct match_char **parent_ptr, struct match_char *node)
Definition: pbx.c:1418
static struct test_val a
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:343
#define ao2_link(container, obj)
Definition: astobj2.h:1549
int ast_dial_prerun(struct ast_dial *dial, struct ast_channel *chan, struct ast_format_cap *cap)
Request all appended channels, but do not dial.
Definition: dial.c:433
void * ast_hashtab_remove_this_object(struct ast_hashtab *tab, void *obj)
Hash the object and then compare ptrs in bucket list instead of calling the compare routine...
Definition: hashtab.c:789