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