Asterisk - The Open Source Telephony Project  21.4.1
main/app.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, 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 Convenient Application Routines
22  *
23  * \author Mark Spencer <markster@digium.com>
24  */
25 
26 /*!
27  * Application Skeleton is an example of creating an application for Asterisk.
28  * \example app_skel.c
29  */
30 
31 /*** MODULEINFO
32  <support_level>core</support_level>
33  ***/
34 
35 #include "asterisk.h"
36 
37 #ifdef HAVE_SYS_STAT_H
38 #include <sys/stat.h>
39 #endif
40 #include <regex.h> /* for regcomp(3) */
41 #include <sys/file.h> /* for flock(2) */
42 #include <signal.h> /* for pthread_sigmask(3) */
43 #include <stdlib.h> /* for closefrom(3) */
44 #include <sys/types.h>
45 #include <sys/wait.h> /* for waitpid(2) */
46 #ifndef HAVE_CLOSEFROM
47 #include <dirent.h> /* for opendir(3) */
48 #endif
49 #ifdef HAVE_CAP
50 #include <sys/capability.h>
51 #endif /* HAVE_CAP */
52 
53 #include "asterisk/paths.h" /* use ast_config_AST_DATA_DIR */
54 #include "asterisk/channel.h"
55 #include "asterisk/pbx.h"
56 #include "asterisk/file.h"
57 #include "asterisk/app.h"
58 #include "asterisk/dsp.h"
59 #include "asterisk/utils.h"
60 #include "asterisk/lock.h"
61 #include "asterisk/indications.h"
62 #include "asterisk/linkedlists.h"
63 #include "asterisk/threadstorage.h"
64 #include "asterisk/test.h"
65 #include "asterisk/module.h"
66 #include "asterisk/astobj2.h"
67 #include "asterisk/stasis.h"
68 #include "asterisk/stasis_channels.h"
69 #include "asterisk/json.h"
70 #include "asterisk/format_cache.h"
71 
72 AST_THREADSTORAGE_PUBLIC(ast_str_thread_global_buf);
73 
74 static pthread_t shaun_of_the_dead_thread = AST_PTHREADT_NULL;
75 
76 struct zombie {
77  pid_t pid;
78  AST_LIST_ENTRY(zombie) list;
79 };
80 
82 
83 #ifdef HAVE_CAP
84 static cap_t child_cap;
85 #endif
86 /*!
87  * \brief Define \ref stasis topic objects
88  * @{
89  */
91 static struct stasis_topic_pool *queue_topic_pool;
92 
93 /*! @} */
94 
95 static void *shaun_of_the_dead(void *data)
96 {
97  struct zombie *cur;
98  int status;
99  for (;;) {
100  if (!AST_LIST_EMPTY(&zombies)) {
101  /* Don't allow cancellation while we have a lock. */
102  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
105  if (waitpid(cur->pid, &status, WNOHANG) != 0) {
107  ast_free(cur);
108  }
109  }
112  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
113  }
114  pthread_testcancel();
115  /* Wait for 60 seconds, without engaging in a busy loop. */
116  ast_poll(NULL, 0, AST_LIST_FIRST(&zombies) ? 5000 : 60000);
117  }
118  return NULL;
119 }
120 
121 
122 #define AST_MAX_FORMATS 10
123 
125 
126 /*!
127  * \brief This function presents a dialtone and reads an extension into 'collect'
128  * which must be a pointer to a **pre-initialized** array of char having a
129  * size of 'size' suitable for writing to. It will collect no more than the smaller
130  * of 'maxlen' or 'size' minus the original strlen() of collect digits.
131  * \param chan struct.
132  * \param context
133  * \param collect
134  * \param size
135  * \param maxlen
136  * \param timeout timeout in milliseconds
137 */
138 int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout)
139 {
140  struct ast_tone_zone_sound *ts;
141  int res = 0, x = 0;
142 
143  if (maxlen > size) {
144  maxlen = size;
145  }
146 
147  if (!timeout) {
148  if (ast_channel_pbx(chan) && ast_channel_pbx(chan)->dtimeoutms) {
149  timeout = ast_channel_pbx(chan)->dtimeoutms;
150  } else {
151  timeout = 5000;
152  }
153  }
154 
155  if ((ts = ast_get_indication_tone(ast_channel_zone(chan), "dial"))) {
156  res = ast_playtones_start(chan, 0, ts->data, 0);
157  ts = ast_tone_zone_sound_unref(ts);
158  } else {
159  ast_log(LOG_NOTICE, "Huh....? no dial for indications?\n");
160  }
161 
162  for (x = strlen(collect); x < maxlen; ) {
163  res = ast_waitfordigit(chan, timeout);
164  if (!ast_ignore_pattern(context, collect)) {
165  ast_playtones_stop(chan);
166  }
167  if (res < 1) {
168  break;
169  }
170  if (res == '#') {
171  break;
172  }
173  collect[x++] = res;
174  if (!ast_matchmore_extension(chan, context, collect, 1,
175  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
176  break;
177  }
178  }
179 
180  if (res >= 0) {
181  res = ast_exists_extension(chan, context, collect, 1,
182  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)) ? 1 : 0;
183  }
184 
185  return res;
186 }
187 
188 enum ast_getdata_result ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout)
189 {
190  return ast_app_getdata_terminator(c, prompt, s, maxlen, timeout, NULL);
191 }
192 
193 enum ast_getdata_result ast_app_getdata_terminator(struct ast_channel *c, const char *prompt, char *s,
194  int maxlen, int timeout, char *terminator)
195 {
196  int res = 0, to, fto;
197  char *front, *filename;
198 
199  /* XXX Merge with full version? XXX */
200 
201  if (maxlen)
202  s[0] = '\0';
203 
204  if (!prompt)
205  prompt = "";
206 
207  filename = ast_strdupa(prompt);
208  while ((front = ast_strsep(&filename, '&', AST_STRSEP_STRIP | AST_STRSEP_TRIM))) {
209  if (!ast_strlen_zero(front)) {
210  res = ast_streamfile(c, front, ast_channel_language(c));
211  if (res)
212  continue;
213  }
214  if (ast_strlen_zero(filename)) {
215  /* set timeouts for the last prompt */
216  fto = ast_channel_pbx(c) ? ast_channel_pbx(c)->rtimeoutms : 6000;
217  to = ast_channel_pbx(c) ? ast_channel_pbx(c)->dtimeoutms : 2000;
218 
219  if (timeout > 0) {
220  fto = to = timeout;
221  }
222  if (timeout < 0) {
223  fto = to = 1000000000;
224  }
225  } else {
226  /* there is more than one prompt, so
227  * get rid of the long timeout between
228  * prompts, and make it 50ms */
229  fto = 50;
230  to = ast_channel_pbx(c) ? ast_channel_pbx(c)->dtimeoutms : 2000;
231  }
232  res = ast_readstring(c, s, maxlen, to, fto, (terminator ? terminator : "#"));
234  return res;
235  }
236  if (!ast_strlen_zero(s)) {
237  return res;
238  }
239  }
240 
241  return res;
242 }
243 
244 /* The lock type used by ast_lock_path() / ast_unlock_path() */
245 static enum AST_LOCK_TYPE ast_lock_type = AST_LOCK_TYPE_LOCKFILE;
246 
247 int ast_app_getdata_full(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
248 {
249  int res, to = 2000, fto = 6000;
250 
251  if (!ast_strlen_zero(prompt)) {
252  res = ast_streamfile(c, prompt, ast_channel_language(c));
253  if (res < 0) {
254  return res;
255  }
256  }
257 
258  if (timeout > 0) {
259  fto = to = timeout;
260  }
261  if (timeout < 0) {
262  fto = to = 1000000000;
263  }
264 
265  res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
266 
267  return res;
268 }
269 
270 /* BUGBUG this is not thread safe. */
271 static const struct ast_app_stack_funcs *app_stack_callbacks;
272 
274 {
275  app_stack_callbacks = funcs;
276 }
277 
278 const char *ast_app_expand_sub_args(struct ast_channel *chan, const char *args)
279 {
280  const struct ast_app_stack_funcs *funcs;
281  const char *new_args;
282 
283  funcs = app_stack_callbacks;
284  if (!funcs || !funcs->expand_sub_args || !ast_module_running_ref(funcs->module)) {
285  ast_log(LOG_WARNING,
286  "Cannot expand 'Gosub(%s)' arguments. The app_stack module is not available.\n",
287  args);
288  return NULL;
289  }
290 
291  new_args = funcs->expand_sub_args(chan, args);
292  ast_module_unref(funcs->module);
293 
294  return new_args;
295 }
296 
297 int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_args, int ignore_hangup)
298 {
299  const struct ast_app_stack_funcs *funcs;
300  int res;
301 
302  funcs = app_stack_callbacks;
303  if (!funcs || !funcs->run_sub || !ast_module_running_ref(funcs->module)) {
304  ast_log(LOG_WARNING,
305  "Cannot run 'Gosub(%s)'. The app_stack module is not available.\n",
306  sub_args);
307  return -1;
308  }
309 
310  if (autoservice_chan) {
311  ast_autoservice_start(autoservice_chan);
312  }
313 
314  res = funcs->run_sub(sub_chan, sub_args, ignore_hangup);
315  ast_module_unref(funcs->module);
316 
317  if (autoservice_chan) {
318  ast_autoservice_stop(autoservice_chan);
319  }
320 
321  if (!ignore_hangup && ast_check_hangup_locked(sub_chan)) {
322  ast_queue_hangup(sub_chan);
323  }
324 
325  return res;
326 }
327 
328 int ast_app_run_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_location, const char *sub_args, int ignore_hangup)
329 {
330  int res;
331  char *args_str;
332  size_t args_len;
333 
334  if (ast_strlen_zero(sub_args)) {
335  return ast_app_exec_sub(autoservice_chan, sub_chan, sub_location, ignore_hangup);
336  }
337 
338  /* Create the Gosub application argument string. */
339  args_len = strlen(sub_location) + strlen(sub_args) + 3;
340  args_str = ast_malloc(args_len);
341  if (!args_str) {
342  return -1;
343  }
344  snprintf(args_str, args_len, "%s(%s)", sub_location, sub_args);
345 
346  res = ast_app_exec_sub(autoservice_chan, sub_chan, args_str, ignore_hangup);
347  ast_free(args_str);
348  return res;
349 }
350 
351 /*! \brief The container for the voicemail provider */
352 static AO2_GLOBAL_OBJ_STATIC(vm_provider);
353 
354 /*! Voicemail not registered warning */
355 static int vm_warnings;
356 
358 {
359  struct ast_vm_functions *table;
360  int is_registered;
361 
362  table = ao2_global_obj_ref(vm_provider);
363  is_registered = table ? 1 : 0;
364  ao2_cleanup(table);
365  return is_registered;
366 }
367 
368 int __ast_vm_register(const struct ast_vm_functions *vm_table, struct ast_module *module)
369 {
370  RAII_VAR(struct ast_vm_functions *, table, NULL, ao2_cleanup);
371 
372  if (!vm_table->module_name) {
373  ast_log(LOG_ERROR, "Voicemail provider missing required information.\n");
374  return -1;
375  }
376  if (vm_table->module_version != VM_MODULE_VERSION) {
377  ast_log(LOG_ERROR, "Voicemail provider '%s' has incorrect version\n",
378  vm_table->module_name);
379  return -1;
380  }
381 
382  table = ao2_global_obj_ref(vm_provider);
383  if (table) {
384  ast_log(LOG_WARNING, "Voicemail provider already registered by %s.\n",
385  table->module_name);
387  }
388 
389  table = ao2_alloc_options(sizeof(*table), NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
390  if (!table) {
391  return -1;
392  }
393  *table = *vm_table;
394  table->module = module;
395 
396  ao2_global_obj_replace_unref(vm_provider, table);
397  return 0;
398 }
399 
401 {
402  struct ast_vm_functions *table;
403 
404  table = ao2_global_obj_ref(vm_provider);
405  if (table && !strcmp(table->module_name, module_name)) {
406  ao2_global_obj_release(vm_provider);
407  }
408  ao2_cleanup(table);
409 }
410 
411 #ifdef TEST_FRAMEWORK
412 /*! \brief Holding container for the voicemail provider used while testing */
413 static AO2_GLOBAL_OBJ_STATIC(vm_provider_holder);
414 static int provider_is_swapped = 0;
415 
416 void ast_vm_test_swap_table_in(const struct ast_vm_functions *vm_table)
417 {
418  RAII_VAR(struct ast_vm_functions *, holding_table, NULL, ao2_cleanup);
419  RAII_VAR(struct ast_vm_functions *, new_table, NULL, ao2_cleanup);
420 
421  if (provider_is_swapped) {
422  ast_log(LOG_ERROR, "Attempted to swap in test function table without swapping out old test table.\n");
423  return;
424  }
425 
426  holding_table = ao2_global_obj_ref(vm_provider);
427 
428  if (holding_table) {
429  ao2_global_obj_replace_unref(vm_provider_holder, holding_table);
430  }
431 
432  new_table = ao2_alloc_options(sizeof(*new_table), NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
433  if (!new_table) {
434  return;
435  }
436  *new_table = *vm_table;
437 
438  ao2_global_obj_replace_unref(vm_provider, new_table);
439  provider_is_swapped = 1;
440 }
441 
442 void ast_vm_test_swap_table_out(void)
443 {
444  RAII_VAR(struct ast_vm_functions *, held_table, NULL, ao2_cleanup);
445 
446  if (!provider_is_swapped) {
447  ast_log(LOG_ERROR, "Attempted to swap out test function table, but none is currently installed.\n");
448  return;
449  }
450 
451  held_table = ao2_global_obj_ref(vm_provider_holder);
452  if (!held_table) {
453  return;
454  }
455 
456  ao2_global_obj_replace_unref(vm_provider, held_table);
457  ao2_global_obj_release(vm_provider_holder);
458  provider_is_swapped = 0;
459 }
460 #endif
461 
462 /*! \brief The container for the voicemail greeter provider */
463 static AO2_GLOBAL_OBJ_STATIC(vm_greeter_provider);
464 
465 /*! Voicemail greeter not registered warning */
467 
469 {
470  struct ast_vm_greeter_functions *table;
471  int is_registered;
472 
473  table = ao2_global_obj_ref(vm_greeter_provider);
474  is_registered = table ? 1 : 0;
475  ao2_cleanup(table);
476  return is_registered;
477 }
478 
480 {
481  RAII_VAR(struct ast_vm_greeter_functions *, table, NULL, ao2_cleanup);
482 
483  if (!vm_table->module_name) {
484  ast_log(LOG_ERROR, "Voicemail greeter provider missing required information.\n");
485  return -1;
486  }
487  if (vm_table->module_version != VM_GREETER_MODULE_VERSION) {
488  ast_log(LOG_ERROR, "Voicemail greeter provider '%s' has incorrect version\n",
489  vm_table->module_name);
490  return -1;
491  }
492 
493  table = ao2_global_obj_ref(vm_greeter_provider);
494  if (table) {
495  ast_log(LOG_WARNING, "Voicemail greeter provider already registered by %s.\n",
496  table->module_name);
498  }
499 
500  table = ao2_alloc_options(sizeof(*table), NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
501  if (!table) {
502  return -1;
503  }
504  *table = *vm_table;
505  table->module = module;
506 
507  ao2_global_obj_replace_unref(vm_greeter_provider, table);
508  return 0;
509 }
510 
512 {
513  struct ast_vm_greeter_functions *table;
514 
515  table = ao2_global_obj_ref(vm_greeter_provider);
516  if (table && !strcmp(table->module_name, module_name)) {
517  ao2_global_obj_release(vm_greeter_provider);
518  }
519  ao2_cleanup(table);
520 }
521 
522 #ifdef TEST_FRAMEWORK
523 static ast_vm_test_create_user_fn *ast_vm_test_create_user_func = NULL;
524 static ast_vm_test_destroy_user_fn *ast_vm_test_destroy_user_func = NULL;
525 
526 void ast_install_vm_test_functions(ast_vm_test_create_user_fn *vm_test_create_user_func,
527  ast_vm_test_destroy_user_fn *vm_test_destroy_user_func)
528 {
529  ast_vm_test_create_user_func = vm_test_create_user_func;
530  ast_vm_test_destroy_user_func = vm_test_destroy_user_func;
531 }
532 
533 void ast_uninstall_vm_test_functions(void)
534 {
535  ast_vm_test_create_user_func = NULL;
536  ast_vm_test_destroy_user_func = NULL;
537 }
538 #endif
539 
540 static void vm_warn_no_provider(void)
541 {
542  if (vm_warnings++ % 10 == 0) {
543  ast_verb(3, "No voicemail provider registered.\n");
544  }
545 }
546 
547 #define VM_API_CALL(res, api_call, api_parms) \
548  do { \
549  struct ast_vm_functions *table; \
550  table = ao2_global_obj_ref(vm_provider); \
551  if (!table) { \
552  vm_warn_no_provider(); \
553  } else if (table->api_call) { \
554  ast_module_ref(table->module); \
555  (res) = table->api_call api_parms; \
556  ast_module_unref(table->module); \
557  } \
558  ao2_cleanup(table); \
559  } while (0)
560 
561 static void vm_greeter_warn_no_provider(void)
562 {
563  if (vm_greeter_warnings++ % 10 == 0) {
564  ast_verb(3, "No voicemail greeter provider registered.\n");
565  }
566 }
567 
568 #define VM_GREETER_API_CALL(res, api_call, api_parms) \
569  do { \
570  struct ast_vm_greeter_functions *table; \
571  table = ao2_global_obj_ref(vm_greeter_provider); \
572  if (!table) { \
573  vm_greeter_warn_no_provider(); \
574  } else if (table->api_call) { \
575  ast_module_ref(table->module); \
576  (res) = table->api_call api_parms; \
577  ast_module_unref(table->module); \
578  } \
579  ao2_cleanup(table); \
580  } while (0)
581 
582 int ast_app_has_voicemail(const char *mailboxes, const char *folder)
583 {
584  int res = 0;
585 
586  VM_API_CALL(res, has_voicemail, (mailboxes, folder));
587  return res;
588 }
589 
590 /*!
591  * \internal
592  * \brief Function used as a callback for ast_copy_recording_to_vm when a real one isn't installed.
593  * \param vm_rec_data Stores crucial information about the voicemail that will basically just be used
594  * to figure out what the name of the recipient was supposed to be
595  */
597 {
598  int res = -1;
599 
600  VM_API_CALL(res, copy_recording_to_vm, (vm_rec_data));
601  return res;
602 }
603 
604 int ast_app_inboxcount(const char *mailboxes, int *newmsgs, int *oldmsgs)
605 {
606  int res = 0;
607 
608  if (newmsgs) {
609  *newmsgs = 0;
610  }
611  if (oldmsgs) {
612  *oldmsgs = 0;
613  }
614 
615  VM_API_CALL(res, inboxcount, (mailboxes, newmsgs, oldmsgs));
616  return res;
617 }
618 
619 int ast_app_inboxcount2(const char *mailboxes, int *urgentmsgs, int *newmsgs, int *oldmsgs)
620 {
621  int res = 0;
622 
623  if (newmsgs) {
624  *newmsgs = 0;
625  }
626  if (oldmsgs) {
627  *oldmsgs = 0;
628  }
629  if (urgentmsgs) {
630  *urgentmsgs = 0;
631  }
632 
633  VM_API_CALL(res, inboxcount2, (mailboxes, urgentmsgs, newmsgs, oldmsgs));
634  return res;
635 }
636 
637 int ast_app_sayname(struct ast_channel *chan, const char *mailbox_id)
638 {
639  int res = -1;
640 
641  VM_GREETER_API_CALL(res, sayname, (chan, mailbox_id));
642  return res;
643 }
644 
645 int ast_app_messagecount(const char *mailbox_id, const char *folder)
646 {
647  int res = 0;
648 
649  VM_API_CALL(res, messagecount, (mailbox_id, folder));
650  return res;
651 }
652 
653 const char *ast_vm_index_to_foldername(int id)
654 {
655  const char *res = NULL;
656 
657  VM_API_CALL(res, index_to_foldername, (id));
658  return res;
659 }
660 
662  const char *context,
663  const char *folder,
664  int descending,
665  enum ast_vm_snapshot_sort_val sort_val,
666  int combine_INBOX_and_OLD)
667 {
668  struct ast_vm_mailbox_snapshot *res = NULL;
669 
670  VM_API_CALL(res, mailbox_snapshot_create, (mailbox, context, folder, descending,
671  sort_val, combine_INBOX_and_OLD));
672  return res;
673 }
674 
676 {
677  struct ast_vm_mailbox_snapshot *res = NULL;
678 
679  VM_API_CALL(res, mailbox_snapshot_destroy, (mailbox_snapshot));
680  return res;
681 }
682 
683 int ast_vm_msg_move(const char *mailbox,
684  const char *context,
685  size_t num_msgs,
686  const char *oldfolder,
687  const char *old_msg_ids[],
688  const char *newfolder)
689 {
690  int res = 0;
691 
692  VM_API_CALL(res, msg_move, (mailbox, context, num_msgs, oldfolder, old_msg_ids,
693  newfolder));
694  return res;
695 }
696 
697 int ast_vm_msg_remove(const char *mailbox,
698  const char *context,
699  size_t num_msgs,
700  const char *folder,
701  const char *msgs[])
702 {
703  int res = 0;
704 
705  VM_API_CALL(res, msg_remove, (mailbox, context, num_msgs, folder, msgs));
706  return res;
707 }
708 
709 int ast_vm_msg_forward(const char *from_mailbox,
710  const char *from_context,
711  const char *from_folder,
712  const char *to_mailbox,
713  const char *to_context,
714  const char *to_folder,
715  size_t num_msgs,
716  const char *msg_ids[],
717  int delete_old)
718 {
719  int res = 0;
720 
721  VM_API_CALL(res, msg_forward, (from_mailbox, from_context, from_folder, to_mailbox,
722  to_context, to_folder, num_msgs, msg_ids, delete_old));
723  return res;
724 }
725 
726 int ast_vm_msg_play(struct ast_channel *chan,
727  const char *mailbox,
728  const char *context,
729  const char *folder,
730  const char *msg_num,
731  ast_vm_msg_play_cb *cb)
732 {
733  int res = 0;
734 
735  VM_API_CALL(res, msg_play, (chan, mailbox, context, folder, msg_num, cb));
736  return res;
737 }
738 
739 #ifdef TEST_FRAMEWORK
740 int ast_vm_test_create_user(const char *context, const char *mailbox)
741 {
742  if (ast_vm_test_create_user_func) {
743  return ast_vm_test_create_user_func(context, mailbox);
744  }
745  return 0;
746 }
747 
748 int ast_vm_test_destroy_user(const char *context, const char *mailbox)
749 {
750  if (ast_vm_test_destroy_user_func) {
751  return ast_vm_test_destroy_user_func(context, mailbox);
752  }
753  return 0;
754 }
755 #endif
756 
757 static int external_sleep(struct ast_channel *chan, int ms)
758 {
759  usleep(ms * 1000);
760  return 0;
761 }
762 
763 static int sf_stream(struct ast_channel *chan, struct ast_channel *chan2, const char *digits, int frequency, int is_external)
764 {
765  /* Bell System Technical Journal 39 (Nov. 1960) */
766  #define SF_ON 67
767  #define SF_OFF 33
768  #define SF_BETWEEN 600
769 
770  const char *ptr;
771  int res;
772  struct ast_silence_generator *silgen = NULL, *silgen2 = NULL;
773  char *freq;
774  int (*my_sleep)(struct ast_channel *chan, int ms);
775 
776  if (frequency >= 100000) {
777  ast_log(LOG_WARNING, "Frequency too large: %d\n", frequency);
778  return -1;
779  }
780 
781  if (is_external) {
782  my_sleep = external_sleep;
783  } else {
784  my_sleep = ast_safe_sleep;
785  }
786 
787  /* Need a quiet time before sending digits. */
788  if (ast_opt_transmit_silence) {
790  if (chan2) {
791  silgen2 = ast_channel_start_silence_generator(chan2);
792  }
793  }
794  if (chan2) {
795  ast_autoservice_start(chan2);
796  }
797  res = my_sleep(chan, 100);
798  if (chan2) {
799  ast_autoservice_stop(chan2);
800  }
801  if (res) {
802  goto sf_stream_cleanup;
803  }
804 
805 /* len(SF_ON) + len(SF_OFF) + len(0) + maxlen(frequency) + /,/ + null terminator = 2 + 2 + 1 + 5 at most + 3 + 1 = 14 */
806 #define SF_BUF_LEN 20
807  freq = ast_alloca(SF_BUF_LEN); /* min 20 to avoid compiler warning about insufficient buffer */
808  /* pauses need to send audio, so send 0 Hz */
809  snprintf(freq, SF_BUF_LEN, "%d/%d,%d/%d", frequency, SF_ON, 0, SF_OFF);
810 
811  for (ptr = digits; *ptr; ptr++) {
812  if (*ptr == 'w') {
813  /* 'w' -- wait half a second */
814  if (chan2) {
815  ast_autoservice_start(chan2);
816  }
817  res = my_sleep(chan, 500);
818  if (chan2) {
819  ast_autoservice_stop(chan2);
820  }
821  if (res) {
822  break;
823  }
824  } else if (*ptr == 'h' || *ptr == 'H') {
825  /* 'h' -- 2600 Hz for half a second, but
826  only to far end of trunk, not near end */
827  ast_playtones_start(chan, 0, "2600", 0);
828  if (chan2) {
829  ast_playtones_start(chan2, 0, "0", 0);
830  ast_autoservice_start(chan2);
831  }
832  res = my_sleep(chan, 250);
833  ast_senddigit_mf_end(chan);
834  if (chan2) {
835  ast_autoservice_stop(chan2);
836  ast_senddigit_mf_end(chan2);
837  }
838  if (res) {
839  break;
840  }
841  } else if (strchr("0123456789*#ABCDabcdwWfF", *ptr)) {
842  if (*ptr == 'f' || *ptr == 'F') {
843  /* ignore return values if not supported by channel */
845  } else if (*ptr == 'W') {
846  /* ignore return values if not supported by channel */
848  } else {
849  /* Character represents valid SF */
850  int beeps;
851  if (*ptr == '*') {
852  beeps = 11;
853  } else if (*ptr == '#') {
854  beeps = 12;
855  } else if (*ptr == 'D') {
856  beeps = 13;
857  } else if (*ptr == 'C') {
858  beeps = 14;
859  } else if (*ptr == 'B') {
860  beeps = 15;
861  } else if (*ptr == 'A') {
862  beeps = 16;
863  } else {
864  beeps = (*ptr == '0') ? 10 : *ptr - '0';
865  }
866  while (beeps-- > 0) {
867  ast_playtones_start(chan, 0, freq, 0);
868  if (chan2) {
869  ast_playtones_start(chan2, 0, freq, 0);
870  ast_autoservice_start(chan2);
871  }
872  res = my_sleep(chan, SF_ON + SF_OFF);
873  ast_senddigit_mf_end(chan);
874  if (chan2) {
875  ast_autoservice_stop(chan2);
876  ast_senddigit_mf_end(chan2);
877  }
878  if (res) {
879  break;
880  }
881  }
882  }
883  /* pause between digits */
884  ast_playtones_start(chan, 0, "0", 0);
885  if (chan2) {
886  ast_playtones_start(chan2, 0, "0", 0);
887  ast_autoservice_start(chan2);
888  }
889  res = my_sleep(chan, SF_BETWEEN);
890  if (chan2) {
891  ast_autoservice_stop(chan2);
892  ast_senddigit_mf_end(chan2);
893  }
894  ast_senddigit_mf_end(chan);
895  if (res) {
896  break;
897  }
898  } else {
899  ast_log(LOG_WARNING, "Illegal SF character '%c' in string. (0-9A-DwWfFhH allowed)\n", *ptr);
900  }
901  }
902 
903 sf_stream_cleanup:
904  if (silgen) {
906  }
907  if (silgen2) {
908  ast_channel_stop_silence_generator(chan2, silgen2);
909  }
910 
911  return res;
912 }
913 
914 static int mf_stream(struct ast_channel *chan, struct ast_channel *chan2, const char *digits, int between, unsigned int duration,
915  unsigned int durationkp, unsigned int durationst, int is_external)
916 {
917  const char *ptr;
918  int res;
919  struct ast_silence_generator *silgen = NULL, *silgen2 = NULL;
920  int (*my_sleep)(struct ast_channel *chan, int ms);
921 
922  if (is_external) {
923  my_sleep = external_sleep;
924  } else {
925  my_sleep = ast_safe_sleep;
926  }
927 
928  if (!between) {
929  between = 100;
930  }
931 
932  /* Need a quiet time before sending digits. */
933  if (ast_opt_transmit_silence) {
935  if (chan2) {
936  silgen2 = ast_channel_start_silence_generator(chan2);
937  }
938  }
939  if (chan2) {
940  ast_autoservice_start(chan2);
941  }
942  res = my_sleep(chan, 100);
943  if (chan2) {
944  ast_autoservice_stop(chan2);
945  }
946  if (res) {
947  goto mf_stream_cleanup;
948  }
949 
950  for (ptr = digits; *ptr; ptr++) {
951  if (*ptr == 'w') {
952  /* 'w' -- wait half a second */
953  if (chan2) {
954  ast_autoservice_start(chan2);
955  }
956  res = my_sleep(chan, 500);
957  if (chan2) {
958  ast_autoservice_stop(chan2);
959  }
960  if (res) {
961  break;
962  }
963  } else if (*ptr == 'h' || *ptr == 'H') {
964  /* 'h' -- 2600 Hz for half a second, but
965  only to far end of trunk, not near end */
966  ast_playtones_start(chan, 0, "2600", 0);
967  if (chan2) {
968  ast_playtones_start(chan2, 0, "0", 0);
969  ast_autoservice_start(chan2);
970  }
971  res = my_sleep(chan, 250);
972  ast_senddigit_mf_end(chan);
973  if (chan2) {
974  ast_autoservice_stop(chan2);
975  ast_senddigit_mf_end(chan2);
976  }
977  if (res) {
978  break;
979  }
980  } else if (strchr("0123456789*#ABCwWfF", *ptr)) {
981  if (*ptr == 'f' || *ptr == 'F') {
982  /* ignore return values if not supported by channel */
984  } else if (*ptr == 'W') {
985  /* ignore return values if not supported by channel */
987  } else {
988  /* Character represents valid MF */
989  ast_senddigit_mf(chan, *ptr, duration, durationkp, durationst, is_external);
990  if (chan2) {
991  ast_senddigit_mf(chan2, *ptr, duration, durationkp, durationst, is_external);
992  }
993  }
994  /* pause between digits */
995  /* The DSP code in Asterisk does not currently properly receive repeated tones
996  if no audio is sent in the middle. Simply sending audio (even 0 Hz)
997  works around this limitation and guarantees the correct behavior.
998  */
999  ast_playtones_start(chan, 0, "0", 0);
1000  if (chan2) {
1001  ast_playtones_start(chan2, 0, "0", 0);
1002  ast_autoservice_start(chan2);
1003  }
1004  res = my_sleep(chan, between);
1005  ast_senddigit_mf_end(chan);
1006  if (chan2) {
1007  ast_autoservice_stop(chan2);
1008  ast_senddigit_mf_end(chan2);
1009  }
1010  if (res) {
1011  break;
1012  }
1013  } else {
1014  ast_log(LOG_WARNING, "Illegal MF character '%c' in string. (0-9*#ABCwWfFhH allowed)\n", *ptr);
1015  }
1016  }
1017 
1018 mf_stream_cleanup:
1019  if (silgen) {
1020  ast_channel_stop_silence_generator(chan, silgen);
1021  }
1022  if (silgen2) {
1023  ast_channel_stop_silence_generator(chan2, silgen2);
1024  }
1025 
1026  return res;
1027 }
1028 
1029 static int dtmf_stream(struct ast_channel *chan, const char *digits, int between, unsigned int duration, int is_external)
1030 {
1031  const char *ptr;
1032  int res;
1033  struct ast_silence_generator *silgen = NULL;
1034  int (*my_sleep)(struct ast_channel *chan, int ms);
1035  int (*my_senddigit)(struct ast_channel *chan, char digit, unsigned int duration);
1036 
1037  if (is_external) {
1038  my_sleep = external_sleep;
1039  my_senddigit = ast_senddigit_external;
1040  } else {
1041  my_sleep = ast_safe_sleep;
1042  my_senddigit = ast_senddigit;
1043  }
1044 
1045  if (!between) {
1046  between = 100;
1047  }
1048 
1049  /* Need a quiet time before sending digits. */
1050  if (ast_opt_transmit_silence) {
1051  silgen = ast_channel_start_silence_generator(chan);
1052  }
1053  res = my_sleep(chan, 100);
1054  if (res) {
1055  goto dtmf_stream_cleanup;
1056  }
1057 
1058  for (ptr = digits; *ptr; ptr++) {
1059  if (*ptr == 'w') {
1060  /* 'w' -- wait half a second */
1061  res = my_sleep(chan, 500);
1062  if (res) {
1063  break;
1064  }
1065  } else if (*ptr == 'W') {
1066  /* 'W' -- wait a second */
1067  res = my_sleep(chan, 1000);
1068  if (res) {
1069  break;
1070  }
1071  } else if (strchr("0123456789*#abcdfABCDF", *ptr)) {
1072  if (*ptr == 'f' || *ptr == 'F') {
1073  /* ignore return values if not supported by channel */
1075  } else {
1076  /* Character represents valid DTMF */
1077  my_senddigit(chan, *ptr, duration);
1078  }
1079  /* pause between digits */
1080  res = my_sleep(chan, between);
1081  if (res) {
1082  break;
1083  }
1084  } else {
1085  ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n", *ptr);
1086  }
1087  }
1088 
1089 dtmf_stream_cleanup:
1090  if (silgen) {
1091  ast_channel_stop_silence_generator(chan, silgen);
1092  }
1093 
1094  return res;
1095 }
1096 
1097 int ast_sf_stream(struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *chan2, const char *digits, int frequency, int is_external)
1098 {
1099  int res;
1100  if (frequency <= 0) {
1101  frequency = 2600;
1102  }
1103  if (!is_external && !chan2 && peer && ast_autoservice_start(peer)) {
1104  return -1;
1105  }
1106  res = sf_stream(chan, chan2, digits, frequency, is_external);
1107  if (!is_external && !chan2 && peer && ast_autoservice_stop(peer)) {
1108  res = -1;
1109  }
1110  return res;
1111 }
1112 
1113 int ast_mf_stream(struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *chan2, const char *digits,
1114  int between, unsigned int duration, unsigned int durationkp, unsigned int durationst, int is_external)
1115 {
1116  int res;
1117  if (!is_external && !chan2 && peer && ast_autoservice_start(peer)) {
1118  return -1;
1119  }
1120  res = mf_stream(chan, chan2, digits, between, duration, durationkp, durationst, is_external);
1121  if (!is_external && !chan2 && peer && ast_autoservice_stop(peer)) {
1122  res = -1;
1123  }
1124  return res;
1125 }
1126 
1127 int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration)
1128 {
1129  int res;
1130 
1131  if (peer && ast_autoservice_start(peer)) {
1132  return -1;
1133  }
1134  res = dtmf_stream(chan, digits, between, duration, 0);
1135  if (peer && ast_autoservice_stop(peer)) {
1136  res = -1;
1137  }
1138 
1139  return res;
1140 }
1141 
1142 void ast_dtmf_stream_external(struct ast_channel *chan, const char *digits, int between, unsigned int duration)
1143 {
1144  dtmf_stream(chan, digits, between, duration, 1);
1145 }
1146 
1148  int fd;
1149  int autoclose;
1150  int allowoverride;
1151  struct ast_format *origwfmt;
1152 };
1153 
1154 static void linear_release(struct ast_channel *chan, void *params)
1155 {
1156  struct linear_state *ls = params;
1157 
1158  if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) {
1159  ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%s'\n",
1160  ast_channel_name(chan), ast_format_get_name(ls->origwfmt));
1161  }
1162  ao2_cleanup(ls->origwfmt);
1163 
1164  if (ls->autoclose) {
1165  close(ls->fd);
1166  }
1167 
1168  ast_free(params);
1169 }
1170 
1171 static int linear_generator(struct ast_channel *chan, void *data, int len, int samples)
1172 {
1173  short buf[2048 + AST_FRIENDLY_OFFSET / 2];
1174  struct linear_state *ls = data;
1175  struct ast_frame f = {
1177  .data.ptr = buf + AST_FRIENDLY_OFFSET / 2,
1178  .offset = AST_FRIENDLY_OFFSET,
1179  };
1180  int res;
1181 
1183 
1184  len = samples * 2;
1185  if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
1186  ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" , len);
1187  len = sizeof(buf) - AST_FRIENDLY_OFFSET;
1188  }
1189  res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len);
1190  if (res > 0) {
1191  f.datalen = res;
1192  f.samples = res / 2;
1193  ast_write(chan, &f);
1194  if (res == len) {
1195  return 0;
1196  }
1197  }
1198  return -1;
1199 }
1200 
1201 static void *linear_alloc(struct ast_channel *chan, void *params)
1202 {
1203  struct linear_state *ls = params;
1204 
1205  if (!params) {
1206  return NULL;
1207  }
1208 
1209  /* In this case, params is already malloc'd */
1210  if (ls->allowoverride) {
1211  ast_set_flag(ast_channel_flags(chan), AST_FLAG_WRITE_INT);
1212  } else {
1213  ast_clear_flag(ast_channel_flags(chan), AST_FLAG_WRITE_INT);
1214  }
1215 
1216  ls->origwfmt = ao2_bump(ast_channel_writeformat(chan));
1217 
1219  ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", ast_channel_name(chan));
1220  ao2_cleanup(ls->origwfmt);
1221  ast_free(ls);
1222  ls = params = NULL;
1223  }
1224 
1225  return params;
1226 }
1227 
1228 static struct ast_generator linearstream =
1229 {
1230  .alloc = linear_alloc,
1231  .release = linear_release,
1232  .generate = linear_generator,
1233 };
1234 
1235 int ast_linear_stream(struct ast_channel *chan, const char *filename, int fd, int allowoverride)
1236 {
1237  struct linear_state *lin;
1238  char tmpf[256];
1239  int autoclose = 0;
1240 
1241  if (fd < 0) {
1242  if (ast_strlen_zero(filename)) {
1243  return -1;
1244  }
1245 
1246  autoclose = 1;
1247 
1248  if (filename[0] == '/') {
1249  ast_copy_string(tmpf, filename, sizeof(tmpf));
1250  } else {
1251  snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", ast_config_AST_DATA_DIR, "sounds", filename);
1252  }
1253 
1254  fd = open(tmpf, O_RDONLY);
1255  if (fd < 0) {
1256  ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno));
1257  return -1;
1258  }
1259  }
1260 
1261  lin = ast_calloc(1, sizeof(*lin));
1262  if (!lin) {
1263  if (autoclose) {
1264  close(fd);
1265  }
1266 
1267  return -1;
1268  }
1269 
1270  lin->fd = fd;
1271  lin->allowoverride = allowoverride;
1272  lin->autoclose = autoclose;
1273 
1274  return ast_activate_generator(chan, &linearstream, lin);
1275 }
1276 
1277 static int control_streamfile(struct ast_channel *chan,
1278  const char *file,
1279  const char *fwd,
1280  const char *rev,
1281  const char *stop,
1282  const char *suspend,
1283  const char *restart,
1284  int skipms,
1285  long *offsetms,
1286  const char *lang,
1288 {
1289  char *breaks = NULL;
1290  char *end = NULL;
1291  int blen = 2;
1292  int res;
1293  long pause_restart_point = 0;
1294  long offset = 0;
1295  struct ast_silence_generator *silgen = NULL;
1296 
1297  if (!file) {
1298  return -1;
1299  }
1300  if (offsetms) {
1301  offset = *offsetms * 8; /* XXX Assumes 8kHz */
1302  }
1303  if (lang == NULL) {
1304  lang = ast_channel_language(chan);
1305  }
1306 
1307  if (stop) {
1308  blen += strlen(stop);
1309  }
1310  if (suspend) {
1311  blen += strlen(suspend);
1312  }
1313  if (restart) {
1314  blen += strlen(restart);
1315  }
1316 
1317  if (blen > 2) {
1318  breaks = ast_alloca(blen + 1);
1319  breaks[0] = '\0';
1320  if (stop) {
1321  strcat(breaks, stop);
1322  }
1323  if (suspend) {
1324  strcat(breaks, suspend);
1325  }
1326  if (restart) {
1327  strcat(breaks, restart);
1328  }
1329  }
1330 
1331  if ((end = strchr(file, ':'))) {
1332  if (!strcasecmp(end, ":end")) {
1333  *end = '\0';
1334  end++;
1335  } else {
1336  end = NULL;
1337  }
1338  }
1339 
1340  for (;;) {
1341  ast_stopstream(chan);
1342  res = ast_streamfile(chan, file, lang);
1343  if (!res) {
1344  if (pause_restart_point) {
1345  ast_seekstream(ast_channel_stream(chan), pause_restart_point, SEEK_SET);
1346  pause_restart_point = 0;
1347  }
1348  else if (end || offset < 0) {
1349  if (offset == -8) {
1350  offset = 0;
1351  }
1352  ast_verb(3, "ControlPlayback seek to offset %ld from end\n", offset);
1353 
1354  ast_seekstream(ast_channel_stream(chan), offset, SEEK_END);
1355  end = NULL;
1356  offset = 0;
1357  } else if (offset) {
1358  ast_verb(3, "ControlPlayback seek to offset %ld\n", offset);
1359  ast_seekstream(ast_channel_stream(chan), offset, SEEK_SET);
1360  offset = 0;
1361  }
1362  if (cb) {
1363  res = ast_waitstream_fr_w_cb(chan, breaks, fwd, rev, skipms, cb);
1364  } else {
1365  res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
1366  }
1367  }
1368 
1369  if (res < 1) {
1370  break;
1371  }
1372 
1373  /* We go at next loop if we got the restart char */
1374  if ((restart && strchr(restart, res)) || res == AST_CONTROL_STREAM_RESTART) {
1375  ast_debug(1, "we'll restart the stream here at next loop\n");
1376  pause_restart_point = 0;
1377  ast_test_suite_event_notify("PLAYBACK","Channel: %s\r\n"
1378  "Control: %s\r\n",
1379  ast_channel_name(chan),
1380  "Restart");
1381  continue;
1382  }
1383 
1384  if ((suspend && strchr(suspend, res)) || res == AST_CONTROL_STREAM_SUSPEND) {
1385  pause_restart_point = ast_tellstream(ast_channel_stream(chan));
1386 
1387  if (ast_opt_transmit_silence) {
1388  silgen = ast_channel_start_silence_generator(chan);
1389  }
1390  ast_test_suite_event_notify("PLAYBACK","Channel: %s\r\n"
1391  "Control: %s\r\n",
1392  ast_channel_name(chan),
1393  "Pause");
1394  for (;;) {
1395  ast_stopstream(chan);
1396  if (!(res = ast_waitfordigit(chan, 1000))) {
1397  continue;
1398  } else if (res == -1 || (suspend && strchr(suspend, res)) || (stop && strchr(stop, res))
1400  break;
1401  }
1402  }
1403  if (silgen) {
1404  ast_channel_stop_silence_generator(chan, silgen);
1405  silgen = NULL;
1406  }
1407 
1408  if ((suspend && (res == *suspend)) || res == AST_CONTROL_STREAM_SUSPEND) {
1409  res = 0;
1410  ast_test_suite_event_notify("PLAYBACK","Channel: %s\r\n"
1411  "Control: %s\r\n",
1412  ast_channel_name(chan),
1413  "Unpause");
1414  continue;
1415  }
1416  }
1417 
1418  if (res == -1) {
1419  break;
1420  }
1421 
1422  /* if we get one of our stop chars, return it to the calling function */
1423  if ((stop && strchr(stop, res)) || res == AST_CONTROL_STREAM_STOP) {
1424  ast_test_suite_event_notify("PLAYBACK","Channel: %s\r\n"
1425  "Control: %s\r\n",
1426  ast_channel_name(chan),
1427  "Stop");
1428  break;
1429  }
1430  }
1431 
1432  if (pause_restart_point) {
1433  offset = pause_restart_point;
1434  } else {
1435  if (ast_channel_stream(chan)) {
1436  offset = ast_tellstream(ast_channel_stream(chan));
1437  } else {
1438  offset = -8; /* indicate end of file */
1439  }
1440  }
1441 
1442  if (offsetms) {
1443  *offsetms = offset / 8; /* samples --> ms ... XXX Assumes 8 kHz */
1444  }
1445 
1446  ast_stopstream(chan);
1447 
1448  return res;
1449 }
1450 
1452  const char *file,
1453  const char *fwd,
1454  const char *rev,
1455  const char *stop,
1456  const char *suspend,
1457  const char *restart,
1458  int skipms,
1459  long *offsetms,
1461 {
1462  return control_streamfile(chan, file, fwd, rev, stop, suspend, restart, skipms, offsetms, NULL, cb);
1463 }
1464 
1465 int ast_control_streamfile(struct ast_channel *chan, const char *file,
1466  const char *fwd, const char *rev,
1467  const char *stop, const char *suspend,
1468  const char *restart, int skipms, long *offsetms)
1469 {
1470  return control_streamfile(chan, file, fwd, rev, stop, suspend, restart, skipms, offsetms, NULL, NULL);
1471 }
1472 
1473 int ast_control_streamfile_lang(struct ast_channel *chan, const char *file,
1474  const char *fwd, const char *rev, const char *stop, const char *suspend,
1475  const char *restart, int skipms, const char *lang, long *offsetms)
1476 {
1477  return control_streamfile(chan, file, fwd, rev, stop, suspend, restart, skipms, offsetms, lang, NULL);
1478 }
1479 
1480 enum control_tone_frame_response_result {
1481  CONTROL_TONE_RESPONSE_FAILED = -1,
1482  CONTROL_TONE_RESPONSE_NORMAL = 0,
1483  CONTROL_TONE_RESPONSE_FINISHED = 1,
1484 };
1485 
1486 static enum control_tone_frame_response_result control_tone_frame_response(struct ast_channel *chan, struct ast_frame *fr, struct ast_tone_zone_sound *ts, const char *tone, int *paused)
1487 {
1488  switch (fr->subclass.integer) {
1490  ast_playtones_stop(chan);
1491  return CONTROL_TONE_RESPONSE_FINISHED;
1493  if (*paused) {
1494  *paused = 0;
1495  if (ast_playtones_start(chan, 0, ts ? ts->data : tone, 0)) {
1496  return CONTROL_TONE_RESPONSE_FAILED;
1497  }
1498  } else {
1499  *paused = 1;
1500  ast_playtones_stop(chan);
1501  }
1502  return CONTROL_TONE_RESPONSE_NORMAL;
1504  ast_playtones_stop(chan);
1505  if (ast_playtones_start(chan, 0, ts ? ts->data : tone, 0)) {
1506  return CONTROL_TONE_RESPONSE_FAILED;
1507  }
1508  return CONTROL_TONE_RESPONSE_NORMAL;
1510  ast_log(LOG_NOTICE, "Media control operation 'reverse' not supported for media type 'tone'\n");
1511  return CONTROL_TONE_RESPONSE_NORMAL;
1513  ast_log(LOG_NOTICE, "Media control operation 'forward' not supported for media type 'tone'\n");
1514  return CONTROL_TONE_RESPONSE_NORMAL;
1515  case AST_CONTROL_HANGUP:
1516  case AST_CONTROL_BUSY:
1518  return CONTROL_TONE_RESPONSE_FINISHED;
1519  }
1520 
1521  return CONTROL_TONE_RESPONSE_NORMAL;
1522 }
1523 
1524 static int parse_tone_uri(char *tone_parser,
1525  const char **tone_indication,
1526  const char **tone_zone)
1527 {
1528  *tone_indication = strsep(&tone_parser, ";");
1529 
1530  if (ast_strlen_zero(tone_parser)) {
1531  /* Only the indication is included */
1532  return 0;
1533  }
1534 
1535  if (!(strncmp(tone_parser, "tonezone=", 9))) {
1536  *tone_zone = tone_parser + 9;
1537  } else {
1538  ast_log(LOG_ERROR, "Unexpected Tone URI component: %s\n", tone_parser);
1539  return -1;
1540  }
1541 
1542  return 0;
1543 }
1544 
1545 int ast_control_tone(struct ast_channel *chan, const char *tone)
1546 {
1547  struct ast_tone_zone *zone = NULL;
1548  struct ast_tone_zone_sound *ts;
1549  int paused = 0;
1550  int res = 0;
1551 
1552  const char *tone_indication = NULL;
1553  const char *tone_zone = NULL;
1554  char *tone_uri_parser;
1555 
1556  if (ast_strlen_zero(tone)) {
1557  return -1;
1558  }
1559 
1560  tone_uri_parser = ast_strdupa(tone);
1561 
1562  if (parse_tone_uri(tone_uri_parser, &tone_indication, &tone_zone)) {
1563  return -1;
1564  }
1565 
1566  if (tone_zone) {
1567  zone = ast_get_indication_zone(tone_zone);
1568  }
1569 
1570  ts = ast_get_indication_tone(zone ? zone : ast_channel_zone(chan), tone_indication);
1571 
1572  if (ast_playtones_start(chan, 0, ts ? ts->data : tone_indication, 0)) {
1573  res = -1;
1574  }
1575 
1576  while (!res) {
1577  struct ast_frame *fr;
1578 
1579  if (ast_waitfor(chan, -1) < 0) {
1580  res = -1;
1581  break;
1582  }
1583 
1584  fr = ast_read_noaudio(chan);
1585 
1586  if (!fr) {
1587  res = -1;
1588  break;
1589  }
1590 
1591  if (fr->frametype != AST_FRAME_CONTROL) {
1592  continue;
1593  }
1594 
1595  res = control_tone_frame_response(chan, fr, ts, tone_indication, &paused);
1596  if (res == CONTROL_TONE_RESPONSE_FINISHED) {
1597  res = 0;
1598  break;
1599  } else if (res == CONTROL_TONE_RESPONSE_FAILED) {
1600  res = -1;
1601  break;
1602  }
1603  }
1604 
1605  if (ts) {
1607  }
1608 
1609  if (zone) {
1610  ast_tone_zone_unref(zone);
1611  }
1612 
1613  return res;
1614 }
1615 
1616 int ast_play_and_wait(struct ast_channel *chan, const char *fn)
1617 {
1618  int d = 0;
1619 
1620  if ((d = ast_streamfile(chan, fn, ast_channel_language(chan)))) {
1621  return d;
1622  }
1623 
1624  d = ast_waitstream(chan, AST_DIGIT_ANY);
1625 
1626  ast_stopstream(chan);
1627 
1628  return d;
1629 }
1630 
1631 /*!
1632  * \brief Construct a silence frame of the same duration as \a orig.
1633  *
1634  * The \a orig frame must be \ref ast_format_slin.
1635  *
1636  * \param orig Frame as basis for silence to generate.
1637  * \return New frame of silence; free with ast_frfree().
1638  * \retval NULL on error.
1639  */
1640 static struct ast_frame *make_silence(const struct ast_frame *orig)
1641 {
1642  struct ast_frame *silence;
1643  size_t size;
1644  size_t datalen;
1645  size_t samples = 0;
1646 
1647  if (!orig) {
1648  return NULL;
1649  }
1650  do {
1652  ast_log(LOG_WARNING, "Attempting to silence non-slin frame\n");
1653  return NULL;
1654  }
1655 
1656  samples += orig->samples;
1657 
1658  orig = AST_LIST_NEXT(orig, frame_list);
1659  } while (orig);
1660 
1661  ast_verb(4, "Silencing %zu samples\n", samples);
1662 
1663 
1664  datalen = sizeof(short) * samples;
1665  size = sizeof(*silence) + datalen;
1666  silence = ast_calloc(1, size);
1667  if (!silence) {
1668  return NULL;
1669  }
1670 
1671  silence->mallocd = AST_MALLOCD_HDR;
1672  silence->frametype = AST_FRAME_VOICE;
1673  silence->data.ptr = (void *)(silence + 1);
1674  silence->samples = samples;
1675  silence->datalen = datalen;
1676 
1678 
1679  return silence;
1680 }
1681 
1682 /*!
1683  * \brief Sets a channel's read format to \ref ast_format_slin, recording
1684  * its original format.
1685  *
1686  * \param chan Channel to modify.
1687  * \param[out] orig_format Output variable to store channel's original read
1688  * format.
1689  * \return 0 on success.
1690  * \return -1 on error.
1691  */
1692 static int set_read_to_slin(struct ast_channel *chan, struct ast_format **orig_format)
1693 {
1694  if (!chan || !orig_format) {
1695  return -1;
1696  }
1697  *orig_format = ao2_bump(ast_channel_readformat(chan));
1698  return ast_set_read_format(chan, ast_format_slin);
1699 }
1700 
1701 static int global_silence_threshold = 128;
1702 static int global_maxsilence = 0;
1703 
1704 /*! Optionally play a sound file or a beep, then record audio and video from the channel.
1705  * \param chan Channel to playback to/record from.
1706  * \param playfile Filename of sound to play before recording begins.
1707  * \param recordfile Filename to record to.
1708  * \param maxtime Maximum length of recording (in seconds).
1709  * \param fmt Format(s) to record message in. Multiple formats may be specified by separating them with a '|'.
1710  * \param duration Where to store actual length of the recorded message (in milliseconds).
1711  * \param sound_duration Where to store the length of the recorded message (in milliseconds), minus any silence
1712  * \param beep Whether to play a beep before starting to record.
1713  * \param silencethreshold
1714  * \param maxsilence Length of silence that will end a recording (in milliseconds).
1715  * \param path Optional filesystem path to unlock.
1716  * \param prepend If true, prepend the recorded audio to an existing file and follow prepend mode recording rules
1717  * \param acceptdtmf DTMF digits that will end the recording.
1718  * \param canceldtmf DTMF digits that will cancel the recording.
1719  * \param skip_confirmation_sound If true, don't play auth-thankyou at end. Nice for custom recording prompts in apps.
1720  * \param if_exists
1721  *
1722  * \retval -1 failure or hangup
1723  * \retval 'S' Recording ended from silence timeout
1724  * \retval 't' Recording ended from the message exceeding the maximum duration, or via DTMF in prepend mode
1725  * \retval dtmfchar Recording ended via the return value's DTMF character for either cancel or accept.
1726  */
1727 static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
1728  const char *recordfile, int maxtime, const char *fmt, int *duration,
1729  int *sound_duration, int beep, int silencethreshold, int maxsilence,
1730  const char *path, int prepend, const char *acceptdtmf, const char *canceldtmf,
1731  int skip_confirmation_sound, enum ast_record_if_exists if_exists)
1732 {
1733  int d = 0;
1734  char *fmts;
1735  char comment[256];
1736  int x, fmtcnt = 1, res = -1, outmsg = 0;
1737  struct ast_filestream *others[AST_MAX_FORMATS];
1738  const char *sfmt[AST_MAX_FORMATS];
1739  char *stringp = NULL;
1740  time_t start, end;
1741  struct ast_dsp *sildet = NULL; /* silence detector dsp */
1742  int totalsilence = 0;
1743  int dspsilence = 0;
1744  int olddspsilence = 0;
1745  struct ast_format *rfmt = NULL;
1746  struct ast_silence_generator *silgen = NULL;
1747  char prependfile[PATH_MAX];
1748  int ioflags; /* IO flags for writing output file */
1749  SCOPE_ENTER(3, "%s: play: '%s' record: '%s' path: '%s' prepend: %d\n",
1750  ast_channel_name(chan), playfile, recordfile, path, prepend);
1751 
1752  ioflags = O_CREAT|O_WRONLY;
1753 
1754  switch (if_exists) {
1756  ioflags |= O_EXCL;
1757  break;
1759  ioflags |= O_TRUNC;
1760  break;
1762  ioflags |= O_APPEND;
1763  break;
1765  ast_assert(0);
1766  break;
1767  }
1768 
1769  if (silencethreshold < 0) {
1770  silencethreshold = global_silence_threshold;
1771  }
1772 
1773  if (maxsilence < 0) {
1774  maxsilence = global_maxsilence;
1775  }
1776 
1777  /* barf if no pointer passed to store duration in */
1778  if (!duration) {
1779  ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n");
1780  return -1;
1781  }
1782 
1783  ast_debug(1, "play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
1784  snprintf(comment, sizeof(comment), "Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, ast_channel_name(chan));
1785 
1786  if (playfile || beep) {
1787  if (!beep) {
1788  ast_trace(-1, "Playing '%s' to '%s'\n", playfile, ast_channel_name(chan));
1789  d = ast_play_and_wait(chan, playfile);
1790  }
1791  if (d > -1) {
1792  ast_trace(-1, "Playing 'beep' to '%s'\n", ast_channel_name(chan));
1793  d = ast_stream_and_wait(chan, "beep", "");
1794  }
1795  if (d < 0) {
1796  SCOPE_EXIT_RTN_VALUE(-1, "Failed to play. RC: %d\n", d);
1797  }
1798  }
1799 
1800  if (prepend) {
1801  ast_copy_string(prependfile, recordfile, sizeof(prependfile));
1802  strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
1803  ast_trace(-1, "Prepending to '%s'\n", prependfile);
1804  }
1805 
1806  fmts = ast_strdupa(fmt);
1807 
1808  stringp = fmts;
1809  strsep(&stringp, "|");
1810  ast_debug(1, "Recording Formats: sfmts=%s\n", fmts);
1811  sfmt[0] = ast_strdupa(fmts);
1812 
1813  while ((fmt = strsep(&stringp, "|"))) {
1814  if (fmtcnt > AST_MAX_FORMATS - 1) {
1815  ast_log(LOG_WARNING, "Please increase AST_MAX_FORMATS in file.h\n");
1816  break;
1817  }
1818  /*
1819  * Storage for 'fmt' is on the stack and held by 'fmts', which is maintained for
1820  * the rest of this function. So okay to not duplicate 'fmt' here, but only keep
1821  * a pointer to it.
1822  */
1823  sfmt[fmtcnt++] = fmt;
1824  }
1825 
1826  end = start = time(NULL); /* pre-initialize end to be same as start in case we never get into loop */
1827  for (x = 0; x < fmtcnt; x++) {
1828  others[x] = ast_writefile(prepend ? prependfile : recordfile, sfmt[x], comment, ioflags, 0, AST_FILE_MODE);
1829  ast_trace(-1, "x=%d, open writing: %s format: %s, %p\n", x, prepend ? prependfile : recordfile, sfmt[x], others[x]);
1830 
1831  if (!others[x]) {
1832  break;
1833  }
1834  }
1835 
1836  if (path) {
1837  ast_unlock_path(path);
1838  }
1839 
1840  if (maxsilence > 0) {
1841  sildet = ast_dsp_new(); /* Create the silence detector */
1842  if (!sildet) {
1843  ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
1844  return -1;
1845  }
1846  ast_dsp_set_threshold(sildet, silencethreshold);
1847  res = set_read_to_slin(chan, &rfmt);
1848  if (res < 0) {
1849  ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
1850  ast_dsp_free(sildet);
1851  ao2_cleanup(rfmt);
1852  return -1;
1853  }
1854  }
1855 
1856  if (!prepend) {
1857  /* Request a video update */
1859 
1860  if (ast_opt_transmit_silence) {
1861  silgen = ast_channel_start_silence_generator(chan);
1862  }
1863  }
1864 
1865  if (x == fmtcnt) {
1866  /* Loop, writing the packets we read to the writer(s), until
1867  * we have reason to stop. */
1868  struct ast_frame *f;
1869  int paused = 0;
1870  int muted = 0;
1871  time_t pause_start = 0;
1872  int paused_secs = 0;
1873  int pausedsilence = 0;
1874 
1875  for (;;) {
1876  if (!(res = ast_waitfor(chan, 2000))) {
1877  ast_debug(1, "One waitfor failed, trying another\n");
1878  /* Try one more time in case of masq */
1879  if (!(res = ast_waitfor(chan, 2000))) {
1880  ast_log(LOG_WARNING, "No audio available on %s??\n", ast_channel_name(chan));
1881  res = -1;
1882  }
1883  }
1884 
1885  if (res < 0) {
1886  f = NULL;
1887  break;
1888  }
1889  if (!(f = ast_read(chan))) {
1890  break;
1891  }
1892  if (f->frametype == AST_FRAME_VOICE) {
1893  /* write each format */
1894  if (paused) {
1895  /* It's all good */
1896  res = 0;
1897  } else {
1898  struct ast_frame *silence = NULL;
1899  struct ast_frame *orig = f;
1900 
1901  if (muted) {
1902  silence = make_silence(orig);
1903  if (!silence) {
1904  ast_log(LOG_WARNING, "Error creating silence\n");
1905  break;
1906  }
1907  f = silence;
1908  }
1909  for (x = 0; x < fmtcnt; x++) {
1910  if (prepend && !others[x]) {
1911  break;
1912  }
1913  res = ast_writestream(others[x], f);
1914  }
1915  ast_frame_dtor(silence);
1916  f = orig;
1917  }
1918 
1919  /* Silence Detection */
1920  if (maxsilence > 0) {
1921  dspsilence = 0;
1922  ast_dsp_silence(sildet, f, &dspsilence);
1923  if (olddspsilence > dspsilence) {
1924  totalsilence += olddspsilence;
1925  }
1926  olddspsilence = dspsilence;
1927 
1928  if (paused) {
1929  /* record how much silence there was while we are paused */
1930  pausedsilence = dspsilence;
1931  } else if (dspsilence > pausedsilence) {
1932  /* ignore the paused silence */
1933  dspsilence -= pausedsilence;
1934  } else {
1935  /* dspsilence has reset, reset pausedsilence */
1936  pausedsilence = 0;
1937  }
1938 
1939  if (dspsilence > maxsilence) {
1940  /* Ended happily with silence */
1941  ast_verb(3, "Recording automatically stopped after a silence of %d seconds\n", dspsilence/1000);
1942  res = 'S';
1943  outmsg = 2;
1944  break;
1945  }
1946  }
1947  /* Exit on any error */
1948  if (res) {
1949  ast_log(LOG_WARNING, "Error writing frame\n");
1950  break;
1951  }
1952  } else if (f->frametype == AST_FRAME_VIDEO) {
1953  /* Write only once */
1954  ast_writestream(others[0], f);
1955  } else if (f->frametype == AST_FRAME_DTMF) {
1956  if (prepend) {
1957  /* stop recording with any digit */
1958  ast_verb(3, "User ended message by pressing %c\n", f->subclass.integer);
1959  res = 't';
1960  outmsg = 2;
1961  break;
1962  }
1963  if (strchr(acceptdtmf, f->subclass.integer)) {
1964  ast_verb(3, "User ended message by pressing %c\n", f->subclass.integer);
1965  res = f->subclass.integer;
1966  outmsg = 2;
1967  break;
1968  }
1969  if (strchr(canceldtmf, f->subclass.integer)) {
1970  ast_verb(3, "User canceled message by pressing %c\n", f->subclass.integer);
1971  res = f->subclass.integer;
1972  outmsg = 0;
1973  break;
1974  }
1975  } else if (f->frametype == AST_FRAME_CONTROL) {
1977  ast_verb(3, "Message canceled by control\n");
1978  outmsg = 0; /* cancels the recording */
1979  res = 0;
1980  break;
1981  } else if (f->subclass.integer == AST_CONTROL_RECORD_STOP) {
1982  ast_verb(3, "Message ended by control\n");
1983  res = 0;
1984  break;
1985  } else if (f->subclass.integer == AST_CONTROL_RECORD_SUSPEND) {
1986  paused = !paused;
1987  ast_verb(3, "Message %spaused by control\n",
1988  paused ? "" : "un");
1989  if (paused) {
1990  pause_start = time(NULL);
1991  } else {
1992  paused_secs += time(NULL) - pause_start;
1993  }
1994  } else if (f->subclass.integer == AST_CONTROL_RECORD_MUTE) {
1995  muted = !muted;
1996  ast_verb(3, "Message %smuted by control\n",
1997  muted ? "" : "un");
1998  /* We can only silence slin frames, so
1999  * set the mode, if we haven't already
2000  * for sildet
2001  */
2002  if (muted && !rfmt) {
2003  ast_verb(3, "Setting read format to linear mode\n");
2004  res = set_read_to_slin(chan, &rfmt);
2005  if (res < 0) {
2006  ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
2007  break;
2008  }
2009  }
2010  }
2011  }
2012  if (maxtime && !paused) {
2013  end = time(NULL);
2014  if (maxtime < (end - start - paused_secs)) {
2015  ast_verb(3, "Took too long, cutting it short...\n");
2016  res = 't';
2017  outmsg = 2;
2018  break;
2019  }
2020  }
2021  ast_frfree(f);
2022  }
2023  if (!f) {
2024  ast_verb(3, "User hung up\n");
2025  res = -1;
2026  outmsg = 1;
2027  } else {
2028  ast_frfree(f);
2029  }
2030  } else {
2031  ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]);
2032  }
2033 
2034  if (!prepend) {
2035  if (silgen) {
2036  ast_channel_stop_silence_generator(chan, silgen);
2037  }
2038  }
2039 
2040  /*!\note
2041  * Instead of asking how much time passed (end - start), calculate the number
2042  * of seconds of audio which actually went into the file. This fixes a
2043  * problem where audio is stopped up on the network and never gets to us.
2044  *
2045  * Note that we still want to use the number of seconds passed for the max
2046  * message, otherwise we could get a situation where this stream is never
2047  * closed (which would create a resource leak).
2048  */
2049  *duration = others[0] ? ast_tellstream(others[0]) / 8000 : 0;
2050  if (sound_duration) {
2051  *sound_duration = *duration;
2052  }
2053 
2054  if (!prepend) {
2055  /* Reduce duration by a total silence amount */
2056  if (olddspsilence <= dspsilence) {
2057  totalsilence += dspsilence;
2058  }
2059 
2060  if (sound_duration) {
2061  if (totalsilence > 0) {
2062  *sound_duration -= (totalsilence - 200) / 1000;
2063  }
2064  if (*sound_duration < 0) {
2065  *sound_duration = 0;
2066  }
2067  }
2068 
2069  if (dspsilence > 0) {
2070  *duration -= (dspsilence - 200) / 1000;
2071  }
2072 
2073  if (*duration < 0) {
2074  *duration = 0;
2075  }
2076 
2077  for (x = 0; x < fmtcnt; x++) {
2078  if (!others[x]) {
2079  break;
2080  }
2081  /*!\note
2082  * If we ended with silence, trim all but the first 200ms of silence
2083  * off the recording. However, if we ended with '#', we don't want
2084  * to trim ANY part of the recording.
2085  */
2086  if (res > 0 && dspsilence) {
2087  /* rewind only the trailing silence */
2088  ast_stream_rewind(others[x], dspsilence - 200);
2089  }
2090  ast_truncstream(others[x]);
2091  ast_closestream(others[x]);
2092  }
2093  } else if (prepend && outmsg) {
2094  struct ast_filestream *realfiles[AST_MAX_FORMATS];
2095  struct ast_frame *fr;
2096 
2097  for (x = 0; x < fmtcnt; x++) {
2098  snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]);
2099  realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0);
2100  if (!others[x]) {
2101  break;
2102  }
2103  if (!realfiles[x]) {
2104  ast_closestream(others[x]);
2105  continue;
2106  }
2107  /*!\note Same logic as above. */
2108  if (dspsilence) {
2109  ast_stream_rewind(others[x], dspsilence - 200);
2110  }
2111  ast_truncstream(others[x]);
2112  /* add the original file too */
2113  while ((fr = ast_readframe(realfiles[x]))) {
2114  ast_writestream(others[x], fr);
2115  ast_frfree(fr);
2116  }
2117  ast_closestream(others[x]);
2118  ast_closestream(realfiles[x]);
2119  ast_filerename(prependfile, recordfile, sfmt[x]);
2120  ast_trace(-1, "Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x], prependfile, recordfile);
2121  ast_trace(-1, "Deleting the prepend file %s.%s\n", recordfile, sfmt[x]);
2122  ast_filedelete(prependfile, sfmt[x]);
2123  }
2124  } else {
2125  for (x = 0; x < fmtcnt; x++) {
2126  if (!others[x]) {
2127  break;
2128  }
2129  ast_closestream(others[x]);
2130  }
2131  }
2132 
2133  if (rfmt && ast_set_read_format(chan, rfmt)) {
2134  ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_format_get_name(rfmt), ast_channel_name(chan));
2135  }
2136  ao2_cleanup(rfmt);
2137  if ((outmsg == 2) && (!skip_confirmation_sound)) {
2138  ast_stream_and_wait(chan, "auth-thankyou", "");
2139  }
2140  if (sildet) {
2141  ast_dsp_free(sildet);
2142  }
2143  SCOPE_EXIT_RTN_VALUE(res, "Done. RC: %d\n", res);
2144 }
2145 
2146 static const char default_acceptdtmf[] = "#";
2147 static const char default_canceldtmf[] = "";
2148 
2149 int ast_play_and_record_full(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence, const char *path, const char *acceptdtmf, const char *canceldtmf, int skip_confirmation_sound, enum ast_record_if_exists if_exists)
2150 {
2151  return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, beep, silencethreshold, maxsilence, path, 0, S_OR(acceptdtmf, ""), S_OR(canceldtmf, default_canceldtmf), skip_confirmation_sound, if_exists);
2152 }
2153 
2154 int ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int *sound_duration, int silencethreshold, int maxsilence, const char *path)
2155 {
2156  return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, 0, silencethreshold, maxsilence, path, 0, default_acceptdtmf, default_canceldtmf, 0, AST_RECORD_IF_EXISTS_OVERWRITE);
2157 }
2158 
2159 int ast_play_and_prepend(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence)
2160 {
2161  return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, beep, silencethreshold, maxsilence, NULL, 1, default_acceptdtmf, default_canceldtmf, 1, AST_RECORD_IF_EXISTS_OVERWRITE);
2162 }
2163 
2164 /* Channel group core functions */
2165 
2166 int ast_app_group_split_group(const char *data, char *group, int group_max, char *category, int category_max)
2167 {
2168  int res = 0;
2169  char tmp[256];
2170  char *grp = NULL, *cat = NULL;
2171 
2172  if (!ast_strlen_zero(data)) {
2173  ast_copy_string(tmp, data, sizeof(tmp));
2174  grp = tmp;
2175  if ((cat = strchr(tmp, '@'))) {
2176  *cat++ = '\0';
2177  }
2178  }
2179 
2180  if (!ast_strlen_zero(grp)) {
2181  ast_copy_string(group, grp, group_max);
2182  } else {
2183  *group = '\0';
2184  }
2185 
2186  if (!ast_strlen_zero(cat)) {
2187  ast_copy_string(category, cat, category_max);
2188  }
2189 
2190  return res;
2191 }
2192 
2193 int ast_app_group_set_channel(struct ast_channel *chan, const char *data)
2194 {
2195  int res = 0;
2196  char group[80] = "", category[80] = "";
2197  struct ast_group_info *gi = NULL;
2198  size_t len = 0;
2199 
2200  if (ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category))) {
2201  return -1;
2202  }
2203 
2204  /* Calculate memory we will need if this is new */
2205  len = sizeof(*gi) + strlen(group) + 1;
2206  if (!ast_strlen_zero(category)) {
2207  len += strlen(category) + 1;
2208  }
2209 
2211  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) {
2212  if ((gi->chan == chan) && ((ast_strlen_zero(category) && ast_strlen_zero(gi->category)) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) {
2213  AST_RWLIST_REMOVE_CURRENT(group_list);
2214  ast_free(gi);
2215  break;
2216  }
2217  }
2218  AST_RWLIST_TRAVERSE_SAFE_END;
2219 
2220  if (ast_strlen_zero(group)) {
2221  /* Enable unsetting the group */
2222  } else if ((gi = ast_calloc(1, len))) {
2223  gi->chan = chan;
2224  gi->group = (char *) gi + sizeof(*gi);
2225  strcpy(gi->group, group);
2226  if (!ast_strlen_zero(category)) {
2227  gi->category = (char *) gi + sizeof(*gi) + strlen(group) + 1;
2228  strcpy(gi->category, category);
2229  }
2230  AST_RWLIST_INSERT_TAIL(&groups, gi, group_list);
2231  } else {
2232  res = -1;
2233  }
2234 
2236 
2237  return res;
2238 }
2239 
2240 int ast_app_group_get_count(const char *group, const char *category)
2241 {
2242  struct ast_group_info *gi = NULL;
2243  int count = 0;
2244 
2245  if (ast_strlen_zero(group)) {
2246  return 0;
2247  }
2248 
2250  AST_RWLIST_TRAVERSE(&groups, gi, group_list) {
2251  if (!strcasecmp(gi->group, group) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) {
2252  count++;
2253  }
2254  }
2256 
2257  return count;
2258 }
2259 
2260 int ast_app_group_match_get_count(const char *groupmatch, const char *category)
2261 {
2262  struct ast_group_info *gi = NULL;
2263  regex_t regexbuf_group;
2264  regex_t regexbuf_category;
2265  int count = 0;
2266 
2267  if (ast_strlen_zero(groupmatch)) {
2268  ast_log(LOG_NOTICE, "groupmatch empty\n");
2269  return 0;
2270  }
2271 
2272  /* if regex compilation fails, return zero matches */
2273  if (regcomp(&regexbuf_group, groupmatch, REG_EXTENDED | REG_NOSUB)) {
2274  ast_log(LOG_ERROR, "Regex compile failed on: %s\n", groupmatch);
2275  return 0;
2276  }
2277 
2278  if (!ast_strlen_zero(category) && regcomp(&regexbuf_category, category, REG_EXTENDED | REG_NOSUB)) {
2279  ast_log(LOG_ERROR, "Regex compile failed on: %s\n", category);
2280  regfree(&regexbuf_group);
2281  return 0;
2282  }
2283 
2285  AST_RWLIST_TRAVERSE(&groups, gi, group_list) {
2286  if (!regexec(&regexbuf_group, gi->group, 0, NULL, 0) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !regexec(&regexbuf_category, gi->category, 0, NULL, 0)))) {
2287  count++;
2288  }
2289  }
2291 
2292  regfree(&regexbuf_group);
2293  if (!ast_strlen_zero(category)) {
2294  regfree(&regexbuf_category);
2295  }
2296 
2297  return count;
2298 }
2299 
2300 int ast_app_group_update(struct ast_channel *old, struct ast_channel *new)
2301 {
2302  struct ast_group_info *gi = NULL;
2303 
2305  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) {
2306  if (gi->chan == old) {
2307  gi->chan = new;
2308  } else if (gi->chan == new) {
2309  AST_RWLIST_REMOVE_CURRENT(group_list);
2310  ast_free(gi);
2311  }
2312  }
2313  AST_RWLIST_TRAVERSE_SAFE_END;
2315 
2316  return 0;
2317 }
2318 
2320 {
2321  struct ast_group_info *gi = NULL;
2322 
2324  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) {
2325  if (gi->chan == chan) {
2326  AST_RWLIST_REMOVE_CURRENT(group_list);
2327  ast_free(gi);
2328  }
2329  }
2330  AST_RWLIST_TRAVERSE_SAFE_END;
2332 
2333  return 0;
2334 }
2335 
2337 {
2338  return AST_RWLIST_WRLOCK(&groups);
2339 }
2340 
2342 {
2343  return AST_RWLIST_RDLOCK(&groups);
2344 }
2345 
2347 {
2348  return AST_RWLIST_FIRST(&groups);
2349 }
2350 
2352 {
2353  return AST_RWLIST_UNLOCK(&groups);
2354 }
2355 
2356 unsigned int __ast_app_separate_args(char *buf, char delim, int remove_chars, char **array, int arraylen)
2357 {
2358  int argc;
2359  char *scan, *wasdelim = NULL;
2360  int paren = 0, quote = 0, bracket = 0;
2361 
2362  if (!array || !arraylen) {
2363  return 0;
2364  }
2365 
2366  memset(array, 0, arraylen * sizeof(*array));
2367 
2368  if (!buf) {
2369  return 0;
2370  }
2371 
2372  scan = buf;
2373 
2374  for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
2375  array[argc] = scan;
2376  for (; *scan; scan++) {
2377  if (*scan == '(') {
2378  paren++;
2379  } else if (*scan == ')') {
2380  if (paren) {
2381  paren--;
2382  }
2383  } else if (*scan == '[') {
2384  bracket++;
2385  } else if (*scan == ']') {
2386  if (bracket) {
2387  bracket--;
2388  }
2389  } else if (*scan == '"' && delim != '"') {
2390  quote = quote ? 0 : 1;
2391  if (remove_chars) {
2392  /* Remove quote character from argument */
2393  memmove(scan, scan + 1, strlen(scan));
2394  scan--;
2395  }
2396  } else if (*scan == '\\') {
2397  if (remove_chars) {
2398  /* Literal character, don't parse */
2399  memmove(scan, scan + 1, strlen(scan));
2400  } else {
2401  scan++;
2402  }
2403  } else if ((*scan == delim) && !paren && !quote && !bracket) {
2404  wasdelim = scan;
2405  *scan++ = '\0';
2406  break;
2407  }
2408  }
2409  }
2410 
2411  /* If the last character in the original string was the delimiter, then
2412  * there is one additional argument. */
2413  if (*scan || (scan > buf && (scan - 1) == wasdelim)) {
2414  array[argc++] = scan;
2415  }
2416 
2417  return argc;
2418 }
2419 
2420 static enum AST_LOCK_RESULT ast_lock_path_lockfile(const char *path)
2421 {
2422  char *s;
2423  char *fs;
2424  int res;
2425  int fd;
2426  int lp = strlen(path);
2427  time_t start;
2428 
2429  s = ast_alloca(lp + 10);
2430  fs = ast_alloca(lp + 20);
2431 
2432  snprintf(fs, strlen(path) + 19, "%s/.lock-%08lx", path, (unsigned long)ast_random());
2433  fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, AST_FILE_MODE);
2434  if (fd < 0) {
2435  ast_log(LOG_ERROR, "Unable to create lock file '%s': %s\n", path, strerror(errno));
2436  return AST_LOCK_PATH_NOT_FOUND;
2437  }
2438  close(fd);
2439 
2440  snprintf(s, strlen(path) + 9, "%s/.lock", path);
2441  start = time(NULL);
2442  while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5)) {
2443  sched_yield();
2444  }
2445 
2446  unlink(fs);
2447 
2448  if (res) {
2449  ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
2450  return AST_LOCK_TIMEOUT;
2451  } else {
2452  ast_debug(1, "Locked path '%s'\n", path);
2453  return AST_LOCK_SUCCESS;
2454  }
2455 }
2456 
2457 static int ast_unlock_path_lockfile(const char *path)
2458 {
2459  char *s;
2460  int res;
2461 
2462  s = ast_alloca(strlen(path) + 10);
2463 
2464  snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
2465 
2466  if ((res = unlink(s))) {
2467  ast_log(LOG_ERROR, "Could not unlock path '%s': %s\n", path, strerror(errno));
2468  } else {
2469  ast_debug(1, "Unlocked path '%s'\n", path);
2470  }
2471 
2472  return res;
2473 }
2474 
2475 struct path_lock {
2477  int fd;
2478  char *path;
2479 };
2480 
2482 
2483 static void path_lock_destroy(struct path_lock *obj)
2484 {
2485  if (obj->fd >= 0) {
2486  close(obj->fd);
2487  }
2488  if (obj->path) {
2489  ast_free(obj->path);
2490  }
2491  ast_free(obj);
2492 }
2493 
2494 static enum AST_LOCK_RESULT ast_lock_path_flock(const char *path)
2495 {
2496  char *fs;
2497  int res;
2498  int fd;
2499  time_t start;
2500  struct path_lock *pl;
2501  struct stat st, ost;
2502 
2503  fs = ast_alloca(strlen(path) + 20);
2504 
2505  snprintf(fs, strlen(path) + 19, "%s/lock", path);
2506  if (lstat(fs, &st) == 0) {
2507  if ((st.st_mode & S_IFMT) == S_IFLNK) {
2508  ast_log(LOG_WARNING, "Unable to create lock file "
2509  "'%s': it's already a symbolic link\n",
2510  fs);
2511  return AST_LOCK_FAILURE;
2512  }
2513  if (st.st_nlink > 1) {
2514  ast_log(LOG_WARNING, "Unable to create lock file "
2515  "'%s': %u hard links exist\n",
2516  fs, (unsigned int) st.st_nlink);
2517  return AST_LOCK_FAILURE;
2518  }
2519  }
2520  if ((fd = open(fs, O_WRONLY | O_CREAT, 0600)) < 0) {
2521  ast_log(LOG_WARNING, "Unable to create lock file '%s': %s\n",
2522  fs, strerror(errno));
2523  return AST_LOCK_PATH_NOT_FOUND;
2524  }
2525  if (!(pl = ast_calloc(1, sizeof(*pl)))) {
2526  /* We don't unlink the lock file here, on the possibility that
2527  * someone else created it - better to leave a little mess
2528  * than create a big one by destroying someone else's lock
2529  * and causing something to be corrupted.
2530  */
2531  close(fd);
2532  return AST_LOCK_FAILURE;
2533  }
2534  pl->fd = fd;
2535  pl->path = ast_strdup(path);
2536 
2537  time(&start);
2538  while (
2539  #ifdef SOLARIS
2540  ((res = fcntl(pl->fd, F_SETLK, fcntl(pl->fd, F_GETFL) | O_NONBLOCK)) < 0) &&
2541  #else
2542  ((res = flock(pl->fd, LOCK_EX | LOCK_NB)) < 0) &&
2543  #endif
2544  (errno == EWOULDBLOCK) &&
2545  (time(NULL) - start < 5))
2546  usleep(1000);
2547  if (res) {
2548  ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n",
2549  path, strerror(errno));
2550  /* No unlinking of lock done, since we tried and failed to
2551  * flock() it.
2552  */
2553  path_lock_destroy(pl);
2554  return AST_LOCK_TIMEOUT;
2555  }
2556 
2557  /* Check for the race where the file is recreated or deleted out from
2558  * underneath us.
2559  */
2560  if (lstat(fs, &st) != 0 && fstat(pl->fd, &ost) != 0 &&
2561  st.st_dev != ost.st_dev &&
2562  st.st_ino != ost.st_ino) {
2563  ast_log(LOG_WARNING, "Unable to create lock file '%s': "
2564  "file changed underneath us\n", fs);
2565  path_lock_destroy(pl);
2566  return AST_LOCK_FAILURE;
2567  }
2568 
2569  /* Success: file created, flocked, and is the one we started with */
2573 
2574  ast_debug(1, "Locked path '%s'\n", path);
2575 
2576  return AST_LOCK_SUCCESS;
2577 }
2578 
2579 static int ast_unlock_path_flock(const char *path)
2580 {
2581  char *s;
2582  struct path_lock *p;
2583 
2584  s = ast_alloca(strlen(path) + 20);
2585 
2588  if (!strcmp(p->path, path)) {
2590  break;
2591  }
2592  }
2595 
2596  if (p) {
2597  snprintf(s, strlen(path) + 19, "%s/lock", path);
2598  unlink(s);
2599  path_lock_destroy(p);
2600  ast_debug(1, "Unlocked path '%s'\n", path);
2601  } else {
2602  ast_debug(1, "Failed to unlock path '%s': "
2603  "lock not found\n", path);
2604  }
2605 
2606  return 0;
2607 }
2608 
2610 {
2611  ast_lock_type = type;
2612 }
2613 
2614 enum AST_LOCK_RESULT ast_lock_path(const char *path)
2615 {
2616  enum AST_LOCK_RESULT r = AST_LOCK_FAILURE;
2617 
2618  switch (ast_lock_type) {
2619  case AST_LOCK_TYPE_LOCKFILE:
2620  r = ast_lock_path_lockfile(path);
2621  break;
2622  case AST_LOCK_TYPE_FLOCK:
2623  r = ast_lock_path_flock(path);
2624  break;
2625  }
2626 
2627  return r;
2628 }
2629 
2630 int ast_unlock_path(const char *path)
2631 {
2632  int r = 0;
2633 
2634  switch (ast_lock_type) {
2635  case AST_LOCK_TYPE_LOCKFILE:
2636  r = ast_unlock_path_lockfile(path);
2637  break;
2638  case AST_LOCK_TYPE_FLOCK:
2639  r = ast_unlock_path_flock(path);
2640  break;
2641  }
2642 
2643  return r;
2644 }
2645 
2646 int ast_record_review(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, const char *path)
2647 {
2648  int silencethreshold;
2649  int maxsilence = 0;
2650  int res = 0;
2651  int cmd = 0;
2652  int max_attempts = 3;
2653  int attempts = 0;
2654  int recorded = 0;
2655  int message_exists = 0;
2656  /* Note that urgent and private are for flagging messages as such in the future */
2657 
2658  /* barf if no pointer passed to store duration in */
2659  if (!duration) {
2660  ast_log(LOG_WARNING, "Error ast_record_review called without duration pointer\n");
2661  return -1;
2662  }
2663 
2664  cmd = '3'; /* Want to start by recording */
2665 
2666  silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
2667 
2668  while ((cmd >= 0) && (cmd != 't')) {
2669  switch (cmd) {
2670  case '1':
2671  if (!message_exists) {
2672  /* In this case, 1 is to record a message */
2673  cmd = '3';
2674  break;
2675  } else {
2676  ast_stream_and_wait(chan, "vm-msgsaved", "");
2677  cmd = 't';
2678  return res;
2679  }
2680  case '2':
2681  /* Review */
2682  ast_verb(3, "Reviewing the recording\n");
2683  cmd = ast_stream_and_wait(chan, recordfile, AST_DIGIT_ANY);
2684  break;
2685  case '3':
2686  message_exists = 0;
2687  /* Record */
2688  ast_verb(3, "R%secording\n", recorded == 1 ? "e-r" : "");
2689  recorded = 1;
2690  if ((cmd = ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, NULL, silencethreshold, maxsilence, path)) == -1) {
2691  /* User has hung up, no options to give */
2692  return cmd;
2693  }
2694  if (cmd == '0') {
2695  break;
2696  } else if (cmd == '*') {
2697  break;
2698  } else {
2699  /* If all is well, a message exists */
2700  message_exists = 1;
2701  cmd = 0;
2702  }
2703  break;
2704  case '4':
2705  case '5':
2706  case '6':
2707  case '7':
2708  case '8':
2709  case '9':
2710  case '*':
2711  case '#':
2712  cmd = ast_play_and_wait(chan, "vm-sorry");
2713  break;
2714  default:
2715  if (message_exists) {
2716  cmd = ast_play_and_wait(chan, "vm-review");
2717  } else {
2718  if (!(cmd = ast_play_and_wait(chan, "vm-torerecord"))) {
2719  cmd = ast_waitfordigit(chan, 600);
2720  }
2721  }
2722 
2723  if (!cmd) {
2724  cmd = ast_waitfordigit(chan, 6000);
2725  }
2726  if (!cmd) {
2727  attempts++;
2728  }
2729  if (attempts > max_attempts) {
2730  cmd = 't';
2731  }
2732  }
2733  }
2734  if (cmd == 't') {
2735  cmd = 0;
2736  }
2737  return cmd;
2738 }
2739 
2740 #define RES_UPONE (1 << 16)
2741 #define RES_EXIT (1 << 17)
2742 #define RES_REPEAT (1 << 18)
2743 #define RES_RESTART ((1 << 19) | RES_REPEAT)
2744 
2745 static int ast_ivr_menu_run_internal(struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata);
2746 
2747 static int ivr_dispatch(struct ast_channel *chan, struct ast_ivr_option *option, char *exten, void *cbdata)
2748 {
2749  int res;
2750  int (*ivr_func)(struct ast_channel *, void *);
2751  char *c;
2752  char *n;
2753 
2754  switch (option->action) {
2755  case AST_ACTION_UPONE:
2756  return RES_UPONE;
2757  case AST_ACTION_EXIT:
2758  return RES_EXIT | (((unsigned long)(option->adata)) & 0xffff);
2759  case AST_ACTION_REPEAT:
2760  return RES_REPEAT | (((unsigned long)(option->adata)) & 0xffff);
2761  case AST_ACTION_RESTART:
2762  return RES_RESTART ;
2763  case AST_ACTION_NOOP:
2764  return 0;
2765  case AST_ACTION_BACKGROUND:
2766  res = ast_stream_and_wait(chan, (char *)option->adata, AST_DIGIT_ANY);
2767  if (res < 0) {
2768  ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
2769  res = 0;
2770  }
2771  return res;
2772  case AST_ACTION_PLAYBACK:
2773  res = ast_stream_and_wait(chan, (char *)option->adata, "");
2774  if (res < 0) {
2775  ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
2776  res = 0;
2777  }
2778  return res;
2779  case AST_ACTION_MENU:
2780  if ((res = ast_ivr_menu_run_internal(chan, (struct ast_ivr_menu *)option->adata, cbdata)) == -2) {
2781  /* Do not pass entry errors back up, treat as though it was an "UPONE" */
2782  res = 0;
2783  }
2784  return res;
2785  case AST_ACTION_WAITOPTION:
2786  if (!(res = ast_waitfordigit(chan, ast_channel_pbx(chan) ? ast_channel_pbx(chan)->rtimeoutms : 10000))) {
2787  return 't';
2788  }
2789  return res;
2790  case AST_ACTION_CALLBACK:
2791  ivr_func = option->adata;
2792  res = ivr_func(chan, cbdata);
2793  return res;
2794  case AST_ACTION_TRANSFER:
2795  res = ast_parseable_goto(chan, option->adata);
2796  return 0;
2797  case AST_ACTION_PLAYLIST:
2798  case AST_ACTION_BACKLIST:
2799  res = 0;
2800  c = ast_strdupa(option->adata);
2801  while ((n = strsep(&c, ";"))) {
2802  if ((res = ast_stream_and_wait(chan, n,
2803  (option->action == AST_ACTION_BACKLIST) ? AST_DIGIT_ANY : ""))) {
2804  break;
2805  }
2806  }
2807  ast_stopstream(chan);
2808  return res;
2809  default:
2810  ast_log(LOG_NOTICE, "Unknown dispatch function %u, ignoring!\n", option->action);
2811  return 0;
2812  }
2813  return -1;
2814 }
2815 
2816 static int option_exists(struct ast_ivr_menu *menu, char *option)
2817 {
2818  int x;
2819  for (x = 0; menu->options[x].option; x++) {
2820  if (!strcasecmp(menu->options[x].option, option)) {
2821  return x;
2822  }
2823  }
2824  return -1;
2825 }
2826 
2827 static int option_matchmore(struct ast_ivr_menu *menu, char *option)
2828 {
2829  int x;
2830  for (x = 0; menu->options[x].option; x++) {
2831  if ((!strncasecmp(menu->options[x].option, option, strlen(option))) &&
2832  (menu->options[x].option[strlen(option)])) {
2833  return x;
2834  }
2835  }
2836  return -1;
2837 }
2838 
2839 static int read_newoption(struct ast_channel *chan, struct ast_ivr_menu *menu, char *exten, int maxexten)
2840 {
2841  int res = 0;
2842  int ms;
2843  while (option_matchmore(menu, exten)) {
2844  ms = ast_channel_pbx(chan) ? ast_channel_pbx(chan)->dtimeoutms : 5000;
2845  if (strlen(exten) >= maxexten - 1) {
2846  break;
2847  }
2848  if ((res = ast_waitfordigit(chan, ms)) < 1) {
2849  break;
2850  }
2851  exten[strlen(exten) + 1] = '\0';
2852  exten[strlen(exten)] = res;
2853  }
2854  return res > 0 ? 0 : res;
2855 }
2856 
2857 static int ast_ivr_menu_run_internal(struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata)
2858 {
2859  /* Execute an IVR menu structure */
2860  int res = 0;
2861  int pos = 0;
2862  int retries = 0;
2863  char exten[AST_MAX_EXTENSION] = "s";
2864  if (option_exists(menu, "s") < 0) {
2865  strcpy(exten, "g");
2866  if (option_exists(menu, "g") < 0) {
2867  ast_log(LOG_WARNING, "No 's' nor 'g' extension in menu '%s'!\n", menu->title);
2868  return -1;
2869  }
2870  }
2871  while (!res) {
2872  while (menu->options[pos].option) {
2873  if (!strcasecmp(menu->options[pos].option, exten)) {
2874  res = ivr_dispatch(chan, menu->options + pos, exten, cbdata);
2875  ast_debug(1, "IVR Dispatch of '%s' (pos %d) yields %d\n", exten, pos, res);
2876  if (res < 0) {
2877  break;
2878  } else if (res & RES_UPONE) {
2879  return 0;
2880  } else if (res & RES_EXIT) {
2881  return res;
2882  } else if (res & RES_REPEAT) {
2883  int maxretries = res & 0xffff;
2884  if ((res & RES_RESTART) == RES_RESTART) {
2885  retries = 0;
2886  } else {
2887  retries++;
2888  }
2889  if (!maxretries) {
2890  maxretries = 3;
2891  }
2892  if ((maxretries > 0) && (retries >= maxretries)) {
2893  ast_debug(1, "Max retries %d exceeded\n", maxretries);
2894  return -2;
2895  } else {
2896  if (option_exists(menu, "g") > -1) {
2897  strcpy(exten, "g");
2898  } else if (option_exists(menu, "s") > -1) {
2899  strcpy(exten, "s");
2900  }
2901  }
2902  pos = 0;
2903  continue;
2904  } else if (res && strchr(AST_DIGIT_ANY, res)) {
2905  ast_debug(1, "Got start of extension, %c\n", res);
2906  exten[1] = '\0';
2907  exten[0] = res;
2908  if ((res = read_newoption(chan, menu, exten, sizeof(exten)))) {
2909  break;
2910  }
2911  if (option_exists(menu, exten) < 0) {
2912  if (option_exists(menu, "i")) {
2913  ast_debug(1, "Invalid extension entered, going to 'i'!\n");
2914  strcpy(exten, "i");
2915  pos = 0;
2916  continue;
2917  } else {
2918  ast_debug(1, "Aborting on invalid entry, with no 'i' option!\n");
2919  res = -2;
2920  break;
2921  }
2922  } else {
2923  ast_debug(1, "New existing extension: %s\n", exten);
2924  pos = 0;
2925  continue;
2926  }
2927  }
2928  }
2929  pos++;
2930  }
2931  ast_debug(1, "Stopping option '%s', res is %d\n", exten, res);
2932  pos = 0;
2933  if (!strcasecmp(exten, "s")) {
2934  strcpy(exten, "g");
2935  } else {
2936  break;
2937  }
2938  }
2939  return res;
2940 }
2941 
2942 int ast_ivr_menu_run(struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata)
2943 {
2944  int res = ast_ivr_menu_run_internal(chan, menu, cbdata);
2945  /* Hide internal coding */
2946  return res > 0 ? 0 : res;
2947 }
2948 
2949 char *ast_read_textfile(const char *filename)
2950 {
2951  int fd, count = 0, res;
2952  char *output = NULL;
2953  struct stat filesize;
2954 
2955  if (stat(filename, &filesize) == -1) {
2956  ast_log(LOG_WARNING, "Error can't stat %s\n", filename);
2957  return NULL;
2958  }
2959 
2960  count = filesize.st_size + 1;
2961 
2962  if ((fd = open(filename, O_RDONLY)) < 0) {
2963  ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno));
2964  return NULL;
2965  }
2966 
2967  if ((output = ast_malloc(count))) {
2968  res = read(fd, output, count - 1);
2969  if (res == count - 1) {
2970  output[res] = '\0';
2971  } else {
2972  ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count - 1, strerror(errno));
2973  ast_free(output);
2974  output = NULL;
2975  }
2976  }
2977 
2978  close(fd);
2979 
2980  return output;
2981 }
2982 
2983 static int parse_options(const struct ast_app_option *options, void *_flags, char **args, char *optstr, int flaglen)
2984 {
2985  char *s, *arg;
2986  int curarg, res = 0;
2987  unsigned int argloc;
2988  struct ast_flags *flags = _flags;
2989  struct ast_flags64 *flags64 = _flags;
2990 
2991  if (flaglen == 32) {
2992  ast_clear_flag(flags, AST_FLAGS_ALL);
2993  } else {
2994  flags64->flags = 0;
2995  }
2996 
2997  if (!optstr) {
2998  return 0;
2999  }
3000 
3001  s = optstr;
3002  while (*s) {
3003  curarg = *s++ & 0x7f; /* the array (in app.h) has 128 entries */
3004  argloc = options[curarg].arg_index;
3005  if (*s == '(') {
3006  int paren = 1, quote = 0;
3007  int parsequotes = (s[1] == '"') ? 1 : 0;
3008 
3009  /* Has argument */
3010  arg = ++s;
3011  for (; *s; s++) {
3012  if (*s == '(' && !quote) {
3013  paren++;
3014  } else if (*s == ')' && !quote) {
3015  /* Count parentheses, unless they're within quotes (or backslashed, below) */
3016  paren--;
3017  } else if (*s == '"' && parsequotes) {
3018  /* Leave embedded quotes alone, unless they are the first character */
3019  quote = quote ? 0 : 1;
3020  ast_copy_string(s, s + 1, INT_MAX);
3021  s--;
3022  } else if (*s == '\\') {
3023  if (!quote) {
3024  /* If a backslash is found outside of quotes, remove it */
3025  ast_copy_string(s, s + 1, INT_MAX);
3026  } else if (quote && s[1] == '"') {
3027  /* Backslash for a quote character within quotes, remove the backslash */
3028  ast_copy_string(s, s + 1, INT_MAX);
3029  } else {
3030  /* Backslash within quotes, keep both characters */
3031  s++;
3032  }
3033  }
3034 
3035  if (paren == 0) {
3036  break;
3037  }
3038  }
3039  /* This will find the closing paren we found above, or none, if the string ended before we found one. */
3040  if ((s = strchr(s, ')'))) {
3041  if (argloc) {
3042  args[argloc - 1] = arg;
3043  }
3044  *s++ = '\0';
3045  } else {
3046  ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg);
3047  res = -1;
3048  break;
3049  }
3050  } else if (argloc) {
3051  args[argloc - 1] = "";
3052  }
3053  if (!options[curarg].flag) {
3054  ast_log(LOG_WARNING, "Unrecognized option: '%c'\n", curarg);
3055  }
3056  if (flaglen == 32) {
3057  ast_set_flag(flags, options[curarg].flag);
3058  } else {
3059  ast_set_flag64(flags64, options[curarg].flag);
3060  }
3061  }
3062 
3063  return res;
3064 }
3065 
3066 int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
3067 {
3068  return parse_options(options, flags, args, optstr, 32);
3069 }
3070 
3071 int ast_app_parse_options64(const struct ast_app_option *options, struct ast_flags64 *flags, char **args, char *optstr)
3072 {
3073  return parse_options(options, flags, args, optstr, 64);
3074 }
3075 
3076 void ast_app_options2str64(const struct ast_app_option *options, struct ast_flags64 *flags, char *buf, size_t len)
3077 {
3078  unsigned int i, found = 0;
3079  for (i = 32; i < 128 && found < len; i++) {
3080  if (ast_test_flag64(flags, options[i].flag)) {
3081  buf[found++] = i;
3082  }
3083  }
3084  buf[found] = '\0';
3085 }
3086 
3087 int ast_get_encoded_char(const char *stream, char *result, size_t *consumed)
3088 {
3089  int i;
3090  *consumed = 1;
3091  *result = 0;
3092  if (ast_strlen_zero(stream)) {
3093  *consumed = 0;
3094  return -1;
3095  }
3096 
3097  if (*stream == '\\') {
3098  *consumed = 2;
3099  switch (*(stream + 1)) {
3100  case 'n':
3101  *result = '\n';
3102  break;
3103  case 'r':
3104  *result = '\r';
3105  break;
3106  case 't':
3107  *result = '\t';
3108  break;
3109  case 'x':
3110  /* Hexadecimal */
3111  if (strchr("0123456789ABCDEFabcdef", *(stream + 2)) && *(stream + 2) != '\0') {
3112  *consumed = 3;
3113  if (*(stream + 2) <= '9') {
3114  *result = *(stream + 2) - '0';
3115  } else if (*(stream + 2) <= 'F') {
3116  *result = *(stream + 2) - 'A' + 10;
3117  } else {
3118  *result = *(stream + 2) - 'a' + 10;
3119  }
3120  } else {
3121  ast_log(LOG_ERROR, "Illegal character '%c' in hexadecimal string\n", *(stream + 2));
3122  return -1;
3123  }
3124 
3125  if (strchr("0123456789ABCDEFabcdef", *(stream + 3)) && *(stream + 3) != '\0') {
3126  *consumed = 4;
3127  *result <<= 4;
3128  if (*(stream + 3) <= '9') {
3129  *result += *(stream + 3) - '0';
3130  } else if (*(stream + 3) <= 'F') {
3131  *result += *(stream + 3) - 'A' + 10;
3132  } else {
3133  *result += *(stream + 3) - 'a' + 10;
3134  }
3135  }
3136  break;
3137  case '0':
3138  /* Octal */
3139  *consumed = 2;
3140  for (i = 2; ; i++) {
3141  if (strchr("01234567", *(stream + i)) && *(stream + i) != '\0') {
3142  (*consumed)++;
3143  ast_debug(5, "result was %d, ", *result);
3144  *result <<= 3;
3145  *result += *(stream + i) - '0';
3146  ast_debug(5, "is now %d\n", *result);
3147  } else {
3148  break;
3149  }
3150  }
3151  break;
3152  default:
3153  *result = *(stream + 1);
3154  }
3155  } else {
3156  *result = *stream;
3157  *consumed = 1;
3158  }
3159  return 0;
3160 }
3161 
3162 char *ast_get_encoded_str(const char *stream, char *result, size_t result_size)
3163 {
3164  char *cur = result;
3165  size_t consumed;
3166 
3167  while (cur < result + result_size - 1 && !ast_get_encoded_char(stream, cur, &consumed)) {
3168  cur++;
3169  stream += consumed;
3170  }
3171  *cur = '\0';
3172  return result;
3173 }
3174 
3175 int ast_str_get_encoded_str(struct ast_str **str, int maxlen, const char *stream)
3176 {
3177  char next, *buf;
3178  size_t offset = 0;
3179  size_t consumed;
3180 
3181  if (strchr(stream, '\\')) {
3182  while (!ast_get_encoded_char(stream, &next, &consumed)) {
3183  if (offset + 2 > ast_str_size(*str) && maxlen > -1) {
3184  ast_str_make_space(str, maxlen > 0 ? maxlen : (ast_str_size(*str) + 48) * 2 - 48);
3185  }
3186  if (offset + 2 > ast_str_size(*str)) {
3187  break;
3188  }
3189  buf = ast_str_buffer(*str);
3190  buf[offset++] = next;
3191  stream += consumed;
3192  }
3193  buf = ast_str_buffer(*str);
3194  buf[offset++] = '\0';
3195  ast_str_update(*str);
3196  } else {
3197  ast_str_set(str, maxlen, "%s", stream);
3198  }
3199  return 0;
3200 }
3201 
3203 {
3204  closefrom(n + 1);
3205 }
3206 
3207 int ast_safe_fork(int stop_reaper)
3208 {
3209  sigset_t signal_set, old_set;
3210  int pid;
3211 
3212  /* Don't let the default signal handler for children reap our status */
3213  if (stop_reaper) {
3215  }
3216 
3217  /* GCC 4.9 gives a bogus "right-hand operand of comma expression has
3218  * no effect" warning */
3219  (void) sigfillset(&signal_set);
3220  pthread_sigmask(SIG_BLOCK, &signal_set, &old_set);
3221 
3222  pid = fork();
3223 
3224  if (pid != 0) {
3225  /* Fork failed or parent */
3226  pthread_sigmask(SIG_SETMASK, &old_set, NULL);
3227  if (!stop_reaper && pid > 0) {
3228  struct zombie *cur = ast_calloc(1, sizeof(*cur));
3229  if (cur) {
3230  cur->pid = pid;
3232  AST_LIST_INSERT_TAIL(&zombies, cur, list);
3234  if (shaun_of_the_dead_thread == AST_PTHREADT_NULL) {
3235  if (ast_pthread_create_background(&shaun_of_the_dead_thread, NULL, shaun_of_the_dead, NULL)) {
3236  ast_log(LOG_ERROR, "Shaun of the Dead wants to kill zombies, but can't?!!\n");
3237  shaun_of_the_dead_thread = AST_PTHREADT_NULL;
3238  }
3239  }
3240  }
3241  }
3242  return pid;
3243  } else {
3244  /* Child */
3245 #ifdef HAVE_CAP
3246  cap_set_proc(child_cap);
3247 #endif
3248 
3249  /* Before we unblock our signals, return our trapped signals back to the defaults */
3250  signal(SIGHUP, SIG_DFL);
3251  signal(SIGCHLD, SIG_DFL);
3252  signal(SIGINT, SIG_DFL);
3253  signal(SIGURG, SIG_DFL);
3254  signal(SIGTERM, SIG_DFL);
3255  signal(SIGPIPE, SIG_DFL);
3256  signal(SIGXFSZ, SIG_DFL);
3257 
3258  /* unblock important signal handlers */
3259  if (pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
3260  ast_log(LOG_WARNING, "unable to unblock signals: %s\n", strerror(errno));
3261  _exit(1);
3262  }
3263 
3264  return pid;
3265  }
3266 }
3267 
3269 {
3271 }
3272 
3273 int ast_app_parse_timelen(const char *timestr, int *result, enum ast_timelen unit)
3274 {
3275  int res;
3276  char u[10];
3277 #ifdef HAVE_LONG_DOUBLE_WIDER
3278  long double amount;
3279  #define FMT "%30Lf%9s"
3280 #else
3281  double amount;
3282  #define FMT "%30lf%9s"
3283 #endif
3284  if (!timestr) {
3285  return -1;
3286  }
3287 
3288  res = sscanf(timestr, FMT, &amount, u);
3289 
3290  if (res == 0 || res == EOF) {
3291 #undef FMT
3292  return -1;
3293  } else if (res == 2) {
3294  switch (u[0]) {
3295  case 'h':
3296  case 'H':
3297  unit = TIMELEN_HOURS;
3298  if (u[1] != '\0') {
3299  return -1;
3300  }
3301  break;
3302  case 's':
3303  case 'S':
3304  unit = TIMELEN_SECONDS;
3305  if (u[1] != '\0') {
3306  return -1;
3307  }
3308  break;
3309  case 'm':
3310  case 'M':
3311  if (toupper(u[1]) == 'S') {
3312  unit = TIMELEN_MILLISECONDS;
3313  if (u[2] != '\0') {
3314  return -1;
3315  }
3316  } else if (u[1] == '\0') {
3317  unit = TIMELEN_MINUTES;
3318  } else {
3319  return -1;
3320  }
3321  break;
3322  default:
3323  return -1;
3324  }
3325  }
3326 
3327  switch (unit) {
3328  case TIMELEN_HOURS:
3329  amount *= 60;
3330  /* fall-through */
3331  case TIMELEN_MINUTES:
3332  amount *= 60;
3333  /* fall-through */
3334  case TIMELEN_SECONDS:
3335  amount *= 1000;
3336  /* fall-through */
3337  case TIMELEN_MILLISECONDS:
3338  ;
3339  }
3340  *result = amount > INT_MAX ? INT_MAX : (int) amount;
3341  return 0;
3342 }
3343 
3345 {
3346  return queue_topic_all;
3347 }
3348 
3349 struct stasis_topic *ast_queue_topic(const char *queuename)
3350 {
3351  return stasis_topic_pool_get_topic(queue_topic_pool, queuename);
3352 }
3353 
3354 static void app_cleanup(void)
3355 {
3356 #ifdef HAS_CAP
3357  cap_free(child_cap);
3358 #endif
3359  ao2_cleanup(queue_topic_pool);
3360  queue_topic_pool = NULL;
3361  ao2_cleanup(queue_topic_all);
3362  queue_topic_all = NULL;
3363 }
3364 
3365 int app_init(void)
3366 {
3367  ast_register_cleanup(app_cleanup);
3368 #ifdef HAVE_CAP
3369  child_cap = cap_from_text("cap_net_admin-eip");
3370 #endif
3371  queue_topic_all = stasis_topic_create("queue:all");
3372  if (!queue_topic_all) {
3373  return -1;
3374  }
3375  queue_topic_pool = stasis_topic_pool_create(queue_topic_all);
3376  if (!queue_topic_pool) {
3377  return -1;
3378  }
3379  return 0;
3380 }
unsigned int module_version
The version of this function table.
enum ast_getdata_result ast_app_getdata_terminator(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout, char *terminator)
Plays a stream and gets DTMF data from a channel.
Definition: main/app.c:193
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1574
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Definition: channel.c:1150
int app_init(void)
Initialize the application core.
Definition: main/app.c:3365
Tone Indication Support.
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
Main Channel structure associated with a channel.
channel group info
Definition: channel.h:2915
struct ast_module * module
The module for the voicemail provider.
struct stasis_topic * ast_queue_topic(const char *queuename)
Get the Stasis Message Bus API topic for queue messages for a particular queue name.
Definition: main/app.c:3349
static int __ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence, const char *path, int prepend, const char *acceptdtmf, const char *canceldtmf, int skip_confirmation_sound, enum ast_record_if_exists if_exists)
Definition: main/app.c:1727
void( ast_waitstream_fr_cb)(struct ast_channel *chan, long ms, enum ast_waitstream_fr_cb_values val)
callback used during dtmf controlled file playback to indicate location of playback in a file after r...
Definition: file.h:65
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1293
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
unsigned int __ast_app_separate_args(char *buf, char delim, int remove_chars, char **array, int arraylen)
Separate a string into arguments in an array.
Definition: main/app.c:2356
int ast_vm_msg_remove(const char *mailbox, const char *context, size_t num_msgs, const char *folder, const char *msgs[])
Remove/delete messages from a mailbox folder.
Definition: main/app.c:697
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
static AO2_GLOBAL_OBJ_STATIC(vm_provider)
The container for the voicemail provider.
int ast_play_and_prepend(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence)
Record a file based on input frm a channel. Recording is performed in 'prepend' mode which works a li...
Definition: main/app.c:2159
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
int ast_app_inboxcount2(const char *mailboxes, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Determine number of urgent/new/old messages in a mailbox.
Definition: main/app.c:619
static struct stasis_topic * queue_topic_all
Define Stasis Message Bus API topic objects.
Definition: main/app.c:90
static struct ast_tone_zone * ast_tone_zone_unref(struct ast_tone_zone *tz)
Release a reference to an ast_tone_zone.
Definition: indications.h:205
void ast_unreplace_sigchld(void)
Restore the SIGCHLD handler.
Definition: extconf.c:815
int ast_app_getdata_full(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
Full version with audiofd and controlfd. NOTE: returns '2' on ctrlfd available, not '1' like other fu...
Definition: main/app.c:247
int ast_vm_msg_move(const char *mailbox, const char *context, size_t num_msgs, const char *oldfolder, const char *old_msg_ids[], const char *newfolder)
Move messages from one folder to another.
Definition: main/app.c:683
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX". If folder is "INBOX", includes the number of messages in the "Urgent" folder.
Definition: main/app.c:582
static int vm_greeter_warnings
Definition: main/app.c:466
int ast_app_inboxcount(const char *mailboxes, int *newmsgs, int *oldmsgs)
Determine number of new/old messages in a mailbox.
Definition: main/app.c:604
int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params)
Definition: channel.c:2951
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4277
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
int ast_app_parse_timelen(const char *timestr, int *result, enum ast_timelen unit)
Common routine to parse time lengths, with optional time unit specifier.
Definition: main/app.c:3273
Convenient Signal Processing routines.
int ast_app_group_set_channel(struct ast_channel *chan, const char *data)
Set the group for a channel, splitting the provided data into group and category, if specified...
Definition: main/app.c:2193
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
int ast_vm_greeter_is_registered(void)
Determine if a voicemail greeter provider is registered.
Definition: main/app.c:468
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
Voicemail greeter function table definition.
int ast_unlock_path(const char *path)
Unlock a path.
Definition: main/app.c:2630
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1758
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
Definition: main/app.c:3202
ast_record_if_exists
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
Test Framework API.
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4257
void( ast_vm_msg_play_cb)(struct ast_channel *chan, const char *playfile, int duration)
Voicemail playback callback function definition.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:6879
Definition of a media format.
Definition: format.c:43
int ast_senddigit_external(struct ast_channel *chan, char digit, unsigned int duration)
Send a DTMF digit to a channel from an external thread.
Definition: channel.c:4987
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:3066
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
int ast_app_run_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_location, const char *sub_args, int ignore_hangup)
Run a subroutine on a channel, placing an optional second channel into autoservice.
Definition: main/app.c:328
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
struct ast_vm_mailbox_snapshot * ast_vm_mailbox_snapshot_destroy(struct ast_vm_mailbox_snapshot *mailbox_snapshot)
destroy a snapshot
Definition: main/app.c:675
struct stasis_topic * stasis_topic_pool_get_topic(struct stasis_topic_pool *pool, const char *topic_name)
Find or create a topic in the pool.
Definition: stasis.c:1884
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:393
void ast_app_options2str64(const struct ast_app_option *options, struct ast_flags64 *flags, char *buf, size_t len)
Given a list of options array, return an option string based on passed flags.
Definition: main/app.c:3076
int ast_sf_stream(struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *chan2, const char *digits, int frequency, int is_external)
Send a string of SF digits to a channel.
Definition: main/app.c:1097
Definitions to aid in the use of thread local storage.
int ast_senddigit(struct ast_channel *chan, char digit, unsigned int duration)
Send a DTMF digit to a channel.
Definition: channel.c:4974
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition: file.c:1141
int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout)
This function presents a dialtone and reads an extension into 'collect' which must be a pointer to a ...
Definition: main/app.c:138
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Check the given mailbox's message count.
int ast_vm_msg_forward(const char *from_mailbox, const char *from_context, const char *from_folder, const char *to_mailbox, const char *to_context, const char *to_folder, size_t num_msgs, const char *msg_ids[], int delete_old)
forward a message from one mailbox to another.
Definition: main/app.c:709
Structure used to handle a large number of boolean flags == used only in app_dial?
Definition: utils.h:204
int ast_play_and_record_full(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence, const char *path, const char *acceptdtmf, const char *canceldtmf, int skip_confirmation_sound, enum ast_record_if_exists if_exists)
Record a file based on input from a channel This function will play "auth-thankyou" upon successful r...
Definition: main/app.c:2149
struct stasis_topic * ast_queue_topic_all(void)
Get the Stasis Message Bus API topic for queue messages.
Definition: main/app.c:3344
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
int ast_linear_stream(struct ast_channel *chan, const char *filename, int fd, int allowoverride)
Stream a filename (or file descriptor) as a generator.
Definition: main/app.c:1235
const char * ast_vm_index_to_foldername(int id)
Return name of folder, given an id.
Definition: main/app.c:653
struct ast_frame_subclass subclass
int totalsilence
Definition: dsp.c:411
ast_getdata_result
Utility functions.
struct stasis_topic_pool * stasis_topic_pool_create(struct stasis_topic *pooled_topic)
Create a topic pool that routes messages from dynamically generated topics to the given topic...
Definition: stasis.c:1833
off_t ast_tellstream(struct ast_filestream *fs)
Tell where we are in a stream.
Definition: file.c:1085
void ast_frame_dtor(struct ast_frame *frame)
NULL-safe wrapper for ast_frfree, good for RAII_VAR.
Definition: main/frame.c:187
static int set_read_to_slin(struct ast_channel *chan, struct ast_format **orig_format)
Sets a channel's read format to ast_format_slin, recording its original format.
Definition: main/app.c:1692
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
Definition: linkedlists.h:333
Number structure.
Definition: app_followme.c:154
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
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
int ast_app_group_get_count(const char *group, const char *category)
Get the current channel count of the specified group and category.
Definition: main/app.c:2240
#define AST_MALLOCD_HDR
int ast_app_group_list_rdlock(void)
Read Lock the group count list.
Definition: main/app.c:2341
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
A structure to hold the description of an application 'option'.
static struct ast_frame * make_silence(const struct ast_frame *orig)
Construct a silence frame of the same duration as orig.
Definition: main/app.c:1640
General Asterisk PBX channel definitions.
Asterisk JSON abstraction layer.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
Asterisk file paths, configured in asterisk.conf.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5762
A set of tones for a given locale.
Definition: indications.h:74
Definition: dsp.c:407
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
int ast_control_streamfile_w_cb(struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *suspend, const char *restart, int skipms, long *offsetms, ast_waitstream_fr_cb cb)
Stream a file with fast forward, pause, reverse, restart.
Definition: main/app.c:1451
int ast_app_group_update(struct ast_channel *old, struct ast_channel *new)
Update all group counting for a channel to a new one.
Definition: main/app.c:2300
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:8866
#define AST_MAX_EXTENSION
Definition: channel.h:134
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
int ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int *sound_duration, int silencethreshold, int maxsilence, const char *path)
Record a file based on input from a channel. Use default accept and cancel DTMF. This function will p...
Definition: main/app.c:2154
#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
int ast_str_get_encoded_str(struct ast_str **str, int maxlen, const char *stream)
Decode a stream of encoded control or extended ASCII characters.
Definition: main/app.c:3175
static struct ast_tone_zone_sound * ast_tone_zone_sound_unref(struct ast_tone_zone_sound *ts)
Release a reference to an ast_tone_zone_sound.
Definition: indications.h:227
char * ast_strsep(char **s, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
Definition: utils.c:1835
A set of macros to manage forward-linked lists.
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
int ast_waitstream_fr(struct ast_channel *c, const char *breakon, const char *forward, const char *rewind, int ms)
Same as waitstream but allows stream to be forwarded or rewound.
Definition: file.c:1809
#define ast_debug(level,...)
Log a DEBUG message.
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5803
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
Definition: stasis.c:617
void ast_vm_greeter_unregister(const char *module_name)
Unregister the specified voicemail greeter provider.
Definition: main/app.c:511
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
void ast_replace_sigchld(void)
Replace the SIGCHLD handler.
Definition: extconf.c:801
Core PBX routines and definitions.
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
struct ast_module * module
The module for the voicemail greeter provider.
const char * ast_app_expand_sub_args(struct ast_channel *chan, const char *args)
Add missing context/exten to subroutine argument string.
Definition: main/app.c:278
int ast_app_group_match_get_count(const char *groupmatch, const char *category)
Get the current channel count of all groups that match the specified pattern and category.
Definition: main/app.c:2260
static int global_maxsilence
Definition: app_minivm.c:691
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
Definition: linkedlists.h:291
void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
Set the minimum average magnitude threshold to determine talking by the DSP.
Definition: dsp.c:1788
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:189
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
struct ast_silence_generator * ast_channel_start_silence_generator(struct ast_channel *chan)
Starts a silence generator on the given channel.
Definition: channel.c:8164
int ast_app_messagecount(const char *mailbox_id, const char *folder)
Get the number of messages in a given mailbox folder.
Definition: main/app.c:645
int __ast_vm_greeter_register(const struct ast_vm_greeter_functions *vm_table, struct ast_module *module)
Set voicemail greeter function callbacks.
Definition: main/app.c:479
struct ast_vm_mailbox_snapshot * ast_vm_mailbox_snapshot_create(const char *mailbox, const char *context, const char *folder, int descending, enum ast_vm_snapshot_sort_val sort_val, int combine_INBOX_and_OLD)
Create a snapshot of a mailbox which contains information about every msg.
Definition: main/app.c:661
int ast_app_sayname(struct ast_channel *chan, const char *mailbox_id)
Play a recorded user name for the mailbox to the specified channel.
Definition: main/app.c:637
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
int ast_mf_stream(struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *chan2, const char *digits, int between, unsigned int duration, unsigned int durationkp, unsigned int durationst, int is_external)
Send a string of MF digits to a channel.
Definition: main/app.c:1113
Support for dynamic strings.
Definition: strings.h:623
int ast_control_streamfile(struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *suspend, const char *restart, int skipms, long *offsetms)
Stream a file with fast forward, pause, reverse, restart.
Definition: main/app.c:1465
void ast_dtmf_stream_external(struct ast_channel *chan, const char *digits, int between, unsigned int duration)
Send a string of DTMF digits to a channel from an external thread.
Definition: main/app.c:1142
const char * module_name
The name of the module that provides the voicemail greeter functionality.
int ast_app_group_split_group(const char *data, char *group, int group_max, char *category, int category_max)
Split a group string into group and category, returning a default category if none is provided...
Definition: main/app.c:2166
struct ast_frame * ast_readframe(struct ast_filestream *s)
Read a frame from a filestream.
Definition: file.c:936
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
Definition: astobj2.h:859
Stack applications callback functions.
int ast_senddigit_mf_end(struct ast_channel *chan)
End sending an MF digit to a channel.
Definition: channel.c:4943
int ast_stream_rewind(struct ast_filestream *fs, off_t ms)
Rewind stream ms.
Definition: file.c:1100
struct ast_tone_zone * ast_get_indication_zone(const char *country)
locate ast_tone_zone
Definition: indications.c:439
int ast_control_tone(struct ast_channel *chan, const char *tone)
Controls playback of a tone.
Definition: main/app.c:1545
Description of a tone.
Definition: indications.h:35
struct ast_tone_zone_sound * ast_get_indication_tone(const struct ast_tone_zone *zone, const char *indication)
Locate a tone zone sound.
Definition: indications.c:461
int ast_app_group_discard(struct ast_channel *chan)
Discard all group counting for a channel.
Definition: main/app.c:2319
struct ast_filestream * ast_writefile(const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
Starts writing a file.
Definition: file.c:1423
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
Definition: file.c:1075
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:410
unsigned int stop
Definition: res_smdi.c:217
void ast_set_lock_type(enum AST_LOCK_TYPE type)
Set the type of locks used by ast_lock_path()
Definition: main/app.c:2609
void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
Stops a previously-started silence generator on the given channel.
Definition: channel.c:8210
union ast_frame::@224 data
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
void ast_install_stack_functions(const struct ast_app_stack_funcs *funcs)
Set stack application function callbacks.
Definition: main/app.c:273
int ast_app_group_list_wrlock(void)
Write Lock the group count list.
Definition: main/app.c:2336
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1878
int ast_closestream(struct ast_filestream *f)
Closes a stream.
Definition: file.c:1111
int ast_vm_msg_play(struct ast_channel *chan, const char *mailbox, const char *context, const char *folder, const char *msg_num, ast_vm_msg_play_cb *cb)
Play a voicemail msg back on a channel.
Definition: main/app.c:726
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:5144
struct ast_ivr_option * options
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
Definition: main/app.c:1616
void ast_safe_fork_cleanup(void)
Common routine to cleanup after fork'ed process is complete (if reaping was stopped) ...
Definition: main/app.c:3268
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
unsigned int arg_index
The index of the entry in the arguments array that should be used for this option's argument...
Structure used to handle boolean flags.
Definition: utils.h:199
static int vm_warnings
Definition: main/app.c:355
int(* run_sub)(struct ast_channel *chan, const char *args, int ignore_hangup)
Callback for the routine to run a subroutine on a channel.
int ast_truncstream(struct ast_filestream *fs)
Trunc stream at current location.
Definition: file.c:1080
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:483
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
Definition: module.h:469
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3175
const char * module_name
The name of the module that provides the voicemail functionality.
void ast_vm_unregister(const char *module_name)
Unregister the specified voicemail provider.
Definition: main/app.c:400
int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_args, int ignore_hangup)
Run a subroutine on a channel, placing an optional second channel into autoservice.
Definition: main/app.c:297
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
Definition: astobj2.h:901
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Process the audio frame for silence.
Definition: dsp.c:1488
struct ast_group_info * ast_app_group_list_head(void)
Get the head of the group count list.
Definition: main/app.c:2346
Structure used for ast_copy_recording_to_vm in order to cleanly supply data needed for making the rec...
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Definition: mod_format.h:101
char * ast_get_encoded_str(const char *stream, char *result, size_t result_size)
Decode a stream of encoded control or extended ASCII characters.
Definition: main/app.c:3162
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3162
int __ast_vm_register(const struct ast_vm_functions *vm_table, struct ast_module *module)
Set voicemail function callbacks.
Definition: main/app.c:368
int dtimeoutms
Definition: pbx.h:215
int ast_safe_fork(int stop_reaper)
Common routine to safely fork without a chance of a signal handler firing badly in the child...
Definition: main/app.c:3207
static int has_voicemail(const char *mailbox, const char *folder)
Determines if the given folder has messages.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
void ast_str_update(struct ast_str *buf)
Update the length of the buffer, after using ast_str merely as a buffer.
Definition: strings.h:703
#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
int ast_vm_is_registered(void)
Determine if a voicemail provider is registered.
Definition: main/app.c:357
int ast_app_parse_options64(const struct ast_app_option *options, struct ast_flags64 *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:3071
int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
Writes a frame to a stream.
Definition: file.c:244
char * ast_read_textfile(const char *filename)
Read a file into asterisk.
Definition: main/app.c:2949
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1840
int ast_control_streamfile_lang(struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *suspend, const char *restart, int skipms, const char *lang, long *offsetms)
Version of ast_control_streamfile() which allows the language of the media file to be specified...
Definition: main/app.c:1473
Data structure associated with a single frame of data.
int ast_app_group_list_unlock(void)
Unlock the group count list.
Definition: main/app.c:2351
struct ast_filestream * ast_readfile(const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
Starts reading from a file.
Definition: file.c:1371
unsigned int module_version
The version of this function table.
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
Definition: indications.c:302
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
Definition: file.c:1146
int ast_app_copy_recording_to_vm(struct ast_vm_recording_data *vm_rec_data)
param[in] vm_rec_data Contains data needed to make the recording. retval 0 voicemail successfully cre...
Definition: main/app.c:596
const char * data
Description of a tone.
Definition: indications.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
enum ast_frame_type frametype
enum ast_getdata_result ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout)
Plays a stream and gets DTMF data from a channel.
Definition: main/app.c:188
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
Definition: channel.c:6558
struct ast_format * format
int ast_record_review(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, const char *path)
Allow to record message and have a review option.
Definition: main/app.c:2646
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Definition: dsp.c:2009
Asterisk module definitions.
int ast_ivr_menu_run(struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata)
Runs an IVR menu.
Definition: main/app.c:2942
Voicemail function table definition.
#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
AST_LOCK_TYPE
Type of locking to use in ast_lock_path / ast_unlock_path.
struct ast_frame * ast_read_noaudio(struct ast_channel *chan)
Reads a frame, returning AST_FRAME_NULL frame if audio.
Definition: channel.c:4267
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
const char *(* expand_sub_args)(struct ast_channel *chan, const char *args)
Add missing context/exten to Gosub application argument string.
int ast_senddigit_mf(struct ast_channel *chan, char digit, unsigned int duration, unsigned int durationkp, unsigned int durationst, int is_external)
Send an MF digit to a channel.
Definition: channel.c:4952
int ast_get_encoded_char(const char *stream, char *result, size_t *consumed)
Decode an encoded control or extended ASCII character.
Definition: main/app.c:3087
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:222
int ast_waitstream_fr_w_cb(struct ast_channel *c, const char *breakon, const char *forward, const char *rewind, int ms, ast_waitstream_fr_cb cb)
Same as waitstream_fr but allows a callback to be alerted when a user fastforwards or rewinds the fil...
Definition: file.c:1798
Media Format Cache API.
int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration)
Send a string of DTMF digits to a channel.
Definition: main/app.c:1127
#define AST_MAX_FORMATS
Definition: file.h:44
int rtimeoutms
Definition: pbx.h:216
enum AST_LOCK_RESULT ast_lock_path(const char *path)
Lock a filesystem path.
Definition: main/app.c:2614