]> git.ipfire.org Git - thirdparty/freeswitch.git/blob - src/mod/applications/mod_dptools/mod_dptools.c
[core,miniupnpc,modules] Fix not used variables
[thirdparty/freeswitch.git] / src / mod / applications / mod_dptools / mod_dptools.c
1 /*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2020, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
19 * The Initial Developer of the Original Code is
20 * Anthony Minessale II <anthm@freeswitch.org>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Anthony Minessale II <anthm@freeswitch.org>
27 * Ken Rice <krice@freeswitch.org>
28 * Michael Murdock <mike at mmurdock dot org>
29 * Neal Horman <neal at wanlink dot com>
30 * Bret McDanel <trixter AT 0xdecafbad dot com>
31 * Luke Dashjr <luke@openmethods.com> (OpenMethods, LLC)
32 * Cesar Cepeda <cesar@auronix.com>
33 * Christopher M. Rienzo <chris@rienzo.com>
34 * Seven Du <dujinfang@gmail.com>
35 * William King <william.king@quentustech.com>
36 *
37 * mod_dptools.c -- Raw Audio File Streaming Application Module
38 *
39 */
40 #include <switch.h>
41
42 SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load);
43 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_dptools_shutdown);
44 SWITCH_MODULE_DEFINITION(mod_dptools, mod_dptools_load, mod_dptools_shutdown, NULL);
45
46 SWITCH_STANDARD_DIALPLAN(inline_dialplan_hunt)
47 {
48 switch_caller_extension_t *extension = NULL;
49 char *argv[128] = { 0 };
50 int argc;
51 switch_channel_t *channel = switch_core_session_get_channel(session);
52 int x = 0;
53 char *lbuf;
54 char *target = arg;
55 char delim = ',';
56
57 if (!caller_profile) {
58 caller_profile = switch_channel_get_caller_profile(channel);
59 }
60
61 if ((extension = switch_caller_extension_new(session, "inline", "inline")) == 0) {
62 abort();
63 }
64
65 if (zstr(target)) {
66 target = caller_profile->destination_number;
67 }
68
69
70 if (zstr(target)) {
71 return NULL;
72 } else {
73 lbuf = switch_core_session_strdup(session, target);
74 }
75
76 if (*lbuf == 'm' && *(lbuf + 1) == ':' && *(lbuf + 3) == ':') {
77 delim = *(lbuf + 2);
78 lbuf += 4;
79 }
80
81 argc = switch_separate_string(lbuf, delim, argv, (sizeof(argv) / sizeof(argv[0])));
82
83 for (x = 0; x < argc; x++) {
84 char *app = argv[x];
85 char *data = strchr(app, ':');
86
87 if (data) {
88 *data++ = '\0';
89 }
90
91 while (*app == ' ') {
92 app++;
93 }
94
95 switch_caller_extension_add_application(session, extension, app, data);
96 }
97
98 caller_profile->destination_number = (char *) caller_profile->rdnis;
99 caller_profile->rdnis = SWITCH_BLANK_STRING;
100
101 return extension;
102 }
103
104 struct action_binding {
105 char *realm;
106 char *input;
107 char *string;
108 char *value;
109 switch_digit_action_target_t target;
110 switch_core_session_t *session;
111 };
112
113 static switch_status_t digit_nomatch_action_callback(switch_ivr_dmachine_match_t *match)
114 {
115 switch_core_session_t *session = (switch_core_session_t *) match->user_data;
116 switch_channel_t *channel;
117 switch_event_t *event;
118 switch_core_session_t *use_session = session;
119
120 if (switch_ivr_dmachine_get_target(match->dmachine) == DIGIT_TARGET_PEER) {
121 if (switch_core_session_get_partner(session, &use_session) != SWITCH_STATUS_SUCCESS) {
122 use_session = session;
123 }
124 }
125
126 channel = switch_core_session_get_channel(use_session);
127
128
129 switch_channel_set_variable(channel, "last_non_matching_digits", match->match_digits);
130
131 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(use_session), SWITCH_LOG_DEBUG, "%s Digit NOT match binding [%s]\n",
132 switch_channel_get_name(channel), match->match_digits);
133
134 if (switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
135 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "digits", match->match_digits);
136
137 if (switch_core_session_queue_event(use_session, &event) != SWITCH_STATUS_SUCCESS) {
138 switch_event_destroy(&event);
139 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(use_session), SWITCH_LOG_WARNING, "%s event queue failure.\n",
140 switch_core_session_get_name(use_session));
141 }
142 }
143
144 /* send it back around and skip the dmachine */
145 switch_channel_queue_dtmf_string(channel, match->match_digits);
146
147 if (use_session != session) {
148 switch_core_session_rwunlock(use_session);
149 }
150
151
152 return SWITCH_STATUS_SUCCESS;
153 }
154
155 static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match)
156 {
157 struct action_binding *act = (struct action_binding *) match->user_data;
158 switch_event_t *event;
159 int exec = 0;
160 int api = 0;
161 char *string = NULL;
162 switch_channel_t *channel;
163 switch_core_session_t *use_session = act->session;
164 char *flags = "";
165
166 if (act->target == DIGIT_TARGET_PEER || act->target == DIGIT_TARGET_BOTH) {
167 if (switch_core_session_get_partner(act->session, &use_session) != SWITCH_STATUS_SUCCESS) {
168 use_session = act->session;
169 }
170 }
171
172 top:
173
174 string = switch_core_session_strdup(use_session, act->string);
175 exec = 0;
176 api = 0;
177
178 channel = switch_core_session_get_channel(use_session);
179
180 switch_channel_set_variable(channel, "last_matching_digits", match->match_digits);
181
182
183 if (switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
184 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(act->session), SWITCH_LOG_DEBUG, "%s Digit match binding [%s][%s]\n",
185 switch_channel_get_name(channel), act->string, act->value);
186
187 if (!strncasecmp(string, "exec", 4)) {
188 char *e;
189
190 string += 4;
191 if (*string == ':') {
192 string++;
193 exec = 1;
194 } else if (*string == '[') {
195 flags = string;
196 if ((e = switch_find_end_paren(flags, '[', ']'))) {
197 if (*++e == ':') {
198 flags++;
199 *e++ = '\0';
200 string = e;
201 exec = strchr(flags, 'i') ? 2 : 1;
202 }
203 }
204 }
205 } else if (!strncasecmp(string, "api:", 4)) {
206 string += 4;
207 api = 1;
208 }
209
210 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, string, act->value);
211 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "digits", match->match_digits);
212
213 if (exec) {
214 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute", exec == 1 ? "non-blocking" : "blocking");
215 }
216
217 if (switch_core_session_queue_event(use_session, &event) != SWITCH_STATUS_SUCCESS) {
218 switch_event_destroy(&event);
219 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(use_session), SWITCH_LOG_WARNING, "%s event queue failure.\n",
220 switch_core_session_get_name(use_session));
221 }
222 }
223
224 if (exec) {
225 if (exec == 2) {
226 switch_core_session_execute_application(use_session, string, act->value);
227 } else {
228 char *cmd = switch_core_session_sprintf(use_session, "%s::%s", string, act->value);
229 switch_media_flag_enum_t exec_flags = SMF_ECHO_ALEG;
230
231 if (act->target != DIGIT_TARGET_BOTH && !strchr(flags, 'H')) {
232 exec_flags |= SMF_HOLD_BLEG;
233 }
234
235 switch_ivr_broadcast_in_thread(use_session, cmd, exec_flags);
236 }
237 } else if (api) {
238 switch_stream_handle_t stream = { 0 };
239 SWITCH_STANDARD_STREAM(stream);
240 switch_api_execute(string, act->value, NULL, &stream);
241 if (stream.data) {
242 switch_channel_set_variable(channel, "bind_digit_action_api_result", (char *)stream.data);
243 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(act->session), SWITCH_LOG_DEBUG, "%s Digit match binding [%s][%s] api executed, %s\n",
244 switch_core_session_get_name(use_session), act->string, act->value, (char *)stream.data);
245 } else {
246 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(act->session), SWITCH_LOG_DEBUG, "%s Digit match binding [%s][%s] api executed\n",
247 switch_core_session_get_name(use_session), act->string, act->value);
248 }
249 switch_safe_free(stream.data);
250 }
251
252
253 if (use_session != act->session) {
254 switch_core_session_rwunlock(use_session);
255
256 if (act->target == DIGIT_TARGET_BOTH) {
257 use_session = act->session;
258 goto top;
259 }
260 }
261
262 return SWITCH_STATUS_SUCCESS;
263 }
264
265 static switch_digit_action_target_t str2target(const char *target_str)
266 {
267 if (!strcasecmp(target_str, "peer")) {
268 return DIGIT_TARGET_PEER;
269 }
270
271 if (!strcasecmp(target_str, "both")) {
272 return DIGIT_TARGET_BOTH;
273 }
274
275 return DIGIT_TARGET_SELF;
276 }
277
278 #define CLEAR_DIGIT_ACTION_USAGE "<realm>|all[,target]"
279 SWITCH_STANDARD_APP(clear_digit_action_function)
280 {
281 //switch_channel_t *channel = switch_core_session_get_channel(session);
282 switch_ivr_dmachine_t *dmachine;
283 char *realm = NULL;
284 char *target_str;
285 switch_digit_action_target_t t, target = DIGIT_TARGET_SELF;
286
287 if (zstr((char *)data)) {
288 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "clear_digit_action called with no args");
289 return;
290 }
291
292 realm = switch_core_session_strdup(session, data);
293
294 if ((target_str = strchr(realm, ','))) {
295 *target_str++ = '\0';
296 target = str2target(target_str);
297 }
298
299 clear_next:
300 if (target == DIGIT_TARGET_BOTH) {
301 t = DIGIT_TARGET_PEER;
302 } else {
303 t = target;
304 }
305
306 if ((dmachine = switch_core_session_get_dmachine(session, t))) {
307 if (zstr(realm) || !strcasecmp(realm, "all")) {
308 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Digit parser %s: Clearing all realms\n", switch_ivr_dmachine_get_name(dmachine));
309 switch_core_session_set_dmachine(session, NULL, t);
310 switch_ivr_dmachine_destroy(&dmachine);
311 } else {
312 switch_ivr_dmachine_clear_realm(dmachine, realm);
313 }
314 }
315
316 if (target == DIGIT_TARGET_BOTH) {
317 target = DIGIT_TARGET_SELF;
318 goto clear_next;
319 }
320 }
321
322 #define DIGIT_ACTION_SET_REALM_USAGE "<realm>[,<target>]"
323 SWITCH_STANDARD_APP(digit_action_set_realm_function)
324 {
325 switch_ivr_dmachine_t *dmachine;
326 char *realm = switch_core_session_strdup(session, data);
327 char *target_str;
328 switch_digit_action_target_t target = DIGIT_TARGET_SELF;
329
330 if ((target_str = strchr(realm, ','))) {
331 *target_str++ = '\0';
332 target = str2target(target_str);
333 }
334
335 if (zstr(data)) {
336 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", DIGIT_ACTION_SET_REALM_USAGE);
337 return;
338 }
339
340
341 if ((dmachine = switch_core_session_get_dmachine(session, target))) {
342 switch_ivr_dmachine_set_realm(dmachine, realm);
343 }
344
345 }
346
347
348 static void bind_to_session(switch_core_session_t *session,
349 const char *arg0, const char *arg1, const char *arg2, const char *arg3,
350 switch_digit_action_target_t target, switch_digit_action_target_t bind_target)
351 {
352 struct action_binding *act;
353 switch_ivr_dmachine_t *dmachine;
354 switch_channel_t *channel = switch_core_session_get_channel(session);
355 const char *terminators = NULL;
356 switch_byte_t is_priority = 0;
357
358 if (!(dmachine = switch_core_session_get_dmachine(session, target))) {
359 uint32_t digit_timeout = 1500;
360 uint32_t input_timeout = 0;
361 const char *var;
362
363 if ((var = switch_channel_get_variable(channel, "bind_digit_digit_timeout"))) {
364 digit_timeout = switch_atoul(var);
365 }
366
367 if ((var = switch_channel_get_variable(channel, "bind_digit_input_timeout"))) {
368 input_timeout = switch_atoul(var);
369 }
370
371 switch_ivr_dmachine_create(&dmachine, "DPTOOLS", NULL, digit_timeout, input_timeout, NULL, digit_nomatch_action_callback, session);
372 switch_core_session_set_dmachine(session, dmachine, target);
373 }
374
375
376 act = switch_core_session_alloc(session, sizeof(*act));
377 act->realm = switch_core_session_strdup(session, arg0);
378 act->input = switch_core_session_strdup(session, arg1);
379 act->string = switch_core_session_strdup(session, arg2);
380 act->value = switch_core_session_strdup(session, arg3);
381 act->target = bind_target;
382 act->session = session;
383
384 if (!strncasecmp(act->string, "exec", 4) || !strncasecmp(act->string, "api:", 4)) {
385 char *flags, *e;
386 char *string = switch_core_session_strdup(session, act->string);
387
388 string += 4;
389 if (*string == '[') {
390 flags = string;
391 if ((e = switch_find_end_paren(flags, '[', ']'))) {
392 if (*(e+1) == ':') {
393 flags++;
394 *e = '\0';
395 if (strchr(flags, 'P'))
396 is_priority = 1;
397 }
398 }
399 }
400 }
401
402 switch_ivr_dmachine_bind(dmachine, act->realm, act->input, is_priority, 0, digit_action_callback, act);
403
404 if ((terminators = switch_channel_get_variable(channel, "bda_terminators"))) {
405 switch_ivr_dmachine_set_terminators(dmachine, terminators);
406 }
407 }
408
409 #define BIND_DIGIT_ACTION_USAGE "<realm>,<digits|~regex>,<string>[,<value>][,<dtmf target leg>][,<event target leg>]"
410 SWITCH_STANDARD_APP(bind_digit_action_function)
411 {
412
413 char *mydata;
414 int argc = 0;
415 char *argv[6] = { 0 };
416 switch_digit_action_target_t target, bind_target;
417 char *target_str = "self", *bind_target_str = "self";
418 char *value = "";
419
420 if (zstr(data)) {
421 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", BIND_DIGIT_ACTION_USAGE);
422 return;
423 }
424
425 mydata = switch_core_session_strdup(session, data);
426
427 argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0])));
428
429 if (argc < 3 || zstr(argv[0]) || zstr(argv[1]) || zstr(argv[2])) {
430 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", BIND_DIGIT_ACTION_USAGE);
431 return;
432 }
433
434 if (argv[3]) {
435 value = argv[3];
436 }
437
438 if (argv[4]) {
439 target_str = argv[4];
440 }
441
442 if (argv[5]) {
443 bind_target_str = argv[5];
444 }
445
446 target = str2target(target_str);
447 bind_target = str2target(bind_target_str);
448
449
450 switch(target) {
451 case DIGIT_TARGET_PEER:
452 bind_to_session(session, argv[0], argv[1], argv[2], value, DIGIT_TARGET_PEER, bind_target);
453 break;
454 case DIGIT_TARGET_BOTH:
455 bind_to_session(session, argv[0], argv[1], argv[2], value, DIGIT_TARGET_PEER, bind_target);
456 bind_to_session(session, argv[0], argv[1], argv[2], value, DIGIT_TARGET_SELF, bind_target);
457 break;
458 default:
459 bind_to_session(session, argv[0], argv[1], argv[2], value, DIGIT_TARGET_SELF, bind_target);
460 break;
461 }
462 }
463
464 #define DETECT_SPEECH_SYNTAX "<mod_name> <gram_name> <gram_path> [<addr>] OR grammar <gram_name> [<path>] OR nogrammar <gram_name> OR grammaron/grammaroff <gram_name> OR grammarsalloff OR pause OR resume OR start_input_timers OR stop OR param <name> <value>"
465 SWITCH_STANDARD_APP(detect_speech_function)
466 {
467 char *argv[4];
468 int argc;
469 char *lbuf = NULL;
470
471 if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
472 && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
473 if (!strcasecmp(argv[0], "grammar") && argc >= 1) {
474 switch_ivr_detect_speech_load_grammar(session, argv[1], argv[2]);
475 } else if (!strcasecmp(argv[0], "nogrammar")) {
476 switch_ivr_detect_speech_unload_grammar(session, argv[1]);
477 } else if (!strcasecmp(argv[0], "grammaron")) {
478 switch_ivr_detect_speech_enable_grammar(session, argv[1]);
479 } else if (!strcasecmp(argv[0], "grammaroff")) {
480 switch_ivr_detect_speech_disable_grammar(session, argv[1]);
481 } else if (!strcasecmp(argv[0], "grammarsalloff")) {
482 switch_ivr_detect_speech_disable_all_grammars(session);
483 } else if (!strcasecmp(argv[0], "init")) {
484 switch_ivr_detect_speech_init(session, argv[1], argv[2], NULL);
485 } else if (!strcasecmp(argv[0], "pause")) {
486 switch_ivr_pause_detect_speech(session);
487 } else if (!strcasecmp(argv[0], "resume")) {
488 switch_ivr_resume_detect_speech(session);
489 } else if (!strcasecmp(argv[0], "stop")) {
490 switch_ivr_stop_detect_speech(session);
491 } else if (!strcasecmp(argv[0], "param")) {
492 switch_ivr_set_param_detect_speech(session, argv[1], argv[2]);
493 } else if (!strcasecmp(argv[0], "start-input-timers")) {
494 switch_ivr_detect_speech_start_input_timers(session);
495 } else if (!strcasecmp(argv[0], "start_input_timers")) {
496 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "start_input_timers is deprecated, please use start-input-timers instead!\n");
497 switch_ivr_detect_speech_start_input_timers(session);
498 } else if (argc >= 3) {
499 switch_ivr_detect_speech(session, argv[0], argv[1], argv[2], argv[3], NULL);
500 }
501 } else {
502 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", DETECT_SPEECH_SYNTAX);
503 }
504 }
505
506 #define PLAY_AND_DETECT_SPEECH_SYNTAX "<file> detect:<engine> {param1=val1,param2=val2}<grammar>"
507 SWITCH_STANDARD_APP(play_and_detect_speech_function)
508 {
509 switch_channel_t *channel = switch_core_session_get_channel(session);
510 char *argv[2];
511 char *lbuf = NULL;
512 const char *response = "DONE";
513 char *detect = NULL;
514 char *s;
515
516 switch_channel_set_variable(channel, "detect_speech_result", "");
517
518 if (zstr(data) || !(lbuf = switch_core_session_strdup(session, data)) || !(detect = strstr(lbuf, "detect:"))) {
519 /* bad input */
520 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", PLAY_AND_DETECT_SPEECH_SYNTAX);
521 response = "USAGE ERROR";
522 goto done;
523 }
524
525 /* trim any trailing space */
526 s = detect;
527 while (--s >= lbuf && switch_isspace(*s)) {
528 *s = '\0';
529 }
530
531 /* split input at "detect:" */
532 detect[0] = '\0';
533 detect += 7;
534 if (zstr(detect)) {
535 /* bad input */
536 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", PLAY_AND_DETECT_SPEECH_SYNTAX);
537 response = "USAGE ERROR";
538 goto done;
539 }
540
541 /* need to have at 2 parameters for detect */
542 if (switch_separate_string(detect, ' ', argv, (sizeof(argv) / sizeof(argv[0]))) == 2) {
543 char *file = lbuf;
544 char *engine = argv[0];
545 char *grammar = argv[1];
546 char *result = NULL;
547 switch_status_t status = switch_ivr_play_and_detect_speech(session, file, engine, grammar, &result, 0, NULL);
548 if (status == SWITCH_STATUS_SUCCESS) {
549 if (!zstr(result)) {
550 switch_channel_set_variable(channel, "detect_speech_result", result);
551 }
552 } else if (status == SWITCH_STATUS_GENERR) {
553 response = "GRAMMAR ERROR";
554 } else if (status == SWITCH_STATUS_NOT_INITALIZED) {
555 response = "ASR INIT ERROR";
556 } else {
557 response = "ERROR";
558 }
559 } else {
560 /* bad input */
561 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", PLAY_AND_DETECT_SPEECH_SYNTAX);
562 response = "USAGE ERROR";
563 }
564
565 done:
566 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, response);
567 }
568
569 #define SCHED_HEARTBEAT_SYNTAX "[0|<seconds>]"
570 SWITCH_STANDARD_APP(sched_heartbeat_function)
571 {
572 int seconds = 0;
573
574 if (data) {
575 seconds = atoi(data);
576 if (seconds >= 0) {
577 switch_core_session_sched_heartbeat(session, seconds);
578 return;
579 }
580 }
581
582 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", SCHED_HEARTBEAT_SYNTAX);
583
584 }
585
586 #define FILTER_CODECS_SYNTAX "<codec string>"
587 SWITCH_STANDARD_APP(filter_codecs_function)
588 {
589 const char *r_sdp;
590 switch_channel_t *channel = switch_core_session_get_channel(session);
591
592
593 r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
594
595 if (data && r_sdp) {
596 switch_core_media_merge_sdp_codec_string(session, r_sdp, SDP_TYPE_REQUEST, data);
597 switch_channel_set_variable(channel, "filter_codec_string", data);
598 } else {
599 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Incomplete data\n");
600 }
601 }
602
603
604 #define HEARTBEAT_SYNTAX "[0|<seconds>]"
605 SWITCH_STANDARD_APP(heartbeat_function)
606 {
607 int seconds = 0;
608
609 if (data) {
610 seconds = atoi(data);
611 if (seconds >= 0) {
612
613 switch_core_session_enable_heartbeat(session, seconds);
614 return;
615 }
616 }
617
618 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", HEARTBEAT_SYNTAX);
619
620 }
621
622
623 #define KEEPALIVE_SYNTAX "[0|<seconds>]"
624 SWITCH_STANDARD_APP(keepalive_function)
625 {
626 int seconds = 0;
627
628 if (data) {
629 seconds = atoi(data);
630 if (seconds >= 0) {
631 switch_core_session_message_t msg = { 0 };
632
633 msg.message_id = SWITCH_MESSAGE_INDICATE_KEEPALIVE;
634 msg.numeric_arg = seconds;
635 switch_core_session_receive_message(session, &msg);
636
637 switch_core_session_enable_heartbeat(session, seconds);
638 return;
639 }
640 }
641
642 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", HEARTBEAT_SYNTAX);
643
644 }
645
646 #define EXE_SYNTAX "<extension> <dialplan> <context>"
647 SWITCH_STANDARD_APP(exe_function)
648 {
649 char *argv[4] = { 0 };
650 char *lbuf = NULL;
651
652 if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
653 && switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) {
654 switch_core_session_execute_exten(session, argv[0], argv[1], argv[2]);
655 } else {
656 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", EXE_SYNTAX);
657 }
658 }
659
660 #define MKDIR_SYNTAX "<path>"
661 SWITCH_STANDARD_APP(mkdir_function)
662 {
663 switch_dir_make_recursive(data, SWITCH_DEFAULT_DIR_PERMS, switch_core_session_get_pool(session));
664 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s MKDIR: %s\n",
665 switch_channel_get_name(switch_core_session_get_channel(session)), data);
666 }
667 #define RENAME_SYNTAX "<from_path> <to_path>"
668 SWITCH_STANDARD_APP(rename_function)
669 {
670 char *argv[2] = { 0 };
671 char *lbuf = NULL;
672
673 if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
674 && switch_split(lbuf, ' ', argv) == 2) {
675
676 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s RENAME: %s %s\n",
677 switch_channel_get_name(switch_core_session_get_channel(session)), argv[0], argv[1]);
678
679 if (switch_file_rename(argv[0], argv[1], switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
680 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Can't rename %s to %s\n",
681 switch_channel_get_name(switch_core_session_get_channel(session)), argv[0], argv[1]);
682 }
683
684 } else {
685 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", RENAME_SYNTAX);
686 }
687 }
688
689 #define TRANSFER_VARS_SYNTAX "<~variable_prefix|variable>"
690 SWITCH_STANDARD_APP(transfer_vars_function)
691 {
692 char *argv[1] = { 0 };
693 char *lbuf = NULL;
694
695 if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
696 && switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))) >= 1) {
697 switch_core_session_t *nsession = NULL;
698
699 switch_core_session_get_partner(session, &nsession);
700
701 if (nsession) {
702 switch_ivr_transfer_variable(session, nsession, argv[0]);
703 switch_core_session_rwunlock(nsession);
704 } else {
705 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", TRANSFER_VARS_SYNTAX);
706 }
707 }
708 }
709
710 #define SOFT_HOLD_SYNTAX "<unhold key> [<moh_a>] [<moh_b>]"
711 SWITCH_STANDARD_APP(soft_hold_function)
712 {
713 char *argv[3] = { 0 };
714 char *lbuf = NULL;
715
716 if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
717 && switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))) >= 1) {
718 switch_ivr_soft_hold(session, argv[0], argv[1], argv[2]);
719 } else {
720 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", SOFT_HOLD_SYNTAX);
721 }
722 }
723
724 SWITCH_STANDARD_APP(dtmf_unblock_function)
725 {
726 switch_ivr_unblock_dtmf_session(session);
727 }
728
729 SWITCH_STANDARD_APP(media_reset_function)
730 {
731 switch_channel_t *channel = switch_core_session_get_channel(session);
732 const char *name = switch_channel_get_name(channel);
733
734 if (switch_channel_media_ready(channel)) {
735 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s This function does not work once media has been established.\n", name);
736 return;
737 }
738
739 switch_channel_clear_flag(channel, CF_PROXY_MODE);
740 switch_channel_clear_flag(channel, CF_PROXY_MEDIA);
741 switch_channel_set_variable(channel, "bypass_media", NULL);
742 switch_channel_set_variable(channel, "proxy_media", NULL);
743
744 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "%sReset MEDIA flags.\n", name);
745 }
746
747 SWITCH_STANDARD_APP(dtmf_block_function)
748 {
749 switch_ivr_block_dtmf_session(session);
750 }
751
752 #define UNBIND_SYNTAX "[<key>]"
753 SWITCH_STANDARD_APP(dtmf_unbind_function)
754 {
755 char *key = (char *) data;
756 int kval = 0;
757
758 if (key) {
759 kval = switch_dtmftoi(key);
760 }
761
762 switch_ivr_unbind_dtmf_meta_session(session, kval);
763
764 }
765
766 #define BIND_SYNTAX "<key> [a|b|ab] [a|b|o|s|i|1] <app>"
767 SWITCH_STANDARD_APP(dtmf_bind_function)
768 {
769 char *argv[4] = { 0 };
770 char *lbuf = NULL;
771
772 if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
773 && switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))) == 4) {
774 int kval = switch_dtmftoi(argv[0]);
775 switch_bind_flag_t bind_flags = 0;
776
777 if (strchr(argv[1], 'a')) {
778 bind_flags |= SBF_DIAL_ALEG;
779 }
780
781 if (strchr(argv[1], 'b')) {
782 bind_flags |= SBF_DIAL_BLEG;
783 }
784
785 if (strchr(argv[2], 'a')) {
786 if ((bind_flags & SBF_EXEC_BLEG)) {
787 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot bind execute to multiple legs\n");
788 } else {
789 bind_flags |= SBF_EXEC_ALEG;
790 }
791 }
792
793 if (strchr(argv[2], 'b')) {
794 if ((bind_flags & SBF_EXEC_ALEG)) {
795 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot bind execute to multiple legs\n");
796 } else {
797 bind_flags |= SBF_EXEC_BLEG;
798 }
799 }
800
801 if (strchr(argv[2], 'a')) {
802 if ((bind_flags & SBF_EXEC_BLEG)) {
803 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot bind execute to multiple legs\n");
804 } else {
805 bind_flags |= SBF_EXEC_ALEG;
806 }
807 }
808
809 if (strchr(argv[2], 'i')) {
810 bind_flags |= SBF_EXEC_INLINE;
811 }
812
813 if (strchr(argv[2], 'o')) {
814 if ((bind_flags & SBF_EXEC_BLEG) || (bind_flags & SBF_EXEC_ALEG) || (bind_flags & SBF_EXEC_SAME)) {
815 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot bind execute to multiple legs\n");
816 } else {
817 bind_flags |= SBF_EXEC_OPPOSITE;
818 }
819 }
820
821 if (strchr(argv[2], 's')) {
822 if ((bind_flags & SBF_EXEC_BLEG) || (bind_flags & SBF_EXEC_ALEG) || (bind_flags & SBF_EXEC_SAME)) {
823 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot bind execute to multiple legs\n");
824 } else {
825 bind_flags |= SBF_EXEC_SAME;
826 }
827 }
828
829 if (strchr(argv[2], '1')) {
830 bind_flags |= SBF_ONCE;
831 }
832
833 if (switch_ivr_bind_dtmf_meta_session(session, kval, bind_flags, argv[3]) != SWITCH_STATUS_SUCCESS) {
834 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Bind Error!\n");
835 }
836 } else {
837 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", BIND_SYNTAX);
838 }
839 }
840
841 #define INTERCEPT_SYNTAX "[-bleg] <uuid>"
842 SWITCH_STANDARD_APP(intercept_function)
843 {
844 char *argv[4] = { 0 };
845 char *mydata;
846 char *uuid;
847 switch_bool_t bleg = SWITCH_FALSE;
848
849 if (!zstr(data) && (mydata = switch_core_session_strdup(session, data))) {
850 if (switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))) >= 1) {
851 if (!strcasecmp(argv[0], "-bleg")) {
852 if (argv[1]) {
853 uuid = argv[1];
854 bleg = SWITCH_TRUE;
855 } else {
856 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", INTERCEPT_SYNTAX);
857 return;
858 }
859 } else {
860 uuid = argv[0];
861 }
862
863 switch_ivr_intercept_session(session, uuid, bleg);
864 }
865 return;
866 }
867
868 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", INTERCEPT_SYNTAX);
869 }
870
871 #define MAX_SPY 3000
872 struct e_data {
873 char *uuid_list[MAX_SPY];
874 int total;
875 };
876
877 static int e_callback(void *pArg, int argc, char **argv, char **columnNames)
878 {
879 char *uuid = argv[0];
880 struct e_data *e_data = (struct e_data *) pArg;
881
882 if (uuid && e_data) {
883 e_data->uuid_list[e_data->total++] = strdup(uuid);
884 return 0;
885 }
886
887 return 1;
888 }
889
890 #define native_eavesdrop_SYNTAX "<uuid> [read|write]"
891 SWITCH_STANDARD_APP(native_eavesdrop_function)
892 {
893 switch_eavesdrop_flag_t flags = ED_TAP_READ;
894 char *argv[2] = { 0 };
895 int argc = 0;
896 char *mydata;
897
898
899 if (zstr(data)) {
900 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "INVALID ARGS usage (%s)\n", native_eavesdrop_SYNTAX);
901 return;
902 }
903
904 mydata = switch_core_session_strdup(session, data);
905 argc = switch_split(mydata, ' ', argv);
906
907 if (argc > 1) {
908 if (switch_stristr("read", argv[1])) {
909 flags |= ED_TAP_READ;
910 } else if (switch_stristr("write", argv[1])) {
911 flags |= ED_TAP_WRITE;
912 }
913 }
914
915 switch_ivr_eavesdrop_session(session, argv[0], NULL, flags);
916 }
917
918
919 #define eavesdrop_SYNTAX "[all | <uuid>]"
920 SWITCH_STANDARD_APP(eavesdrop_function)
921 {
922 if (zstr(data)) {
923 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", eavesdrop_SYNTAX);
924 } else {
925 switch_eavesdrop_flag_t flags = ED_DTMF;
926 switch_channel_t *channel = switch_core_session_get_channel(session);
927 const char *require_group = switch_channel_get_variable(channel, "eavesdrop_require_group");
928 const char *enable_dtmf = switch_channel_get_variable(channel, "eavesdrop_enable_dtmf");
929 const char *bridge_aleg = switch_channel_get_variable(channel, "eavesdrop_bridge_aleg");
930 const char *bridge_bleg = switch_channel_get_variable(channel, "eavesdrop_bridge_bleg");
931 const char *whisper_aleg = switch_channel_get_variable(channel, "eavesdrop_whisper_aleg");
932 const char *whisper_bleg = switch_channel_get_variable(channel, "eavesdrop_whisper_bleg");
933
934 if (enable_dtmf) {
935 flags = switch_true(enable_dtmf) ? ED_DTMF : ED_NONE;
936 }
937
938 if (switch_true(whisper_aleg)) {
939 flags |= ED_MUX_READ;
940 }
941 if (switch_true(whisper_bleg)) {
942 flags |= ED_MUX_WRITE;
943 }
944
945 /* Defaults to both, if neither is set */
946 if (switch_true(bridge_aleg)) {
947 flags |= ED_BRIDGE_READ;
948 }
949 if (switch_true(bridge_bleg)) {
950 flags |= ED_BRIDGE_WRITE;
951 }
952
953 if (!strcasecmp((char *) data, "all")) {
954 switch_cache_db_handle_t *db = NULL;
955 char *errmsg = NULL;
956 struct e_data e_data = { {0} };
957 char *sql = switch_mprintf("select uuid from channels where uuid != '%q'", switch_core_session_get_uuid(session));
958 const char *file = NULL;
959 int x = 0;
960 char buf[2] = "";
961 switch_size_t buflen = sizeof(buf);
962 char terminator;
963 switch_status_t status;
964
965 while (switch_channel_ready(channel)) {
966 for (x = 0; x < MAX_SPY; x++) {
967 switch_safe_free(e_data.uuid_list[x]);
968 }
969 e_data.total = 0;
970
971 if (switch_core_db_handle(&db) != SWITCH_STATUS_SUCCESS) {
972 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Database Error!\n");
973 break;
974 }
975 switch_cache_db_execute_sql_callback(db, sql, e_callback, &e_data, &errmsg);
976 switch_cache_db_release_db_handle(&db);
977 if (errmsg) {
978 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error: %s\n", errmsg);
979 free(errmsg);
980 if ((file = switch_channel_get_variable(channel, "eavesdrop_indicate_failed"))) {
981 switch_ivr_play_file(session, NULL, file, NULL);
982 }
983 buf[0] = '\0';
984 switch_ivr_collect_digits_count(session, buf, buflen, 1, "*", &terminator, 5000, 0, 0);
985 continue;
986 }
987 if (e_data.total) {
988 for (x = 0; x < e_data.total && switch_channel_ready(channel); x++) {
989 if (!switch_ivr_uuid_exists(e_data.uuid_list[x])) continue;
990
991 /* If we have a group and 1000 concurrent calls, we will flood the logs. This check avoids this */
992 if (!require_group)
993 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Spy: %s\n", e_data.uuid_list[x]);
994 if ((file = switch_channel_get_variable(channel, "eavesdrop_indicate_new"))) {
995 switch_ivr_play_file(session, NULL, file, NULL);
996 }
997 if ((status = switch_ivr_eavesdrop_session(session, e_data.uuid_list[x], require_group, flags)) != SWITCH_STATUS_SUCCESS) {
998 if (status != SWITCH_STATUS_BREAK) {
999 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Spy: %s Failed\n", e_data.uuid_list[x]);
1000 if ((file = switch_channel_get_variable(channel, "eavesdrop_indicate_failed"))) {
1001 switch_ivr_play_file(session, NULL, file, NULL);
1002 }
1003 buf[0] = '\0';
1004 switch_ivr_collect_digits_count(session, buf, buflen, 1, "*", &terminator, 5000, 0, 0);
1005 }
1006 }
1007 }
1008 } else {
1009 if ((file = switch_channel_get_variable(channel, "eavesdrop_indicate_idle"))) {
1010 switch_ivr_play_file(session, NULL, file, NULL);
1011 }
1012 buf[0] = '\0';
1013 switch_ivr_collect_digits_count(session, buf, buflen, 1, "*", &terminator, 2000, 0, 0);
1014 }
1015 }
1016
1017 for (x = 0; x < MAX_SPY; x++) {
1018 switch_safe_free(e_data.uuid_list[x]);
1019 }
1020
1021 free(sql);
1022
1023 } else {
1024 switch_ivr_eavesdrop_session(session, data, require_group, flags);
1025 }
1026 }
1027 }
1028
1029 #define threeway_SYNTAX "<uuid>"
1030 SWITCH_STANDARD_APP(three_way_function)
1031 {
1032 if (zstr(data)) {
1033 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", threeway_SYNTAX);
1034 } else {
1035 switch_ivr_eavesdrop_session(session, data, NULL, ED_MUX_READ | ED_MUX_WRITE);
1036 }
1037 }
1038
1039 #define SET_USER_SYNTAX "<user>@<domain> [prefix]"
1040 SWITCH_STANDARD_APP(set_user_function)
1041 {
1042 switch_ivr_set_user(session, data);
1043 }
1044
1045 #define SET_AUDIO_LEVEL_SYNTAX "[read|write] <vol>"
1046 SWITCH_STANDARD_APP(set_audio_level_function)
1047 {
1048 char *argv[2] = { 0 };
1049 int argc = 0;
1050 char *mydata;
1051 int level = 0;
1052
1053 mydata = switch_core_session_strdup(session, data);
1054 argc = switch_split(mydata, ' ', argv);
1055
1056 if (argc != 2) {
1057 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Error. USAGE: %s\n",
1058 switch_core_session_get_name(session), SET_AUDIO_LEVEL_SYNTAX);
1059 return;
1060 }
1061
1062 level = atoi(argv[1]);
1063
1064 switch_ivr_session_audio(session, "level", argv[0], level);
1065
1066
1067 }
1068
1069 #define SET_MUTE_SYNTAX "[read|write] [[true|cn level]|false]"
1070 SWITCH_STANDARD_APP(set_mute_function)
1071 {
1072 char *argv[2] = { 0 };
1073 int argc = 0;
1074 char *mydata;
1075 int level = 0;
1076
1077 mydata = switch_core_session_strdup(session, data);
1078 argc = switch_split(mydata, ' ', argv);
1079
1080 if (argc != 2) {
1081 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Error. USAGE: %s\n",
1082 switch_core_session_get_name(session), SET_MUTE_SYNTAX);
1083 return;
1084 }
1085
1086 if ((level = atoi(argv[1])) <= 0) {
1087 level = switch_true(argv[1]);
1088 }
1089
1090 switch_ivr_session_audio(session, "mute", argv[0], level);
1091
1092 }
1093
1094 SWITCH_STANDARD_APP(capture_text_function)
1095 {
1096 switch_ivr_capture_text(session, switch_true((char *)data));
1097 }
1098
1099 SWITCH_STANDARD_APP(acknowledge_call_function)
1100 {
1101 switch_channel_acknowledge_call(switch_core_session_get_channel(session));
1102 }
1103
1104 SWITCH_STANDARD_APP(ring_ready_function)
1105 {
1106 if (!zstr(data)) {
1107 if (!strcasecmp(data, "queued")) {
1108 switch_channel_ring_ready_value(switch_core_session_get_channel(session), SWITCH_RING_READY_QUEUED);
1109 return;
1110 }
1111 }
1112
1113 switch_channel_ring_ready(switch_core_session_get_channel(session));
1114 }
1115
1116 SWITCH_STANDARD_APP(remove_bugs_function)
1117 {
1118 const char *function = NULL;
1119
1120 if (!zstr((char *)data)) {
1121 function = data;
1122 }
1123
1124 switch_core_media_bug_remove_all_function(session, function);
1125 }
1126
1127 SWITCH_STANDARD_APP(break_function)
1128 {
1129 switch_channel_t *channel;
1130
1131 channel = switch_core_session_get_channel(session);
1132
1133 if (data && strcasecmp(data, "all")) {
1134 switch_core_session_flush_private_events(session);
1135 }
1136
1137 if (switch_channel_test_flag(channel, CF_BROADCAST)) {
1138 switch_channel_stop_broadcast(channel);
1139 } else {
1140 switch_channel_set_flag(channel, CF_BREAK);
1141 }
1142 }
1143
1144 SWITCH_STANDARD_APP(reuse_caller_profile_function)
1145 {
1146 switch_channel_t *channel;
1147 channel = switch_core_session_get_channel(session);
1148 switch_channel_set_flag(channel, CF_REUSE_CALLER_PROFILE);
1149 }
1150
1151 SWITCH_STANDARD_APP(queue_dtmf_function)
1152 {
1153 switch_channel_queue_dtmf_string(switch_core_session_get_channel(session), (const char *) data);
1154 }
1155
1156 SWITCH_STANDARD_APP(send_dtmf_function)
1157 {
1158 switch_core_session_send_dtmf_string(session, (const char *) data);
1159 }
1160
1161 SWITCH_STANDARD_APP(check_acl_function)
1162 {
1163 int argc;
1164 char *argv[3] = { 0 };
1165 char *mydata;
1166 switch_call_cause_t cause = SWITCH_CAUSE_CALL_REJECTED;
1167
1168 if (!zstr(data) && (mydata = switch_core_session_strdup(session, data))) {
1169 if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) > 1) {
1170 if (!switch_check_network_list_ip(argv[0], argv[1])) {
1171 switch_channel_t *channel = switch_core_session_get_channel(session);
1172 if (argc > 2) {
1173 cause = switch_channel_str2cause(argv[2]);
1174 }
1175 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Call failed acl check for ip %s on list %s\n", argv[0], argv[1]);
1176 switch_channel_hangup(channel, cause);
1177 }
1178 }
1179 }
1180
1181 }
1182
1183 SWITCH_STANDARD_APP(flush_dtmf_function)
1184 {
1185 switch_channel_flush_dtmf(switch_core_session_get_channel(session));
1186 }
1187
1188 SWITCH_STANDARD_APP(transfer_function)
1189 {
1190 char *argv[4] = { 0 };
1191 char *mydata;
1192 int bleg = 0, both = 0;
1193
1194
1195 if (!zstr(data) && (mydata = switch_core_session_strdup(session, data))) {
1196 if (switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))) >= 1) {
1197 bleg = !strcasecmp(argv[0], "-bleg");
1198 both = !strcasecmp(argv[0], "-both");
1199
1200 if (bleg || both) {
1201 const char *uuid;
1202 switch_channel_t *channel = switch_core_session_get_channel(session);
1203 if ((uuid = switch_channel_get_partner_uuid(channel))) {
1204 switch_core_session_t *b_session;
1205 if ((b_session = switch_core_session_locate(uuid))) {
1206 switch_ivr_session_transfer(b_session, argv[1], argv[2], argv[3]);
1207 switch_core_session_rwunlock(b_session);
1208 }
1209 } else {
1210 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "No B-leg present.\n");
1211 }
1212 if (both) {
1213 switch_ivr_session_transfer(session, argv[1], argv[2], argv[3]);
1214 }
1215 } else {
1216 switch_ivr_session_transfer(session, argv[0], argv[1], argv[2]);
1217 }
1218 } else {
1219 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No extension specified.\n");
1220 }
1221 }
1222 }
1223
1224 SWITCH_STANDARD_APP(sched_transfer_function)
1225 {
1226 char *argv[4] = { 0 };
1227 char *mydata;
1228
1229 if (!zstr(data) && (mydata = switch_core_session_strdup(session, data))) {
1230 if (switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))) >= 2) {
1231 time_t when;
1232 uint32_t id;
1233 char ids[80] = "";
1234
1235 if (*argv[0] == '+') {
1236 when = switch_epoch_time_now(NULL) + atol(argv[0] + 1);
1237 } else {
1238 when = atol(argv[0]);
1239 }
1240
1241 id = switch_ivr_schedule_transfer(when, switch_core_session_get_uuid(session), argv[1], argv[2], argv[3]);
1242 snprintf(ids, sizeof(ids), "%u", id);
1243 switch_channel_set_variable(switch_core_session_get_channel(session), "last_sched_id", ids);
1244 } else {
1245 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Args\n");
1246 }
1247 }
1248 }
1249
1250 SWITCH_STANDARD_APP(sched_hangup_function)
1251 {
1252 char *argv[5] = { 0 };
1253 char *mydata;
1254
1255 if (!zstr(data) && (mydata = switch_core_session_strdup(session, data))) {
1256 if (switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))) >= 1) {
1257 time_t when;
1258 switch_call_cause_t cause = SWITCH_CAUSE_ALLOTTED_TIMEOUT;
1259 switch_bool_t bleg = SWITCH_FALSE;
1260 int sec = atol(argv[0] + 1);
1261
1262 if (*argv[0] == '+') {
1263 when = switch_epoch_time_now(NULL) + sec;
1264 } else {
1265 when = atol(argv[0]);
1266 }
1267
1268 if (argv[1]) {
1269 cause = switch_channel_str2cause(argv[1]);
1270 }
1271
1272 if (argv[2] && !strcasecmp(argv[2], "bleg")) {
1273 bleg = SWITCH_TRUE;
1274 }
1275
1276 if (sec == 0) {
1277 switch_channel_hangup(switch_core_session_get_channel(session), cause);
1278 } else {
1279 switch_ivr_schedule_hangup(when, switch_core_session_get_uuid(session), cause, bleg);
1280 }
1281 } else {
1282 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No time specified.\n");
1283 }
1284 }
1285 }
1286
1287 SWITCH_STANDARD_APP(sched_broadcast_function)
1288 {
1289 char *argv[6] = { 0 };
1290 char *mydata;
1291
1292 if (!zstr(data) && (mydata = switch_core_session_strdup(session, data))) {
1293 if (switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))) >= 2) {
1294 time_t when;
1295 switch_media_flag_t flags = SMF_NONE;
1296 uint32_t id;
1297 char ids[80] = "";
1298
1299 if (*argv[0] == '@') {
1300 when = atol(argv[0] + 1);
1301 } else if (*argv[0] == '+') {
1302 when = switch_epoch_time_now(NULL) + atol(argv[0] + 1);
1303 } else {
1304 when = atol(argv[0]);
1305 }
1306
1307 if (argv[2]) {
1308 if (!strcmp(argv[2], "both")) {
1309 flags |= (SMF_ECHO_ALEG | SMF_ECHO_BLEG);
1310 } else if (!strcmp(argv[2], "aleg")) {
1311 flags |= SMF_ECHO_ALEG;
1312 } else if (!strcmp(argv[2], "bleg")) {
1313 flags |= SMF_ECHO_BLEG;
1314 }
1315 } else {
1316 flags |= SMF_ECHO_ALEG;
1317 }
1318
1319 id = switch_ivr_schedule_broadcast(when, switch_core_session_get_uuid(session), argv[1], flags);
1320 snprintf(ids, sizeof(ids), "%u", id);
1321 switch_channel_set_variable(switch_core_session_get_channel(session), "last_sched_id", ids);
1322 } else {
1323 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Args\n");
1324 }
1325 }
1326 }
1327
1328 SWITCH_STANDARD_APP(delay_function)
1329 {
1330 uint32_t len = 0;
1331
1332 if (zstr(data)) {
1333 len = 1000;
1334 } else {
1335 len = atoi(data);
1336 }
1337
1338 switch_ivr_delay_echo(session, len);
1339 }
1340
1341 SWITCH_STANDARD_APP(eval_function)
1342 {
1343 return;
1344 }
1345
1346 SWITCH_STANDARD_APP(set_media_stats_function)
1347 {
1348 switch_core_media_set_stats(session);
1349
1350 return;
1351 }
1352
1353 SWITCH_STANDARD_APP(zombie_function)
1354 {
1355 switch_channel_t *channel = switch_core_session_get_channel(session);
1356
1357 if (switch_channel_up(channel)) {
1358 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s MMM Brains....\n", switch_channel_get_name(channel));
1359 switch_channel_set_flag(channel, CF_ZOMBIE_EXEC);
1360 }
1361
1362 return;
1363 }
1364
1365
1366 SWITCH_STANDARD_APP(hangup_function)
1367 {
1368 switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
1369
1370 if (!zstr(data)) {
1371 cause = switch_channel_str2cause(data);
1372 }
1373
1374 switch_channel_hangup(switch_core_session_get_channel(session), cause);
1375 }
1376
1377 SWITCH_STANDARD_APP(set_name_function)
1378 {
1379
1380 if (!zstr(data)) {
1381 switch_channel_set_name(switch_core_session_get_channel(session), (char *) data);
1382 }
1383 }
1384
1385 SWITCH_STANDARD_APP(answer_function)
1386 {
1387 switch_channel_t *channel = switch_core_session_get_channel(session);
1388 const char *arg = (char *) data;
1389
1390 if (zstr(arg)) {
1391 arg = switch_channel_get_variable(channel, "answer_flags");
1392 }
1393
1394 if (!zstr(arg)) {
1395 if (switch_stristr("is_conference", arg)) {
1396 switch_channel_set_flag(channel, CF_CONFERENCE);
1397 }
1398 if (switch_stristr("decode_video", arg)) {
1399 switch_channel_set_flag_recursive(channel, CF_VIDEO_DECODED_READ);
1400 }
1401 if (switch_stristr("debug_video", arg)) {
1402 switch_channel_set_flag_recursive(channel, CF_VIDEO_DEBUG_READ);
1403 }
1404 }
1405
1406 switch_channel_answer(channel);
1407 }
1408
1409 SWITCH_STANDARD_APP(wait_for_answer_function)
1410 {
1411 switch_channel_t *channel = switch_core_session_get_channel(session);
1412 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Waiting for answer\n");
1413 while (!switch_channel_test_flag(channel, CF_ANSWERED) && switch_channel_ready(channel)) {
1414 switch_ivr_sleep(session, 100, SWITCH_TRUE, NULL);
1415 }
1416 }
1417
1418 #define WAIT_FOR_VIDEO_READY_SYNTAX "[<ms, 1..10000>]"
1419 SWITCH_STANDARD_APP(wait_for_video_ready_function)
1420 {
1421 uint32_t delay = 0, delay_def = 10000;
1422 switch_status_t res;
1423
1424 switch_channel_t *channel = switch_core_session_get_channel(session);
1425
1426 if (zstr(data) || ((delay = atoi(data)) < 1) || (delay > 10000)) {
1427 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "wait_for_video_ready: Invalid Timeout. Use default %d ms.\n", delay_def);
1428 delay = delay_def;
1429 }
1430
1431 if (switch_channel_test_flag(channel, CF_VIDEO)) {
1432 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Starting to wait %d ms until video stream is ready\n", delay);
1433 res = switch_channel_wait_for_flag(channel, CF_VIDEO_READY, SWITCH_TRUE, delay, NULL);
1434 if (res == SWITCH_STATUS_SUCCESS) {
1435 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Video stream is ready\n");
1436 } else if (res == SWITCH_STATUS_TIMEOUT) {
1437 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Video stream is not ready after %d ms. Abort waiting.\n", delay);
1438 } else {
1439 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Error (%d) waiting for video stream to be ready\n", res);
1440 }
1441 } else {
1442 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Cannot wait for video stream on a non video call\n");
1443 }
1444 }
1445
1446 SWITCH_STANDARD_APP(presence_function)
1447 {
1448 char *argv[6] = { 0 };
1449 char *mydata = NULL;
1450 switch_channel_t *channel = switch_core_session_get_channel(session);
1451
1452 if (zstr(data) || !(mydata = switch_core_session_strdup(session, data))) {
1453 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "INVALID ARGS!\n");
1454 return;
1455 }
1456
1457 if (switch_separate_string(mydata, ' ', argv, sizeof(argv) / sizeof(argv[0])) < 2) {
1458 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "INVALID ARGS!\n");
1459 return;
1460 }
1461
1462 switch_channel_presence(channel, argv[0], argv[1], argv[2]);
1463 }
1464
1465 SWITCH_STANDARD_APP(pre_answer_function)
1466 {
1467 switch_channel_t *channel = switch_core_session_get_channel(session);
1468 const char *arg = (char *) data;
1469
1470 if (!zstr(arg)) {
1471 if (switch_stristr("is_conference", arg)) {
1472 switch_channel_set_flag(channel, CF_CONFERENCE);
1473 }
1474 }
1475
1476 switch_channel_pre_answer(channel);
1477 }
1478
1479 SWITCH_STANDARD_APP(redirect_function)
1480 {
1481 switch_core_session_message_t msg = { 0 };
1482
1483 /* Tell the channel to redirect */
1484 msg.from = __FILE__;
1485 msg.string_arg = data;
1486 msg.message_id = SWITCH_MESSAGE_INDICATE_REDIRECT;
1487 msg.numeric_arg = 1;
1488 switch_core_session_receive_message(session, &msg);
1489 }
1490
1491 SWITCH_STANDARD_APP(video_set_decode_function)
1492 {
1493 switch_channel_t *channel = switch_core_session_get_channel(session);
1494 char *txt = (char *) data;
1495 int on = 0, wait = 0;
1496
1497 if (txt) {
1498 on = !strcasecmp(txt, "on");
1499 wait = !strcasecmp(txt, "wait");
1500 }
1501
1502 if (data && (on || wait)) {
1503 switch_channel_set_flag_recursive(channel, CF_VIDEO_DECODED_READ);
1504 if (wait) {
1505 switch_core_session_wait_for_video_input_params(session, 10000);
1506 }
1507 } else {
1508 switch_channel_clear_flag_recursive(channel, CF_VIDEO_DECODED_READ);
1509 }
1510 }
1511
1512 SWITCH_STANDARD_APP(video_refresh_function)
1513 {
1514 switch_core_session_message_t msg = { 0 };
1515 char *cmd = (char *)data;
1516
1517 if (!zstr(cmd)) {
1518 switch_channel_t *channel = switch_core_session_get_channel(session);
1519
1520 if (!strcasecmp(cmd, "manual")) {
1521 switch_channel_set_flag(channel, CF_MANUAL_VID_REFRESH);
1522 } else if (!strcasecmp(cmd, "auto")) {
1523 switch_channel_clear_flag(channel, CF_MANUAL_VID_REFRESH);
1524 }
1525
1526 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
1527 "%s video refresh now in %s mode.\n", switch_channel_get_name(channel),
1528 switch_channel_test_flag(channel, CF_MANUAL_VID_REFRESH) ? "manual" : "auto");
1529
1530 return;
1531 }
1532
1533 /* Tell the channel to refresh video */
1534 msg.from = __FILE__;
1535 msg.numeric_arg = 1;
1536 msg.string_arg = data;
1537 msg.message_id = SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ;
1538 switch_core_session_receive_message(session, &msg);
1539 }
1540
1541 SWITCH_STANDARD_APP(send_info_function)
1542 {
1543 switch_core_session_message_t msg = { 0 };
1544
1545 /* Tell the channel to send info */
1546 msg.from = __FILE__;
1547 msg.string_arg = data;
1548 msg.message_id = SWITCH_MESSAGE_INDICATE_INFO;
1549 msg.string_array_arg[2] = data;
1550
1551 switch_core_session_receive_message(session, &msg);
1552 }
1553
1554 SWITCH_STANDARD_APP(jitterbuffer_function)
1555 {
1556 switch_core_session_message_t msg = { 0 };
1557
1558 /* Tell the channel to change the jitter buffer */
1559 msg.from = __FILE__;
1560 msg.string_arg = data;
1561 msg.message_id = SWITCH_MESSAGE_INDICATE_JITTER_BUFFER;
1562 switch_core_session_receive_message(session, &msg);
1563 }
1564
1565 SWITCH_STANDARD_APP(display_function)
1566 {
1567 switch_core_session_message_t msg = { 0 };
1568
1569 /* Tell the channel to change display */
1570 msg.from = __FILE__;
1571 msg.string_arg = data;
1572 msg.message_id = SWITCH_MESSAGE_INDICATE_DISPLAY;
1573 switch_core_session_receive_message(session, &msg);
1574 }
1575
1576 SWITCH_STANDARD_APP(respond_function)
1577 {
1578 switch_core_session_message_t msg = { 0 };
1579
1580 /* Tell the channel to respond the call */
1581 msg.from = __FILE__;
1582 msg.string_arg = data;
1583 msg.message_id = SWITCH_MESSAGE_INDICATE_RESPOND;
1584 msg.numeric_arg = -1;
1585 switch_core_session_receive_message(session, &msg);
1586 }
1587
1588 SWITCH_STANDARD_APP(deflect_function)
1589 {
1590 switch_core_session_message_t msg = { 0 };
1591 switch_channel_t *channel = switch_core_session_get_channel(session);
1592
1593 switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
1594 /* Tell the channel to deflect the call */
1595 msg.from = __FILE__;
1596 msg.string_arg = data;
1597 msg.message_id = SWITCH_MESSAGE_INDICATE_DEFLECT;
1598 switch_core_session_receive_message(session, &msg);
1599 }
1600
1601 SWITCH_STANDARD_APP(recovery_refresh_function)
1602 {
1603 switch_core_session_message_t msg = { 0 };
1604
1605 /* Tell the channel to recovery_refresh the call */
1606 msg.from = __FILE__;
1607 msg.string_arg = data;
1608 msg.message_id = SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH;
1609 switch_core_session_receive_message(session, &msg);
1610 }
1611
1612
1613 SWITCH_STANDARD_APP(sched_cancel_function)
1614 {
1615 const char *group = data;
1616
1617 if (zstr(group)) {
1618 group = switch_core_session_get_uuid(session);
1619 }
1620
1621 if (switch_is_digit_string(group)) {
1622 int64_t tmp;
1623 tmp = (uint32_t) atoi(group);
1624 if (tmp > 0) {
1625 switch_scheduler_del_task_id((uint32_t) tmp);
1626 }
1627 } else {
1628 switch_scheduler_del_task_group(group);
1629 }
1630 }
1631
1632 static void base_set (switch_core_session_t *session, const char *data, switch_stack_t stack)
1633 {
1634 char *var, *val = NULL;
1635 const char *what = "SET";
1636
1637 switch (stack) {
1638 case SWITCH_STACK_PUSH:
1639 what = "PUSH";
1640 break;
1641 case SWITCH_STACK_UNSHIFT:
1642 what = "UNSHIFT";
1643 break;
1644 default:
1645 break;
1646 }
1647
1648 if (zstr(data)) {
1649 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n");
1650 } else {
1651 switch_channel_t *channel = switch_core_session_get_channel(session);
1652 char *expanded = NULL;
1653
1654 var = switch_core_session_strdup(session, data);
1655
1656 if (!(val = strchr(var, '='))) {
1657 val = strchr(var, ',');
1658 }
1659
1660 if (val) {
1661 *val++ = '\0';
1662 if (zstr(val)) {
1663 val = NULL;
1664 }
1665 }
1666
1667 if (val) {
1668 expanded = switch_channel_expand_variables(channel, val);
1669 }
1670
1671 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s %s [%s]=[%s]\n",
1672 what, switch_channel_get_name(channel), var, expanded ? expanded : "UNDEF");
1673
1674 switch_channel_add_variable_var_check(channel, var, expanded, SWITCH_FALSE, stack);
1675
1676 if (expanded && expanded != val) {
1677 switch_safe_free(expanded);
1678 }
1679 }
1680 }
1681
1682 SWITCH_STANDARD_APP(multiset_function)
1683 {
1684 char delim = ' ';
1685 char *arg = (char *) data;
1686
1687 if (!zstr(arg) && *arg == '^' && *(arg+1) == '^') {
1688 arg += 2;
1689 delim = *arg++;
1690 }
1691
1692 if (arg) {
1693 char *array[256] = {0};
1694 int i, argc;
1695
1696 arg = switch_core_session_strdup(session, arg);
1697 argc = switch_split(arg, delim, array);
1698
1699 for(i = 0; i < argc; i++) {
1700 base_set(session, array[i], SWITCH_STACK_BOTTOM);
1701 }
1702
1703
1704 } else {
1705 base_set(session, data, SWITCH_STACK_BOTTOM);
1706 }
1707 }
1708
1709 SWITCH_STANDARD_APP(set_function)
1710 {
1711 base_set(session, data, SWITCH_STACK_BOTTOM);
1712 }
1713
1714 SWITCH_STANDARD_APP(push_function)
1715 {
1716 base_set(session, data, SWITCH_STACK_PUSH);
1717 }
1718
1719 SWITCH_STANDARD_APP(unshift_function)
1720 {
1721 base_set(session, data, SWITCH_STACK_UNSHIFT);
1722 }
1723
1724 SWITCH_STANDARD_APP(set_global_function)
1725 {
1726 char *var, *val = NULL;
1727
1728 if (zstr(data)) {
1729 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n");
1730 } else {
1731 var = strdup(data);
1732 switch_assert(var);
1733 val = strchr(var, '=');
1734
1735 if (val) {
1736 *val++ = '\0';
1737 if (zstr(val)) {
1738 val = NULL;
1739 }
1740 }
1741
1742 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "SET GLOBAL [%s]=[%s]\n", var, val ? val : "UNDEF");
1743 switch_core_set_variable(var, val);
1744 free(var);
1745 }
1746 }
1747
1748 SWITCH_STANDARD_APP(set_profile_var_function)
1749 {
1750 char *name, *val = NULL;
1751
1752 if (zstr(data)) {
1753 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n");
1754 } else {
1755 name = switch_core_session_strdup(session, data);
1756 val = strchr(name, '=');
1757
1758 if (val) {
1759 *val++ = '\0';
1760 if (zstr(val)) {
1761 val = NULL;
1762 }
1763 }
1764
1765 switch_channel_set_profile_var(switch_core_session_get_channel(session), name, val);
1766 }
1767 }
1768
1769 SWITCH_STANDARD_APP(export_function)
1770 {
1771 switch_channel_t *channel = switch_core_session_get_channel(session);
1772 char *var, *val = NULL;
1773
1774 if (zstr(data)) {
1775 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n");
1776 } else {
1777 var = switch_core_session_strdup(session, data);
1778
1779 if ((val = strchr(var, '='))) {
1780 *val++ = '\0';
1781 if (zstr(val)) {
1782 val = NULL;
1783 }
1784 }
1785
1786 switch_channel_export_variable_var_check(channel, var, val, SWITCH_EXPORT_VARS_VARIABLE, SWITCH_FALSE);
1787 }
1788 }
1789
1790 SWITCH_STANDARD_APP(bridge_export_function)
1791 {
1792 switch_channel_t *channel = switch_core_session_get_channel(session);
1793 char *var, *val = NULL;
1794
1795 if (zstr(data)) {
1796 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n");
1797 } else {
1798 var = switch_core_session_strdup(session, data);
1799
1800 if ((val = strchr(var, '='))) {
1801 *val++ = '\0';
1802 if (zstr(val)) {
1803 val = NULL;
1804 }
1805 }
1806
1807 switch_channel_export_variable(channel, var, val, SWITCH_BRIDGE_EXPORT_VARS_VARIABLE);
1808 }
1809 }
1810
1811 SWITCH_STANDARD_APP(unset_function)
1812 {
1813 if (zstr(data)) {
1814 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n");
1815 } else {
1816 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UNSET [%s]\n", (char *) data);
1817 switch_channel_set_variable(switch_core_session_get_channel(session), data, NULL);
1818 }
1819 }
1820
1821 SWITCH_STANDARD_APP(multiunset_function)
1822 {
1823 char delim = ' ';
1824 char *arg = (char *) data;
1825
1826 if (!zstr(arg) && *arg == '^' && *(arg+1) == '^') {
1827 arg += 2;
1828 delim = *arg++;
1829 }
1830
1831 if (arg) {
1832 char *array[256] = {0};
1833 int i, argc;
1834
1835 arg = switch_core_session_strdup(session, arg);
1836 argc = switch_split(arg, delim, array);
1837
1838 for(i = 0; i < argc; i++) {
1839 switch_channel_set_variable(switch_core_session_get_channel(session), array[i], NULL);
1840 }
1841
1842 } else {
1843 switch_channel_set_variable(switch_core_session_get_channel(session), arg, NULL);
1844 }
1845 }
1846
1847
1848 SWITCH_STANDARD_APP(log_function)
1849 {
1850 char *level, *log_str;
1851
1852 if (data && (level = strdup(data))) {
1853 switch_log_level_t ltype = SWITCH_LOG_DEBUG;
1854
1855 if ((log_str = strchr(level, ' '))) {
1856 *log_str++ = '\0';
1857 ltype = switch_log_str2level(level);
1858 } else {
1859 log_str = level;
1860 }
1861 if (ltype == SWITCH_LOG_INVALID) {
1862 ltype = SWITCH_LOG_DEBUG;
1863 }
1864
1865 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), ltype, "%s\n", log_str);
1866 switch_safe_free(level);
1867 }
1868 }
1869
1870 SWITCH_STANDARD_APP(info_function)
1871 {
1872 switch_event_t *event;
1873 char *buf;
1874 int level = SWITCH_LOG_INFO;
1875
1876 if (!zstr(data)) {
1877 level = switch_log_str2level(data);
1878 }
1879
1880 if (switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
1881 switch_channel_event_set_data(switch_core_session_get_channel(session), event);
1882 switch_event_serialize(event, &buf, SWITCH_FALSE);
1883 switch_assert(buf);
1884 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), level, "CHANNEL_DATA:\n%s\n", buf);
1885 switch_event_destroy(&event);
1886 free(buf);
1887 }
1888 }
1889
1890 SWITCH_STANDARD_APP(sound_test_function)
1891 {
1892 switch_ivr_sound_test(session);
1893 }
1894
1895 SWITCH_STANDARD_APP(event_function)
1896 {
1897 switch_event_t *event;
1898 char *argv[25] = { 0 };
1899 int argc = 0;
1900 char *lbuf;
1901
1902 if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_APPLICATION) == SWITCH_STATUS_SUCCESS) {
1903 if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
1904 && (argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
1905 int x = 0;
1906
1907 for (x = 0; x < argc; x++) {
1908 char *p, *this = argv[x];
1909 if (this) {
1910 char *var, *val;
1911 p = this;
1912 while (*p == ' ')
1913 *p++ = '\0';
1914 this = p;
1915
1916 var = this;
1917 val = NULL;
1918 if ((val = strchr(var, '='))) {
1919 p = val - 1;
1920 *val++ = '\0';
1921 while (*p == ' ')
1922 *p-- = '\0';
1923 p = val;
1924 while (*p == ' ')
1925 *p++ = '\0';
1926 val = p;
1927 if (!strcasecmp(var, "Event-Name")) {
1928 switch_name_event(val, &event->event_id);
1929 switch_event_del_header(event, var);
1930 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, var, val);
1931 } else if (!strcasecmp(var, "Event-Subclass")) {
1932 size_t len = strlen(val) + 1;
1933 void *new = malloc(len);
1934 switch_assert(new);
1935 memcpy(new, val, len);
1936 event->subclass_name = new;
1937 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, var, val);
1938 } else {
1939 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, var, val);
1940 }
1941 }
1942 }
1943 }
1944 }
1945 switch_channel_event_set_data(switch_core_session_get_channel(session), event);
1946 switch_event_fire(&event);
1947 }
1948 }
1949
1950 SWITCH_STANDARD_APP(privacy_function)
1951 {
1952 switch_caller_profile_t *caller_profile = switch_channel_get_caller_profile(switch_core_session_get_channel(session));
1953
1954 if (zstr(data)) {
1955 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No privacy mode specified.\n");
1956 } else {
1957 switch_set_flag(caller_profile, SWITCH_CPF_SCREEN);
1958
1959
1960 if (!strcasecmp(data, "full")) {
1961 switch_set_flag(caller_profile, SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER);
1962 } else if (!strcasecmp(data, "name")) {
1963 switch_set_flag(caller_profile, SWITCH_CPF_HIDE_NAME);
1964 } else if (!strcasecmp(data, "number")) {
1965 switch_set_flag(caller_profile, SWITCH_CPF_HIDE_NUMBER);
1966 } else if (switch_true(data)) {
1967 switch_set_flag(caller_profile, SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER);
1968 } else if (switch_false(data)) {
1969 switch_clear_flag(caller_profile, SWITCH_CPF_HIDE_NAME);
1970 switch_clear_flag(caller_profile, SWITCH_CPF_HIDE_NUMBER);
1971 } else {
1972 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
1973 "INVALID privacy mode specified. Use a valid mode [no|yes|name|full|number].\n");
1974 }
1975 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set Privacy to %s [%d]\n", data, caller_profile->flags);
1976 }
1977 }
1978
1979 SWITCH_STANDARD_APP(strftime_function)
1980 {
1981 char *argv[2] = { 0 };
1982 char *lbuf;
1983
1984 if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
1985 && switch_separate_string(lbuf, '=', argv, (sizeof(argv) / sizeof(argv[0]))) > 1) {
1986 switch_size_t retsize;
1987 switch_time_exp_t tm;
1988 char date[80] = "";
1989
1990 switch_time_exp_lt(&tm, switch_micro_time_now());
1991 switch_strftime(date, &retsize, sizeof(date), argv[1], &tm);
1992 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "SET [%s]=[%s]\n", argv[0], date);
1993 switch_channel_set_variable(switch_core_session_get_channel(session), argv[0], date);
1994 }
1995 }
1996
1997 SWITCH_STANDARD_API(strepoch_api_function)
1998 {
1999 switch_time_t out;
2000
2001 if (zstr(cmd)) {
2002 out = switch_micro_time_now();
2003 } else {
2004 out = switch_str_time(cmd);
2005 }
2006
2007 stream->write_function(stream, "%d", (uint32_t) ((out) / (int64_t) (1000000)));
2008
2009 return SWITCH_STATUS_SUCCESS;
2010 }
2011
2012
2013 SWITCH_STANDARD_API(strmicroepoch_api_function)
2014 {
2015 switch_time_t out;
2016
2017 if (zstr(cmd)) {
2018 out = switch_micro_time_now();
2019 } else {
2020 out = switch_str_time(cmd);
2021 }
2022
2023 stream->write_function(stream, "%"SWITCH_TIME_T_FMT, out);
2024
2025 return SWITCH_STATUS_SUCCESS;
2026 }
2027
2028 SWITCH_STANDARD_API(strftime_api_function)
2029 {
2030 switch_size_t retsize;
2031 switch_time_exp_t tm;
2032 char date[80] = "";
2033 switch_time_t thetime;
2034 char *p, *q = NULL;
2035 char *mycmd = NULL;
2036
2037 if (!zstr(cmd)) {
2038 mycmd = strdup(cmd);
2039 q = mycmd;
2040 }
2041
2042 if (!zstr(q) && (p = strchr(q, '|'))) {
2043 *p++ = '\0';
2044
2045 thetime = switch_time_make(atol(q), 0);
2046 q = p + 1;
2047 } else {
2048 thetime = switch_micro_time_now();
2049 }
2050 switch_time_exp_lt(&tm, thetime);
2051
2052 if (zstr(q)) {
2053 switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
2054 } else {
2055 switch_strftime(date, &retsize, sizeof(date), q, &tm);
2056 }
2057 stream->write_function(stream, "%s", date);
2058 switch_safe_free(mycmd);
2059
2060 return SWITCH_STATUS_SUCCESS;
2061 }
2062
2063
2064 #define PRESENCE_USAGE "[in|out] <user> <rpid> <message>"
2065 SWITCH_STANDARD_API(presence_api_function)
2066 {
2067 switch_event_t *event;
2068 char *lbuf = NULL, *argv[4];
2069 int argc = 0;
2070 switch_event_types_t type = SWITCH_EVENT_PRESENCE_IN;
2071 int need = 4;
2072
2073 if (!zstr(cmd) && (lbuf = strdup(cmd))
2074 && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) > 0) {
2075
2076 if (!strcasecmp(argv[0], "out")) {
2077 type = SWITCH_EVENT_PRESENCE_OUT;
2078 need = 2;
2079 } else if (strcasecmp(argv[0], "in")) {
2080 goto error;
2081 }
2082
2083 if (argc < need) {
2084 goto error;
2085 }
2086
2087 if (switch_event_create(&event, type) == SWITCH_STATUS_SUCCESS) {
2088 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "dp");
2089 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", __FILE__);
2090 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", argv[1]);
2091 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", argv[2]);
2092 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", argv[3]);
2093 if (type == SWITCH_EVENT_PRESENCE_IN) {
2094 if (!strncasecmp(argv[3], "cs_", 3) || switch_stristr("hangup", argv[3])) {
2095 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP");
2096 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "CS_HANGUP");
2097 }
2098 } else {
2099 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "CS_HANGUP");
2100 }
2101 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
2102 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
2103 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", 0);
2104 switch_event_fire(&event);
2105 }
2106 stream->write_function(stream, "Event Sent");
2107 } else {
2108 goto error;
2109 }
2110
2111 switch_safe_free(lbuf);
2112 return SWITCH_STATUS_SUCCESS;
2113
2114 error:
2115
2116 switch_safe_free(lbuf);
2117 stream->write_function(stream, "Invalid: presence %s", PRESENCE_USAGE);
2118 return SWITCH_STATUS_SUCCESS;
2119 }
2120
2121 SWITCH_STANDARD_API(chat_api_function)
2122 {
2123 char *lbuf = NULL, *argv[5];
2124
2125 if (!zstr(cmd) && (lbuf = strdup(cmd))
2126 && switch_separate_string(lbuf, '|', argv, (sizeof(argv) / sizeof(argv[0]))) >= 4) {
2127
2128 if (switch_core_chat_send_args(argv[0], "global", argv[1], argv[2], "", argv[3], !zstr(argv[4]) ? argv[4] : NULL, "", SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
2129 stream->write_function(stream, "Sent");
2130 } else {
2131 stream->write_function(stream, "Error! Message Not Sent");
2132 }
2133 } else {
2134 stream->write_function(stream, "Invalid");
2135 }
2136
2137 switch_safe_free(lbuf);
2138 return SWITCH_STATUS_SUCCESS;
2139 }
2140
2141 static char *ivr_cf_name = "ivr.conf";
2142
2143 #ifdef _TEST_CALLBACK_
2144 static switch_ivr_action_t menu_handler(switch_ivr_menu_t *menu, char *param, char *buf, size_t buflen, void *obj)
2145 {
2146 switch_ivr_action_t action = SWITCH_IVR_ACTION_NOOP;
2147
2148 if (param != NULL) {
2149 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "menu_handler '%s'\n", param);
2150 }
2151
2152 return action;
2153 }
2154 #endif
2155
2156 SWITCH_STANDARD_APP(ivr_application_function)
2157 {
2158 switch_channel_t *channel = switch_core_session_get_channel(session);
2159 switch_event_t *params;
2160 const char *name = (const char *) data;
2161
2162 if (channel) {
2163 switch_xml_t cxml = NULL, cfg = NULL, xml_menus = NULL, xml_menu = NULL;
2164
2165 /* Open the config from the xml registry */
2166 switch_event_create(&params, SWITCH_EVENT_REQUEST_PARAMS);
2167 switch_assert(params);
2168 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Menu-Name", name);
2169 switch_channel_event_set_data(channel, params);
2170
2171 if ((cxml = switch_xml_open_cfg(ivr_cf_name, &cfg, params)) != NULL) {
2172 if ((xml_menus = switch_xml_child(cfg, "menus"))) {
2173 xml_menu = switch_xml_find_child(xml_menus, "menu", "name", name);
2174
2175 /* if the menu was found */
2176 if (xml_menu != NULL) {
2177 switch_ivr_menu_xml_ctx_t *xml_ctx = NULL;
2178 switch_ivr_menu_t *menu_stack = NULL;
2179
2180 /* build a menu tree and execute it */
2181 if (switch_ivr_menu_stack_xml_init(&xml_ctx, NULL) == SWITCH_STATUS_SUCCESS
2182 #ifdef _TEST_CALLBACK_
2183 && switch_ivr_menu_stack_xml_add_custom(xml_ctx, "custom", &menu_handler) == SWITCH_STATUS_SUCCESS
2184 #endif
2185 && switch_ivr_menu_stack_xml_build(xml_ctx, &menu_stack, xml_menus, xml_menu) == SWITCH_STATUS_SUCCESS) {
2186 switch_xml_free(cxml);
2187 cxml = NULL;
2188 switch_ivr_menu_execute(session, menu_stack, (char *) name, NULL);
2189 switch_ivr_menu_stack_free(menu_stack);
2190 } else {
2191 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unable to create menu\n");
2192 }
2193 } else {
2194 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unable to find menu\n");
2195 }
2196 } else {
2197 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No menus configured\n");
2198 }
2199 switch_xml_free(cxml);
2200 } else {
2201 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Open of %s failed\n", ivr_cf_name);
2202 }
2203 switch_event_destroy(&params);
2204 }
2205 }
2206
2207 SWITCH_STANDARD_APP(dtmf_session_function)
2208 {
2209 switch_ivr_inband_dtmf_session(session);
2210 }
2211
2212 SWITCH_STANDARD_APP(stop_dtmf_session_function)
2213 {
2214 switch_ivr_stop_inband_dtmf_session(session);
2215 }
2216
2217 SWITCH_STANDARD_APP(dtmf_session_generate_function)
2218 {
2219 switch_bool_t do_read = SWITCH_TRUE;
2220
2221 if (!zstr(data)) {
2222 if (!strcasecmp(data, "write")) {
2223 do_read = SWITCH_FALSE;
2224 }
2225 }
2226 switch_ivr_inband_dtmf_generate_session(session, do_read);
2227 }
2228
2229 SWITCH_STANDARD_APP(stop_dtmf_session_generate_function)
2230 {
2231 switch_ivr_stop_inband_dtmf_generate_session(session);
2232 }
2233
2234 SWITCH_STANDARD_APP(fax_detect_session_function)
2235 {
2236 switch_ivr_tone_detect_session(session, "fax", "1100.0", "r", 0, 1, NULL, NULL, NULL);
2237 }
2238
2239 SWITCH_STANDARD_APP(system_session_function)
2240 {
2241 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Executing command: %s\n", data);
2242 if (switch_system(data, SWITCH_TRUE) < 0) {
2243 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Failed to execute command: %s\n", data);
2244 }
2245 }
2246
2247 SWITCH_STANDARD_APP(bgsystem_session_function)
2248 {
2249 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Executing command: %s\n", data);
2250 if (switch_system(data, SWITCH_FALSE) < 0) {
2251 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Failed to execute command: %s\n", data);
2252 }
2253 }
2254
2255 SWITCH_STANDARD_APP(tone_detect_session_function)
2256 {
2257 char *argv[7] = { 0 };
2258 char *mydata = NULL;
2259 time_t to = 0;
2260 int hits = 0;
2261 const char *hp = NULL;
2262
2263 if (zstr(data) || !(mydata = switch_core_session_strdup(session, data))) {
2264 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "INVALID ARGS!\n");
2265 return;
2266 }
2267
2268 if (switch_separate_string(mydata, ' ', argv, sizeof(argv) / sizeof(argv[0])) < 2) {
2269 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "INVALID ARGS!\n");
2270 return;
2271 }
2272
2273 if (argv[3]) {
2274 uint32_t mto;
2275 if (*argv[3] == '+') {
2276 if ((mto = atol(argv[3] + 1)) > 0) {
2277 to = switch_epoch_time_now(NULL) + mto;
2278 } else {
2279 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "INVALID Timeout!\n");
2280 }
2281 } else {
2282 if ((to = atol(argv[3])) < switch_epoch_time_now(NULL)) {
2283 if (to >= 1) {
2284 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "INVALID Timeout!\n");
2285 }
2286 to = 0;
2287 }
2288 }
2289 }
2290
2291 if (argv[4] && argv[5]) {
2292 hp = argv[6];
2293 } else if (argv[4] && !argv[6]) {
2294 hp = argv[4];
2295 }
2296
2297 if (hp) {
2298 hits = atoi(hp);
2299 if (hits < 0) {
2300 hits = 0;
2301 }
2302 }
2303
2304 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Enabling tone detection '%s' '%s'\n", argv[0], argv[1]);
2305
2306 switch_ivr_tone_detect_session(session, argv[0], argv[1], argv[2], to, hits, argv[4], argv[5], NULL);
2307 }
2308
2309 SWITCH_STANDARD_APP(stop_fax_detect_session_function)
2310 {
2311 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Disabling tone detection\n");
2312 switch_ivr_stop_tone_detect_session(session);
2313 }
2314
2315 SWITCH_STANDARD_APP(echo_function)
2316 {
2317 switch_ivr_session_echo(session, NULL);
2318 }
2319
2320 SWITCH_STANDARD_APP(park_function)
2321 {
2322 switch_ivr_park(session, NULL);
2323 }
2324
2325 SWITCH_STANDARD_APP(park_state_function)
2326 {
2327 switch_ivr_park_session(session);
2328 }
2329
2330 /********************************************************************************/
2331 /* Playback/Record Functions */
2332 /********************************************************************************/
2333
2334 /*
2335 dtmf handler function you can hook up to be executed when a digit is dialed during playback
2336 if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
2337 */
2338 static switch_status_t bridge_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
2339 {
2340 char *str = (char *) buf;
2341
2342 if (str && input && itype == SWITCH_INPUT_TYPE_DTMF) {
2343 switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
2344 if (strchr(str, dtmf->digit)) {
2345 return SWITCH_STATUS_BREAK;
2346 }
2347 }
2348 return SWITCH_STATUS_SUCCESS;
2349 }
2350
2351 static switch_status_t on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
2352 {
2353 char sbuf[3];
2354
2355 switch (itype) {
2356 case SWITCH_INPUT_TYPE_DTMF:
2357 {
2358 switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
2359 const char *terminators;
2360 switch_channel_t *channel = switch_core_session_get_channel(session);
2361 const char *p;
2362
2363 if (!(terminators = switch_channel_get_variable(channel, SWITCH_PLAYBACK_TERMINATORS_VARIABLE))) {
2364 terminators = "*";
2365 }
2366 if (!strcasecmp(terminators, "any")) {
2367 terminators = "1234567890*#";
2368 }
2369 if (!strcasecmp(terminators, "none")) {
2370 terminators = NULL;
2371 }
2372 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Digit %c\n", dtmf->digit);
2373
2374 for (p = terminators; p && *p; p++) {
2375 if (*p == dtmf->digit) {
2376 switch_snprintf(sbuf, sizeof(sbuf), "%c", *p);
2377 switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, sbuf);
2378 return SWITCH_STATUS_BREAK;
2379 }
2380 }
2381 }
2382 break;
2383 default:
2384 break;
2385 }
2386
2387 return SWITCH_STATUS_SUCCESS;
2388 }
2389
2390 SWITCH_STANDARD_APP(sleep_function)
2391 {
2392 switch_channel_t *channel = switch_core_session_get_channel(session);
2393
2394 if (zstr(data)) {
2395 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No timeout specified.\n");
2396 } else {
2397 uint32_t ms = atoi(data);
2398 char buf[10];
2399 switch_input_args_t args = { 0 };
2400
2401 if (switch_true(switch_channel_get_variable(channel, "sleep_eat_digits"))) {
2402 args.input_callback = on_dtmf;
2403 args.buf = buf;
2404 args.buflen = sizeof(buf);
2405 switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
2406 }
2407
2408 switch_ivr_sleep(session, ms, SWITCH_TRUE, &args);
2409 }
2410 }
2411
2412 SWITCH_STANDARD_APP(clear_speech_cache_function)
2413 {
2414 switch_ivr_clear_speech_cache(session);
2415 }
2416
2417 SWITCH_STANDARD_APP(speak_function)
2418 {
2419 switch_channel_t *channel = switch_core_session_get_channel(session);
2420 char buf[10];
2421 char *argv[3] = { 0 };
2422 int argc;
2423 const char *engine = NULL;
2424 const char *voice = NULL;
2425 char *text = NULL;
2426 char *mydata = NULL;
2427 switch_input_args_t args = { 0 };
2428
2429 if (zstr(data) || !(mydata = switch_core_session_strdup(session, data))) {
2430 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Params!\n");
2431 return;
2432 }
2433
2434 argc = switch_separate_string(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
2435
2436 if (argc == 0) {
2437 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Params!\n");
2438 return;
2439 } else if (argc == 1) {
2440 text = switch_core_session_strdup(session, data); /* unstripped text */
2441 } else if (argc == 2) {
2442 voice = argv[0];
2443 text = switch_core_session_strdup(session, data + (argv[1] - argv[0])); /* unstripped text */
2444 } else {
2445 engine = argv[0];
2446 voice = argv[1];
2447 text = switch_core_session_strdup(session, data + (argv[2] - argv[0])); /* unstripped text */
2448 }
2449
2450 if (!engine) {
2451 engine = switch_channel_get_variable(channel, "tts_engine");
2452 }
2453
2454 if (!voice) {
2455 voice = switch_channel_get_variable(channel, "tts_voice");
2456 }
2457
2458 if (!(engine && voice && text)) {
2459 if (!engine) {
2460 engine = "NULL";
2461 }
2462 if (!voice) {
2463 voice = "NULL";
2464 }
2465 if (!text) {
2466 text = "NULL";
2467 }
2468 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Params! [%s][%s][%s]\n", engine, voice, text);
2469 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
2470 }
2471
2472 args.input_callback = on_dtmf;
2473 args.buf = buf;
2474 args.buflen = sizeof(buf);
2475
2476 switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
2477
2478 switch_ivr_speak_text(session, engine, voice, text, &args);
2479 }
2480
2481 struct att_keys {
2482 const char *attxfer_cancel_key;
2483 const char *attxfer_hangup_key;
2484 const char *attxfer_conf_key;
2485 };
2486
2487 static switch_status_t xfer_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
2488 {
2489 switch_core_session_t *peer_session = (switch_core_session_t *) buf;
2490 if (!buf || !peer_session) {
2491 return SWITCH_STATUS_SUCCESS;
2492 }
2493
2494 switch (itype) {
2495 case SWITCH_INPUT_TYPE_DTMF:
2496 {
2497 switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
2498 switch_channel_t *channel = switch_core_session_get_channel(session);
2499 switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
2500 struct att_keys *keys = switch_channel_get_private(channel, "__keys");
2501
2502 if (dtmf->digit == *keys->attxfer_hangup_key) {
2503 switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
2504 return SWITCH_STATUS_FALSE;
2505 }
2506
2507 if (dtmf->digit == *keys->attxfer_cancel_key) {
2508 switch_channel_hangup(peer_channel, SWITCH_CAUSE_NORMAL_CLEARING);
2509 return SWITCH_STATUS_FALSE;
2510 }
2511
2512 if (dtmf->digit == *keys->attxfer_conf_key) {
2513 switch_caller_extension_t *extension = NULL;
2514 const char *app = "three_way";
2515 const char *app_arg = switch_core_session_get_uuid(session);
2516 const char *holding = switch_channel_get_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE);
2517 switch_core_session_t *b_session;
2518
2519 if (holding && (b_session = switch_core_session_locate(holding))) {
2520 switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
2521 if (!switch_channel_ready(b_channel)) {
2522 app = "intercept";
2523 }
2524 switch_core_session_rwunlock(b_session);
2525 }
2526
2527 if ((extension = switch_caller_extension_new(peer_session, app, app_arg)) == 0) {
2528 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
2529 abort();
2530 }
2531
2532 switch_caller_extension_add_application(peer_session, extension, app, app_arg);
2533 switch_channel_set_caller_extension(peer_channel, extension);
2534 switch_channel_set_state(peer_channel, CS_RESET);
2535 switch_channel_wait_for_state(peer_channel, channel, CS_RESET);
2536 switch_channel_set_state(peer_channel, CS_EXECUTE);
2537 switch_channel_set_variable(channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, NULL);
2538 return SWITCH_STATUS_FALSE;
2539 }
2540
2541 }
2542 break;
2543 default:
2544 break;
2545 }
2546
2547 return SWITCH_STATUS_SUCCESS;
2548 }
2549
2550 static switch_status_t tmp_hanguphook(switch_core_session_t *session)
2551 {
2552 switch_channel_t *channel = switch_core_session_get_channel(session);
2553 switch_channel_state_t state = switch_channel_get_state(channel);
2554
2555 if (state == CS_HANGUP || state == CS_ROUTING) {
2556 const char *bond = switch_channel_get_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE);
2557
2558 if (!zstr(bond)) {
2559 switch_core_session_t *b_session;
2560
2561 if ((b_session = switch_core_session_locate(bond))) {
2562 switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
2563 if (switch_channel_up(b_channel)) {
2564 switch_channel_set_flag(b_channel, CF_REDIRECT);
2565 }
2566 switch_core_session_rwunlock(b_session);
2567 }
2568 }
2569
2570 switch_core_event_hook_remove_state_change(session, tmp_hanguphook);
2571 }
2572
2573 return SWITCH_STATUS_SUCCESS;
2574 }
2575
2576 static switch_status_t hanguphook(switch_core_session_t *session)
2577 {
2578 switch_channel_t *channel = switch_core_session_get_channel(session);
2579 switch_channel_state_t state = switch_channel_get_state(channel);
2580 const char *id = NULL;
2581
2582 if (state == CS_HANGUP || state == CS_ROUTING) {
2583 if ((id = switch_channel_get_variable(channel, "xfer_uuids"))) {
2584 switch_stream_handle_t stream = { 0 };
2585 SWITCH_STANDARD_STREAM(stream);
2586 switch_api_execute("uuid_bridge", id, NULL, &stream);
2587 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "\nHangup Command uuid_bridge(%s):\n%s\n", id,
2588 switch_str_nil((char *) stream.data));
2589 switch_safe_free(stream.data);
2590 }
2591
2592 switch_core_event_hook_remove_state_change(session, hanguphook);
2593 }
2594 return SWITCH_STATUS_SUCCESS;
2595 }
2596
2597
2598 static void att_xfer_set_result(switch_channel_t *channel, switch_status_t status)
2599 {
2600 switch_channel_set_variable(channel, SWITCH_ATT_XFER_RESULT_VARIABLE, status == SWITCH_STATUS_SUCCESS ? "success" : "failure");
2601 }
2602
2603 struct att_obj {
2604 switch_core_session_t *session;
2605 const char *data;
2606 int running;
2607 };
2608
2609 void *SWITCH_THREAD_FUNC att_thread_run(switch_thread_t *thread, void *obj)
2610 {
2611 struct att_obj *att = (struct att_obj *) obj;
2612 struct att_keys *keys = NULL;
2613 switch_core_session_t *session = att->session;
2614 switch_core_session_t *peer_session = NULL;
2615 const char *data = att->data;
2616 switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
2617 switch_channel_t *channel = switch_core_session_get_channel(session), *peer_channel = NULL;
2618 const char *bond = NULL;
2619 switch_core_session_t *b_session = NULL;
2620 switch_bool_t follow_recording = switch_true(switch_channel_get_variable(channel, "recording_follow_attxfer"));
2621 const char *attxfer_cancel_key = NULL, *attxfer_hangup_key = NULL, *attxfer_conf_key = NULL;
2622
2623 att->running = 1;
2624
2625 if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) {
2626 return NULL;
2627 }
2628
2629 bond = switch_channel_get_partner_uuid(channel);
2630 switch_channel_set_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, bond);
2631 switch_core_event_hook_add_state_change(session, tmp_hanguphook);
2632
2633 if (follow_recording && (b_session = switch_core_session_locate(bond))) {
2634 switch_ivr_transfer_recordings(b_session, session);
2635 switch_core_session_rwunlock(b_session);
2636 }
2637
2638 if (switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL)
2639 != SWITCH_STATUS_SUCCESS || !peer_session) {
2640 switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond);
2641 goto end;
2642 }
2643
2644 peer_channel = switch_core_session_get_channel(peer_session);
2645 switch_channel_set_flag(peer_channel, CF_INNER_BRIDGE);
2646 switch_channel_set_flag(channel, CF_INNER_BRIDGE);
2647
2648 if (!(attxfer_cancel_key = switch_channel_get_variable(channel, "attxfer_cancel_key"))) {
2649 if (!(attxfer_cancel_key = switch_channel_get_variable(peer_channel, "attxfer_cancel_key"))) {
2650 attxfer_cancel_key = "#";
2651 }
2652 }
2653
2654 if (!(attxfer_hangup_key = switch_channel_get_variable(channel, "attxfer_hangup_key"))) {
2655 if (!(attxfer_hangup_key = switch_channel_get_variable(peer_channel, "attxfer_hangup_key"))) {
2656 attxfer_hangup_key = "*";
2657 }
2658 }
2659
2660 if (!(attxfer_conf_key = switch_channel_get_variable(channel, "attxfer_conf_key"))) {
2661 if (!(attxfer_conf_key = switch_channel_get_variable(peer_channel, "attxfer_conf_key"))) {
2662 attxfer_conf_key = "0";
2663 }
2664 }
2665
2666 keys = switch_core_session_alloc(session, sizeof(*keys));
2667 keys->attxfer_cancel_key = switch_core_session_strdup(session, attxfer_cancel_key);
2668 keys->attxfer_hangup_key = switch_core_session_strdup(session, attxfer_hangup_key);
2669 keys->attxfer_conf_key = switch_core_session_strdup(session, attxfer_conf_key);
2670 switch_channel_set_private(channel, "__keys", keys);
2671
2672 switch_ivr_multi_threaded_bridge(session, peer_session, xfer_on_dtmf, peer_session, NULL);
2673
2674 switch_channel_clear_flag(peer_channel, CF_INNER_BRIDGE);
2675 switch_channel_clear_flag(channel, CF_INNER_BRIDGE);
2676
2677 if (zstr(bond) && switch_channel_down(peer_channel)) {
2678 switch_core_session_rwunlock(peer_session);
2679 switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond);
2680 goto end;
2681 }
2682
2683 if (bond) {
2684 int br = 0;
2685
2686 switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond);
2687
2688 if (!switch_channel_down(peer_channel)) {
2689 if (!switch_channel_ready(channel)) {
2690 switch_status_t status;
2691
2692 if (follow_recording) {
2693 switch_ivr_transfer_recordings(session, peer_session);
2694 }
2695 status = switch_ivr_uuid_bridge(switch_core_session_get_uuid(peer_session), bond);
2696 att_xfer_set_result(peer_channel, status);
2697 br++;
2698 } else if ((b_session = switch_core_session_locate(bond))) {
2699 switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
2700 switch_channel_set_variable_printf(b_channel, "xfer_uuids", "%s %s", switch_core_session_get_uuid(peer_session), switch_core_session_get_uuid(session));
2701 switch_channel_set_variable_printf(channel, "xfer_uuids", "%s %s", switch_core_session_get_uuid(peer_session), bond);
2702
2703 switch_core_event_hook_add_state_change(session, hanguphook);
2704 switch_core_event_hook_add_state_change(b_session, hanguphook);
2705
2706 switch_core_session_rwunlock(b_session);
2707 }
2708 }
2709
2710 if (!br) {
2711 switch_status_t status = switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), bond);
2712 att_xfer_set_result(channel, status);
2713 }
2714
2715 }
2716
2717 switch_core_session_rwunlock(peer_session);
2718
2719 end:
2720
2721 switch_core_event_hook_remove_state_change(session, tmp_hanguphook);
2722
2723 switch_channel_set_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, NULL);
2724 switch_channel_clear_flag(channel, CF_XFER_ZOMBIE);
2725
2726 switch_core_session_rwunlock(session);
2727 att->running = 0;
2728
2729 return NULL;
2730 }
2731
2732 SWITCH_STANDARD_APP(att_xfer_function)
2733 {
2734 switch_thread_t *thread;
2735 switch_threadattr_t *thd_attr = NULL;
2736 switch_memory_pool_t *pool = switch_core_session_get_pool(session);
2737 struct att_obj *att;
2738 switch_channel_t *channel = switch_core_session_get_channel(session);
2739
2740 switch_threadattr_create(&thd_attr, pool);
2741 switch_threadattr_detach_set(thd_attr, 1);
2742 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
2743
2744 att = switch_core_session_alloc(session, sizeof(*att));
2745 att->running = -1;
2746 att->session = session;
2747 att->data = switch_core_session_strdup(session, data);
2748 switch_thread_create(&thread, thd_attr, att_thread_run, att, pool);
2749
2750 while(att->running && switch_channel_up(channel)) {
2751 switch_yield(100000);
2752 }
2753 }
2754
2755 SWITCH_STANDARD_APP(read_function)
2756 {
2757 char *mydata;
2758 char *argv[7] = { 0 };
2759 int argc;
2760 int32_t min_digits = 0;
2761 int32_t max_digits = 0;
2762 uint32_t digit_timeout = 0;
2763 int timeout = 1000;
2764 char digit_buffer[128] = "";
2765 const char *prompt_audio_file = NULL;
2766 const char *var_name = NULL;
2767 const char *valid_terminators = NULL;
2768
2769 if (!zstr(data) && (mydata = switch_core_session_strdup(session, data))) {
2770 argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
2771 } else {
2772 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No arguments specified.\n");
2773 return;
2774 }
2775
2776 min_digits = atoi(argv[0]);
2777
2778 if (argc > 1) {
2779 max_digits = atoi(argv[1]);
2780 }
2781
2782 if (argc > 2) {
2783 prompt_audio_file = argv[2];
2784 }
2785
2786 if (argc > 3) {
2787 var_name = argv[3];
2788 }
2789
2790 if (argc > 4) {
2791 timeout = atoi(argv[4]);
2792 }
2793
2794 if (argc > 5) {
2795 valid_terminators = argv[5];
2796 }
2797
2798 if (argc > 6) {
2799 digit_timeout = switch_atoui(argv[6]);
2800 }
2801
2802 if (min_digits <= 1) {
2803 min_digits = 1;
2804 }
2805
2806 if (max_digits < min_digits) {
2807 max_digits = min_digits;
2808 }
2809
2810 if (timeout <= 1000) {
2811 timeout = 1000;
2812 }
2813
2814 if (zstr(valid_terminators)) {
2815 valid_terminators = "#";
2816 }
2817
2818 switch_ivr_read(session, min_digits, max_digits, prompt_audio_file, var_name, digit_buffer, sizeof(digit_buffer), timeout, valid_terminators,
2819 digit_timeout);
2820 }
2821
2822 SWITCH_STANDARD_APP(play_and_get_digits_function)
2823 {
2824 char *mydata;
2825 char *argv[11] = { 0 };
2826 int argc;
2827 int32_t min_digits = 0;
2828 int32_t max_digits = 0;
2829 int32_t max_tries = 0;
2830 uint32_t digit_timeout = 0;
2831 int timeout = 1000;
2832 char digit_buffer[128] = "";
2833 const char *prompt_audio_file = NULL;
2834 const char *bad_input_audio_file = NULL;
2835 const char *var_name = NULL;
2836 const char *valid_terminators = NULL;
2837 const char *digits_regex = NULL;
2838 const char *transfer_on_failure = NULL;
2839
2840 if (!zstr(data) && (mydata = switch_core_session_strdup(session, data))) {
2841 argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
2842 } else {
2843 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No arguments specified.\n");
2844 return;
2845 }
2846
2847 min_digits = atoi(argv[0]);
2848
2849 if (argc > 1) {
2850 max_digits = atoi(argv[1]);
2851 }
2852
2853 if (argc > 2) {
2854 max_tries = atoi(argv[2]);
2855 }
2856
2857 if (argc > 3) {
2858 timeout = atoi(argv[3]);
2859 }
2860
2861 if (argc > 4) {
2862 valid_terminators = argv[4];
2863 }
2864
2865 if (argc > 5) {
2866 prompt_audio_file = argv[5];
2867 }
2868
2869 if (argc > 6) {
2870 bad_input_audio_file = argv[6];
2871 }
2872
2873 if (argc > 7) {
2874 var_name = argv[7];
2875 }
2876
2877 if (argc > 8) {
2878 digits_regex = argv[8];
2879 }
2880
2881 if (argc > 9) {
2882 digit_timeout = switch_atoui(argv[9]);
2883 }
2884
2885 if (argc > 10) {
2886 transfer_on_failure = argv[10];
2887 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Transfer on failure = [%s].\n", transfer_on_failure);
2888 }
2889
2890 if (min_digits <= 0) {
2891 min_digits = 0;
2892 }
2893
2894 if (max_digits < min_digits) {
2895 max_digits = min_digits;
2896 }
2897
2898 if (timeout <= 1000) {
2899 timeout = 1000;
2900 }
2901
2902 if (zstr(valid_terminators)) {
2903 valid_terminators = "#";
2904 }
2905
2906 switch_play_and_get_digits(session, min_digits, max_digits, max_tries, timeout, valid_terminators,
2907 prompt_audio_file, bad_input_audio_file, var_name, digit_buffer, sizeof(digit_buffer),
2908 digits_regex, digit_timeout, transfer_on_failure);
2909 }
2910
2911 #define SAY_SYNTAX "<module_name>[:<lang>] <say_type> <say_method> [<say_gender>] <text>"
2912 SWITCH_STANDARD_APP(say_function)
2913 {
2914 char *argv[5] = { 0 };
2915 int argc;
2916 char *lbuf = NULL;
2917 switch_input_args_t args = { 0 };
2918 switch_channel_t *channel = switch_core_session_get_channel(session);
2919
2920 if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
2921 && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) && (argc == 4 || argc == 5)) {
2922
2923 args.input_callback = on_dtmf;
2924
2925 switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
2926
2927 /* Set default langauge according to the <module_name> */
2928 if (!strchr(argv[0], ':')) {
2929 argv[0] = switch_core_session_sprintf(session, "%s:%s", argv[0], argv[0]);
2930 }
2931
2932 switch_ivr_say(session, (argc == 4) ? argv[3] : argv[4], argv[0], argv[1], argv[2], (argc == 5) ? argv[3] : NULL ,&args);
2933 } else {
2934 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", SAY_SYNTAX);
2935 }
2936
2937 }
2938
2939
2940 SWITCH_STANDARD_APP(phrase_function)
2941 {
2942 char *mydata = NULL;
2943 switch_input_args_t args = { 0 };
2944 switch_channel_t *channel = switch_core_session_get_channel(session);
2945 switch_status_t status;
2946
2947 if (!zstr(data) && (mydata = switch_core_session_strdup(session, data))) {
2948 const char *lang;
2949 char *macro = mydata;
2950 char *mdata = NULL;
2951
2952 if ((mdata = strchr(macro, ','))) {
2953 *mdata++ = '\0';
2954 }
2955
2956 lang = switch_channel_get_variable(channel, "language");
2957
2958 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Execute %s(%s) lang %s\n", macro, switch_str_nil(mdata),
2959 switch_str_nil(lang));
2960
2961 args.input_callback = on_dtmf;
2962
2963 switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
2964
2965 status = switch_ivr_phrase_macro(session, macro, mdata, lang, &args);
2966 } else {
2967 status = SWITCH_STATUS_NOOP;
2968 }
2969
2970 switch (status) {
2971 case SWITCH_STATUS_SUCCESS:
2972 case SWITCH_STATUS_BREAK:
2973 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "PHRASE PLAYED");
2974 break;
2975 case SWITCH_STATUS_NOOP:
2976 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "NOTHING");
2977 break;
2978 default:
2979 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "UNKNOWN ERROR");
2980 break;
2981 }
2982 }
2983
2984
2985 SWITCH_STANDARD_APP(broadcast_function)
2986 {
2987 switch_channel_t *channel = switch_core_session_get_channel(session);
2988 char * uuid = switch_channel_get_uuid(channel);
2989 switch_media_flag_t flags = SMF_ECHO_ALEG | SMF_ECHO_BLEG;
2990 char *mycmd = NULL, *argv[4] = { 0 };
2991 int argc = 0;
2992
2993 if (zstr(data)) {
2994 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid args for broadcast app\n");
2995 return;
2996 }
2997
2998 mycmd = switch_core_session_strdup(session, data);
2999 argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
3000
3001 if (argc > 2) {
3002 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid args for broadcast app [%s]\n", data);
3003 return;
3004 } else {
3005 if (argv[1]) {
3006 if (switch_stristr("both", (argv[1]))) {
3007 flags |= (SMF_ECHO_ALEG | SMF_ECHO_BLEG);
3008 }
3009
3010 if (switch_stristr("aleg", argv[1])) {
3011 flags |= SMF_ECHO_ALEG;
3012 }
3013
3014 if (switch_stristr("bleg", argv[1])) {
3015 flags &= ~SMF_HOLD_BLEG;
3016 flags |= SMF_ECHO_BLEG;
3017 }
3018
3019 if (switch_stristr("holdb", argv[1])) {
3020 flags &= ~SMF_ECHO_BLEG;
3021 flags |= SMF_HOLD_BLEG;
3022 }
3023 }
3024 switch_ivr_broadcast(uuid, argv[0], flags);
3025 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "BROADCAST_SENT");
3026 }
3027 }
3028
3029 SWITCH_STANDARD_APP(playback_function)
3030 {
3031 switch_input_args_t args = { 0 };
3032 switch_channel_t *channel = switch_core_session_get_channel(session);
3033 switch_status_t status = SWITCH_STATUS_SUCCESS;
3034 switch_file_handle_t fh = { 0 };
3035 char *p;
3036 const char *file = NULL;
3037
3038 if (data) {
3039 file = switch_core_session_strdup(session, data);
3040 if ((p = strchr(file, '@')) && *(p + 1) == '@') {
3041 *p = '\0';
3042 p += 2;
3043 if (*p) {
3044 fh.samples = atoi(p);
3045 }
3046 }
3047 } else {
3048 file = data;
3049 }
3050
3051 args.input_callback = on_dtmf;
3052
3053 switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
3054
3055 status = switch_ivr_play_file(session, &fh, file, &args);
3056 switch_assert(!(fh.flags & SWITCH_FILE_OPEN));
3057
3058 switch (status) {
3059 case SWITCH_STATUS_SUCCESS:
3060 case SWITCH_STATUS_BREAK:
3061 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "FILE PLAYED");
3062 break;
3063 case SWITCH_STATUS_NOTFOUND:
3064 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "FILE NOT FOUND");
3065 break;
3066 default:
3067 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "PLAYBACK ERROR");
3068 break;
3069 }
3070
3071 }
3072
3073
3074
3075 SWITCH_STANDARD_APP(endless_playback_function)
3076 {
3077 switch_channel_t *channel = switch_core_session_get_channel(session);
3078 switch_status_t status = SWITCH_STATUS_SUCCESS;
3079 const char *file = data;
3080
3081 while (switch_channel_ready(channel)) {
3082 status = switch_ivr_play_file(session, NULL, file, NULL);
3083
3084 if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
3085 break;
3086 }
3087 }
3088
3089 switch (status) {
3090 case SWITCH_STATUS_SUCCESS:
3091 case SWITCH_STATUS_BREAK:
3092 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "FILE PLAYED");
3093 break;
3094 case SWITCH_STATUS_NOTFOUND:
3095 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "FILE NOT FOUND");
3096 break;
3097 default:
3098 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "PLAYBACK ERROR");
3099 break;
3100 }
3101
3102 }
3103
3104 SWITCH_STANDARD_APP(loop_playback_function)
3105 {
3106 switch_channel_t *channel = switch_core_session_get_channel(session);
3107 switch_status_t status = SWITCH_STATUS_SUCCESS;
3108 const char *file = data;
3109 int loop = 1;
3110
3111 if (*file == '+') {
3112 const char *p = ++file;
3113 while(*file && *file++ != ' ') { }
3114
3115 if (zstr(p)) {
3116 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing loop in data [%s]\n", data);
3117 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
3118 return;
3119 }
3120
3121 loop = atoi(p);
3122 }
3123
3124 if (zstr(file)) {
3125 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing file arg in data [%s]\n", data);
3126 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
3127 return;
3128 }
3129
3130 while (switch_channel_ready(channel) && (loop < 0 || loop-- > 0)) {
3131 status = switch_ivr_play_file(session, NULL, file, NULL);
3132
3133 if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
3134 break;
3135 }
3136 }
3137
3138 switch (status) {
3139 case SWITCH_STATUS_SUCCESS:
3140 case SWITCH_STATUS_BREAK:
3141 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "FILE PLAYED");
3142 break;
3143 case SWITCH_STATUS_NOTFOUND:
3144 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "FILE NOT FOUND");
3145 break;
3146 default:
3147 switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "PLAYBACK ERROR");
3148 break;
3149 }
3150
3151 }
3152
3153 SWITCH_STANDARD_APP(gentones_function)
3154 {
3155 char *tone_script = NULL;
3156 switch_input_args_t args = { 0 };
3157 char *l;
3158 int32_t loops = 0;
3159 switch_channel_t *channel = switch_core_session_get_channel(session);
3160
3161 if (zstr(data) || !(tone_script = switch_core_session_strdup(session, data))) {
3162 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Params!\n");
3163 return;
3164 }
3165
3166 if ((l = strchr(tone_script, '|'))) {
3167 *l++ = '\0';
3168 loops = atoi(l);
3169
3170 if (loops < 0) {
3171 loops = -1;
3172 }
3173 }
3174
3175 args.input_callback = on_dtmf;
3176
3177 switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
3178
3179 switch_ivr_gentones(session, tone_script, loops, &args);
3180 }
3181
3182 SWITCH_STANDARD_APP(displace_session_function)
3183 {
3184 char *path = NULL;
3185 uint32_t limit = 0;
3186 char *argv[6] = { 0 };
3187 int x, argc;
3188 char *lbuf = NULL;
3189 char *flags = NULL;
3190
3191 if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
3192 && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
3193 path = argv[0];
3194 for (x = 1; x < argc; x++) {
3195 if (strchr(argv[x], '+')) {
3196 limit = atoi(argv[x]);
3197 } else if (!zstr(argv[x])) {
3198 flags = argv[x];
3199 }
3200 }
3201 switch_ivr_displace_session(session, path, limit, flags);
3202 }
3203 }
3204
3205 SWITCH_STANDARD_APP(stop_displace_session_function)
3206 {
3207 switch_ivr_stop_displace_session(session, data);
3208 }
3209
3210 SWITCH_STANDARD_APP(capture_function)
3211 {
3212 char *argv[3] = { 0 };
3213 switch_regex_t *re = NULL;
3214 int ovector[30] = {0};
3215 char *lbuf;
3216 int proceed;
3217
3218 if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
3219 && switch_separate_string(lbuf, '|', argv, (sizeof(argv) / sizeof(argv[0]))) == 3) {
3220 if ((proceed = switch_regex_perform(argv[1], argv[2], &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
3221 switch_capture_regex(re, proceed, argv[1], ovector, argv[0], switch_regex_set_var_callback, session);
3222 }
3223 switch_regex_safe_free(re);
3224 } else {
3225 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No data specified.\n");
3226 }
3227 }
3228
3229 SWITCH_STANDARD_APP(record_function)
3230 {
3231 switch_channel_t *channel = switch_core_session_get_channel(session);
3232 switch_status_t status;
3233 uint32_t limit = 0;
3234 char *path;
3235 switch_input_args_t args = { 0 };
3236 switch_file_handle_t fh = { 0 };
3237 //int argc;
3238 char *mydata, *argv[4] = { 0 };
3239 char *l = NULL;
3240 const char *tmp;
3241 int rate;
3242
3243 if (!zstr(data) && (mydata = switch_core_session_strdup(session, data))) {
3244 switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
3245 } else {
3246 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No file specified.\n");
3247 return;
3248 }
3249
3250 path = argv[0];
3251 l = argv[1];
3252
3253 if (l) {
3254 if (*l == '+') {
3255 l++;
3256 }
3257
3258 limit = switch_atoui(l);
3259 }
3260
3261 if (argv[2]) {
3262 fh.thresh = switch_atoui(argv[2]);
3263 }
3264
3265 if (argv[3]) {
3266 fh.silence_hits = switch_atoui(argv[3]);
3267 }
3268
3269 if ((tmp = switch_channel_get_variable(channel, "record_rate"))) {
3270 rate = atoi(tmp);
3271 if (rate > 0) {
3272 fh.samplerate = rate;
3273 }
3274 }
3275
3276 args.input_callback = on_dtmf;
3277
3278 switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
3279
3280 status = switch_ivr_record_file(session, &fh, path, &args, limit);
3281
3282 if (!switch_channel_ready(channel) || (status != SWITCH_STATUS_SUCCESS && !SWITCH_STATUS_IS_BREAK(status))) {
3283 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
3284 }
3285 }
3286
3287 SWITCH_STANDARD_APP(preprocess_session_function)
3288 {
3289 switch_ivr_preprocess_session(session, (char *) data);
3290 }
3291
3292 SWITCH_STANDARD_APP(record_session_mask_function)
3293 {
3294 switch_ivr_record_session_mask(session, (char *) data, SWITCH_TRUE);
3295 }
3296
3297 SWITCH_STANDARD_APP(record_session_unmask_function)
3298 {
3299 switch_ivr_record_session_mask(session, (char *) data, SWITCH_FALSE);
3300 }
3301
3302 SWITCH_STANDARD_APP(record_session_pause_function)
3303 {
3304 switch_ivr_record_session_pause(session, (char *) data, SWITCH_TRUE);
3305 }
3306
3307 SWITCH_STANDARD_APP(record_session_resume_function)
3308 {
3309 switch_ivr_record_session_pause(session, (char *) data, SWITCH_FALSE);
3310 }
3311
3312 SWITCH_STANDARD_APP(record_session_function)
3313 {
3314 char *array[5] = {0};
3315 char *args = NULL;
3316 int argc;
3317
3318 char *path = NULL;
3319 uint32_t limit = 0;
3320 switch_event_t *vars = NULL;
3321 char *new_fp = NULL;
3322
3323 if (zstr(data)) {
3324 return;
3325 }
3326
3327 args = switch_core_session_strdup(session, data);
3328 argc = switch_split(args, ' ', array);
3329
3330 if (argc == 0) {
3331 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "usage: <path> [+<timeout>] [{var1=x,var2=y}]\n");
3332 }
3333
3334 path = array[0];
3335
3336 if (argc > 1) {
3337 if (*array[1] == '+') {
3338 limit = atoi(++array[1]);
3339 if (argc > 2) {
3340 switch_url_decode(array[2]);
3341 switch_event_create_brackets(array[2], '{', '}',',', &vars, &new_fp, SWITCH_FALSE);
3342 }
3343 } else {
3344 switch_url_decode(array[1]);
3345 switch_event_create_brackets(array[1], '{', '}',',', &vars, &new_fp, SWITCH_FALSE);
3346 }
3347 }
3348
3349 switch_ivr_record_session_event(session, path, limit, NULL, vars);
3350 switch_event_safe_destroy(vars);
3351 }
3352
3353 SWITCH_STANDARD_APP(stop_record_session_function)
3354 {
3355 switch_ivr_stop_record_session(session, data);
3356 }
3357
3358
3359 SWITCH_STANDARD_APP(video_write_overlay_session_function)
3360 {
3361 char *mydata;
3362 char *argv[3] = { 0 };
3363 int argc = 0;
3364 switch_img_position_t pos = POS_LEFT_BOT;
3365 uint8_t alpha = 255;
3366
3367 if (zstr(data)) {
3368 return;
3369 }
3370
3371 mydata = switch_core_session_strdup(session, data);
3372 argc = switch_split(mydata, ' ', argv);
3373
3374 if (argc > 1) {
3375 pos = parse_img_position(argv[1]);
3376 }
3377
3378 if (argc > 2) {
3379 int x = atoi(argv[2]);
3380 if (x > 0 && x < 256) {
3381 alpha = (uint8_t) x;
3382 }
3383 }
3384
3385 switch_ivr_video_write_overlay_session(session, argv[0], pos, alpha);
3386 }
3387
3388 SWITCH_STANDARD_APP(stop_video_write_overlay_session_function)
3389 {
3390 switch_ivr_stop_video_write_overlay_session(session);
3391 }
3392
3393 /********************************************************************************/
3394 /* Bridge Functions */
3395 /********************************************************************************/
3396
3397 static switch_status_t camp_fire(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
3398 {
3399 switch (itype) {
3400 case SWITCH_INPUT_TYPE_DTMF:
3401 {
3402 switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
3403 char *key = (char *) buf;
3404
3405 if (dtmf->digit == *key) {
3406 return SWITCH_STATUS_BREAK;
3407 }
3408 }
3409 default:
3410 break;
3411 }
3412
3413 return SWITCH_STATUS_SUCCESS;
3414 }
3415
3416 struct camping_stake {
3417 switch_core_session_t *session;
3418 int running;
3419 int do_xfer;
3420 const char *moh;
3421 };
3422
3423 static void *SWITCH_THREAD_FUNC camp_music_thread(switch_thread_t *thread, void *obj)
3424 {
3425 struct camping_stake *stake = (struct camping_stake *) obj;
3426 switch_core_session_t *session;
3427 switch_channel_t *channel;
3428 const char *moh = stake->moh, *greet = NULL;
3429 switch_input_args_t args = { 0 };
3430 char dbuf[2] = "";
3431 switch_status_t status = SWITCH_STATUS_FALSE;
3432 const char *stop;
3433
3434 session = stake->session;
3435
3436 if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) {
3437 return NULL;
3438 }
3439
3440 channel = switch_core_session_get_channel(stake->session);
3441
3442 if ((stop = switch_channel_get_variable(channel, "campon_stop_key"))) {
3443 *dbuf = *stop;
3444 }
3445
3446 args.input_callback = camp_fire;
3447 args.buf = dbuf;
3448 args.buflen = sizeof(dbuf);
3449
3450 /* don't set this to a local_stream:// or you will not be happy */
3451 if ((greet = switch_channel_get_variable(channel, "campon_announce_sound"))) {
3452 status = switch_ivr_play_file(session, NULL, greet, &args);
3453 }
3454
3455 while (stake->running && switch_channel_ready(channel)) {
3456 switch_ivr_parse_signal_data(session, SWITCH_TRUE, SWITCH_FALSE);
3457
3458 if (status != SWITCH_STATUS_BREAK) {
3459 if (!strcasecmp(moh, "silence")) {
3460 status = switch_ivr_collect_digits_callback(session, &args, 0, 0);
3461 } else {
3462 status = switch_ivr_play_file(session, NULL, stake->moh, &args);
3463 }
3464 }
3465
3466 if (status == SWITCH_STATUS_BREAK) {
3467 switch_channel_set_flag(channel, CF_NOT_READY);
3468 stake->do_xfer = 1;
3469 }
3470 }
3471 switch_core_session_rwunlock(session);
3472
3473 stake->running = 0;
3474
3475 return NULL;
3476 }
3477
3478 SWITCH_STANDARD_APP(audio_bridge_function)
3479 {
3480 switch_channel_t *caller_channel = switch_core_session_get_channel(session);
3481 switch_core_session_t *peer_session = NULL;
3482 const char *v_campon = NULL, *v_campon_retries, *v_campon_sleep, *v_campon_timeout, *v_campon_fallback_exten = NULL;
3483 switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
3484 int campon_retries = 100, campon_timeout = 10, campon_sleep = 10, tmp, camping = 0, fail = 0, thread_started = 0;
3485 struct camping_stake stake = { 0 };
3486 const char *moh = NULL;
3487 switch_thread_t *thread = NULL;
3488 switch_threadattr_t *thd_attr = NULL;
3489 char *camp_data = NULL;
3490 switch_status_t status = SWITCH_STATUS_FALSE;
3491 int camp_loops = 0;
3492
3493 if (zstr(data)) {
3494 return;
3495 }
3496
3497 if ((v_campon = switch_channel_get_variable(caller_channel, "campon")) && switch_true(v_campon)) {
3498 const char *cid_name = NULL;
3499 const char *cid_number = NULL;
3500
3501 if (!(cid_name = switch_channel_get_variable(caller_channel, "effective_caller_id_name"))) {
3502 cid_name = switch_channel_get_variable(caller_channel, "caller_id_name");
3503 }
3504
3505 if (!(cid_number = switch_channel_get_variable(caller_channel, "effective_caller_id_number"))) {
3506 cid_number = switch_channel_get_variable(caller_channel, "caller_id_number");
3507 }
3508
3509 if (cid_name && !cid_number) {
3510 cid_number = cid_name;
3511 }
3512
3513 if (cid_number && !cid_name) {
3514 cid_name = cid_number;
3515 }
3516
3517 v_campon_retries = switch_channel_get_variable(caller_channel, "campon_retries");
3518 v_campon_timeout = switch_channel_get_variable(caller_channel, "campon_timeout");
3519 v_campon_sleep = switch_channel_get_variable(caller_channel, "campon_sleep");
3520 v_campon_fallback_exten = switch_channel_get_variable(caller_channel, "campon_fallback_exten");
3521
3522 if (v_campon_retries) {
3523 if ((tmp = atoi(v_campon_retries)) > 0) {
3524 campon_retries = tmp;
3525 }
3526 }
3527
3528 if (v_campon_timeout) {
3529 if ((tmp = atoi(v_campon_timeout)) > 0) {
3530 campon_timeout = tmp;
3531 }
3532 }
3533
3534 if (v_campon_sleep) {
3535 if ((tmp = atoi(v_campon_sleep)) > 0) {
3536 campon_sleep = tmp;
3537 }
3538 }
3539
3540 switch_channel_answer(caller_channel);
3541 camping = 1;
3542
3543 if (cid_name && cid_number) {
3544 camp_data = switch_core_session_sprintf(session, "{origination_caller_id_name='%s',origination_caller_id_number='%s'}%s",
3545 cid_name, cid_number, data);
3546 } else {
3547 camp_data = (char *) data;
3548 }
3549
3550 if (!(moh = switch_channel_get_variable(caller_channel, "campon_hold_music"))) {
3551 moh = switch_channel_get_hold_music(caller_channel);
3552 }
3553
3554 if (!zstr(moh) && !strcasecmp(moh, "silence")) {
3555 moh = NULL;
3556 }
3557
3558 do {
3559 fail = 0;
3560
3561 if (!switch_channel_ready(caller_channel)) {
3562 fail = 1;
3563 break;
3564 }
3565
3566 if (status == SWITCH_STATUS_SUCCESS) {
3567 break;
3568 } else {
3569 fail = 1;
3570 }
3571
3572 if (!thread_started && fail && moh && !switch_channel_test_flag(caller_channel, CF_PROXY_MODE) &&
3573 !switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA) &&
3574 !switch_true(switch_channel_get_variable(caller_channel, "bypass_media"))) {
3575 switch_threadattr_create(&thd_attr, switch_core_session_get_pool(session));
3576 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
3577 stake.running = 1;
3578 stake.moh = moh;
3579 stake.session = session;
3580 switch_thread_create(&thread, thd_attr, camp_music_thread, &stake, switch_core_session_get_pool(session));
3581 thread_started = 1;
3582 }
3583
3584 if (camp_loops++) {
3585 int64_t wait = (int64_t)campon_sleep * 1000000;
3586
3587 if (--campon_retries <= 0 || stake.do_xfer) {
3588 stake.do_xfer = 1;
3589 break;
3590 }
3591
3592 while (stake.running && wait > 0 && switch_channel_ready(caller_channel)) {
3593 switch_yield(100000);
3594 wait -= 100000;
3595 }
3596 }
3597
3598 status = switch_ivr_originate(NULL, &peer_session,
3599 &cause, camp_data, campon_timeout, NULL, NULL, NULL, NULL, NULL, SOF_NONE,
3600 switch_channel_get_cause_ptr(caller_channel), NULL);
3601
3602
3603 } while (camping && switch_channel_ready(caller_channel));
3604
3605 if (thread) {
3606 stake.running = 0;
3607 switch_channel_set_flag(caller_channel, CF_NOT_READY);
3608 switch_thread_join(&status, thread);
3609 }
3610
3611 switch_channel_clear_flag(caller_channel, CF_NOT_READY);
3612
3613 if (stake.do_xfer && !zstr(v_campon_fallback_exten)) {
3614 switch_ivr_session_transfer(session,
3615 v_campon_fallback_exten,
3616 switch_channel_get_variable(caller_channel, "campon_fallback_dialplan"),
3617 switch_channel_get_variable(caller_channel, "campon_fallback_context"));
3618
3619 if (peer_session) {
3620 switch_channel_hangup(switch_core_session_get_channel(peer_session), SWITCH_CAUSE_ORIGINATOR_CANCEL);
3621 switch_core_session_rwunlock(peer_session);
3622 }
3623
3624 return;
3625 }
3626
3627 } else {
3628 if ((status =
3629 switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL)) != SWITCH_STATUS_SUCCESS) {
3630 fail = 1;
3631 }
3632 }
3633
3634 if (fail) {
3635 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Originate Failed. Cause: %s\n", switch_channel_cause2str(cause));
3636
3637 switch_channel_set_variable(caller_channel, "originate_failed_cause", switch_channel_cause2str(cause));
3638
3639 switch_channel_handle_cause(caller_channel, cause);
3640
3641 return;
3642 } else {
3643
3644 switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
3645 if (switch_true(switch_channel_get_variable(caller_channel, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE)) ||
3646 switch_true(switch_channel_get_variable(peer_channel, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE))) {
3647 switch_channel_set_flag(caller_channel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
3648 }
3649
3650 if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE)) {
3651 switch_ivr_signal_bridge(session, peer_session);
3652 } else {
3653 char *a_key = (char *) switch_channel_get_variable(caller_channel, "bridge_terminate_key");
3654 char *b_key = (char *) switch_channel_get_variable(peer_channel, "bridge_terminate_key");
3655 int ok = 0;
3656 switch_input_callback_function_t func = NULL;
3657
3658 if (a_key) {
3659 a_key = switch_core_session_strdup(session, a_key);
3660 ok++;
3661 }
3662 if (b_key) {
3663 b_key = switch_core_session_strdup(session, b_key);
3664 ok++;
3665 }
3666 if (ok) {
3667 func = bridge_on_dtmf;
3668 } else {
3669 a_key = NULL;
3670 b_key = NULL;
3671 }
3672
3673 switch_ivr_multi_threaded_bridge(session, peer_session, func, a_key, b_key);
3674 }
3675
3676 if (peer_session) {
3677 switch_core_session_rwunlock(peer_session);
3678 }
3679 }
3680 }
3681
3682 static struct {
3683 switch_memory_pool_t *pool;
3684 switch_hash_t *pickup_hash;
3685 switch_mutex_t *pickup_mutex;
3686 switch_hash_t *mutex_hash;
3687 switch_mutex_t *mutex_mutex;
3688 } globals;
3689
3690 /* pickup channel */
3691
3692
3693
3694 typedef struct pickup_node_s {
3695 char *key;
3696 char *uuid;
3697 struct pickup_node_s *next;
3698 } pickup_node_t;
3699
3700
3701 #define PICKUP_PROTO "pickup"
3702 static int EC = 0;
3703
3704 static int pickup_count(const char *key_name)
3705 {
3706 int count = 0;
3707 pickup_node_t *head, *np;
3708
3709 switch_mutex_lock(globals.pickup_mutex);
3710 if ((head = switch_core_hash_find(globals.pickup_hash, key_name))) {
3711 for (np = head; np; np = np->next) count++;
3712 }
3713 switch_mutex_unlock(globals.pickup_mutex);
3714
3715 return count;
3716
3717 }
3718
3719 static void pickup_send_presence(const char *key_name)
3720 {
3721
3722 char *domain_name, *dup_key_name = NULL, *dup_domain_name = NULL, *dup_id = NULL;
3723 switch_event_t *event;
3724 int count;
3725
3726
3727 dup_key_name = strdup(key_name);
3728 switch_assert(dup_key_name);
3729 key_name = dup_key_name;
3730
3731 if ((domain_name = strchr(dup_key_name, '@'))) {
3732 *domain_name++ = '\0';
3733 }
3734
3735 if (zstr(domain_name)) {
3736 dup_domain_name = switch_core_get_domain(SWITCH_TRUE);
3737 domain_name = dup_domain_name;
3738 }
3739
3740 if (zstr(domain_name)) {
3741 domain_name = "cluecon.com";
3742 }
3743
3744 dup_id = switch_mprintf("%s@%s", key_name, domain_name);
3745
3746 count = pickup_count(dup_id);
3747
3748 if (count > 0) {
3749 if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
3750 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", PICKUP_PROTO);
3751 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", dup_id);
3752 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", dup_id);
3753
3754
3755 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "force-status", "Active (%d call%s)", count, count == 1 ? "" : "s");
3756 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "active");
3757 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
3758 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
3759 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++);
3760 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", key_name);
3761 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING");
3762 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "confirmed");
3763 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound");
3764 switch_event_fire(&event);
3765 }
3766 } else {
3767 if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
3768 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", PICKUP_PROTO);
3769 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", dup_id);
3770 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", dup_id);
3771
3772
3773 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", "Idle");
3774 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
3775 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
3776 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
3777 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++);
3778 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", dup_id);
3779 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP");
3780 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "terminated");
3781 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound");
3782 switch_event_fire(&event);
3783 }
3784 }
3785
3786 switch_safe_free(dup_domain_name);
3787 switch_safe_free(dup_key_name);
3788 switch_safe_free(dup_id);
3789
3790 }
3791
3792 static void pickup_pres_event_handler(switch_event_t *event)
3793 {
3794 char *to = switch_event_get_header(event, "to");
3795 char *dup_to = NULL, *key_name, *dup_key_name = NULL, *domain_name, *dup_domain_name = NULL;
3796 int count = 0;
3797
3798 if (!to || strncasecmp(to, "pickup+", 7) || !strchr(to, '@')) {
3799 return;
3800 }
3801
3802 if (!(dup_to = strdup(to))) {
3803 return;
3804 }
3805
3806 key_name = dup_to + 7;
3807
3808 if ((domain_name = strchr(key_name, '@'))) {
3809 *domain_name++ = '\0';
3810 } else {
3811 dup_domain_name = switch_core_get_domain(SWITCH_TRUE);
3812 domain_name = dup_domain_name;
3813 }
3814
3815 if (zstr(domain_name)) {
3816 switch_safe_free(dup_to);
3817 switch_safe_free(dup_domain_name);
3818 return;
3819 }
3820
3821 dup_key_name = switch_mprintf("%q@%q", key_name, domain_name);
3822 count = pickup_count(dup_key_name);
3823
3824 switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN);
3825
3826 if (count) {
3827 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", PICKUP_PROTO);
3828 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", key_name);
3829 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", key_name, domain_name);
3830
3831 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "force-status", "Active (%d call%s)", count, count == 1 ? "" : "s");
3832 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "active");
3833 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
3834 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
3835 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++);
3836 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", key_name);
3837 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING");
3838 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "confirmed");
3839 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound");
3840 } else {
3841 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", PICKUP_PROTO);
3842 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", key_name);
3843 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", key_name, domain_name);
3844
3845 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", "Idle");
3846 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
3847 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
3848 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
3849 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++);
3850 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", key_name);
3851 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP");
3852 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "terminated");
3853 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound");
3854
3855 }
3856
3857 switch_event_fire(&event);
3858 switch_safe_free(dup_to);
3859 switch_safe_free(dup_key_name);
3860 switch_safe_free(dup_domain_name);
3861 }
3862
3863
3864
3865 static void pickup_add_session(switch_core_session_t *session, const char *key)
3866 {
3867 pickup_node_t *head, *node, *np;
3868 char *dup_key = NULL;
3869
3870 if (!strchr(key, '@')) {
3871 dup_key = switch_mprintf("%s@%s", key, switch_core_get_domain(SWITCH_FALSE));
3872 key = dup_key;
3873 }
3874
3875 switch_zmalloc(node, sizeof(*node));
3876 switch_assert(node);
3877 node->key = strdup(key);
3878 node->uuid = strdup(switch_core_session_get_uuid(session));
3879 node->next = NULL;
3880
3881 switch_mutex_lock(globals.pickup_mutex);
3882 head = switch_core_hash_find(globals.pickup_hash, key);
3883
3884 if (head) {
3885 for (np = head; np && np->next; np = np->next);
3886 np->next = node;
3887 } else {
3888 head = node;
3889 switch_core_hash_insert(globals.pickup_hash, key, head);
3890 }
3891
3892 switch_mutex_unlock(globals.pickup_mutex);
3893
3894 pickup_send_presence(key);
3895
3896 switch_safe_free(dup_key);
3897 }
3898
3899 static char *pickup_pop_uuid(const char *key, const char *uuid)
3900 {
3901 pickup_node_t *node = NULL, *head;
3902 char *r = NULL;
3903 char *dup_key = NULL;
3904
3905 if (!strchr(key, '@')) {
3906 dup_key = switch_mprintf("%s@%s", key, switch_core_get_domain(SWITCH_FALSE));
3907 key = dup_key;
3908 }
3909
3910 switch_mutex_lock(globals.pickup_mutex);
3911
3912 if ((head = switch_core_hash_find(globals.pickup_hash, key))) {
3913
3914 switch_core_hash_delete(globals.pickup_hash, key);
3915
3916 if (uuid) {
3917 pickup_node_t *np, *lp = NULL;
3918
3919 for(np = head; np; np = np->next) {
3920 if (!strcmp(np->uuid, uuid)) {
3921 if (lp) {
3922 lp->next = np->next;
3923 } else {
3924 head = np->next;
3925 }
3926
3927 node = np;
3928 break;
3929 }
3930
3931 lp = np;
3932 }
3933
3934 } else {
3935 node = head;
3936 head = head->next;
3937 }
3938
3939
3940 if (head) {
3941 switch_core_hash_insert(globals.pickup_hash, key, head);
3942 }
3943 }
3944
3945 if (node) {
3946 r = node->uuid;
3947 free(node->key);
3948 free(node);
3949 }
3950
3951 switch_mutex_unlock(globals.pickup_mutex);
3952
3953 if (r) pickup_send_presence(key);
3954
3955 switch_safe_free(dup_key);
3956
3957 return r;
3958 }
3959
3960
3961 typedef struct pickup_pvt_s {
3962 char *key;
3963 switch_event_t *vars;
3964 } pickup_pvt_t;
3965
3966 switch_endpoint_interface_t *pickup_endpoint_interface;
3967 static switch_call_cause_t pickup_outgoing_channel(switch_core_session_t *session,
3968 switch_event_t *var_event,
3969 switch_caller_profile_t *outbound_profile,
3970 switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
3971 switch_call_cause_t *cancel_cause);
3972 switch_io_routines_t pickup_io_routines = {
3973 /*.outgoing_channel */ pickup_outgoing_channel
3974 };
3975
3976 static switch_status_t pickup_event_handler(switch_core_session_t *session)
3977 {
3978 switch_channel_t *channel = switch_core_session_get_channel(session);
3979 switch_channel_state_t state = switch_channel_get_running_state(channel);
3980 pickup_pvt_t *tech_pvt = switch_core_session_get_private(session);
3981 char *uuid = NULL;
3982
3983 switch(state) {
3984 case CS_DESTROY:
3985 if (tech_pvt->vars) {
3986 switch_event_destroy(&tech_pvt->vars);
3987 }
3988 break;
3989 case CS_REPORTING:
3990 return SWITCH_STATUS_FALSE;
3991 case CS_HANGUP:
3992 {
3993
3994 if (switch_channel_test_flag(channel, CF_CHANNEL_SWAP)) {
3995 const char *key = switch_channel_get_variable(channel, "channel_swap_uuid");
3996 switch_core_session_t *swap_session;
3997
3998 if ((swap_session = switch_core_session_locate(key))) {
3999 switch_channel_t *swap_channel = switch_core_session_get_channel(swap_session);
4000 switch_channel_hangup(swap_channel, SWITCH_CAUSE_PICKED_OFF);
4001 switch_core_session_rwunlock(swap_session);
4002 }
4003 switch_channel_clear_flag(channel, CF_CHANNEL_SWAP);
4004 }
4005
4006 uuid = pickup_pop_uuid(tech_pvt->key, switch_core_session_get_uuid(session));
4007 switch_safe_free(uuid);
4008 }
4009 break;
4010 default:
4011 break;
4012 }
4013
4014
4015 return SWITCH_STATUS_SUCCESS;
4016 }
4017
4018 switch_state_handler_table_t pickup_event_handlers = {
4019 /*.on_init */ pickup_event_handler,
4020 /*.on_routing */ pickup_event_handler,
4021 /*.on_execute */ pickup_event_handler,
4022 /*.on_hangup */ pickup_event_handler,
4023 /*.on_exchange_media */ pickup_event_handler,
4024 /*.on_soft_execute */ pickup_event_handler,
4025 /*.on_consume_media */ pickup_event_handler,
4026 /*.on_hibernate */ pickup_event_handler,
4027 /*.on_reset */ pickup_event_handler,
4028 /*.on_park */ pickup_event_handler,
4029 /*.on_reporting */ pickup_event_handler,
4030 /*.on_destroy */ pickup_event_handler
4031 };
4032
4033 static switch_call_cause_t pickup_outgoing_channel(switch_core_session_t *session,
4034 switch_event_t *var_event,
4035 switch_caller_profile_t *outbound_profile,
4036 switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
4037 switch_call_cause_t *cancel_cause)
4038 {
4039 char *pickup;
4040 switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
4041 switch_core_session_t *nsession;
4042 switch_channel_t *nchannel;
4043 char *name;
4044 pickup_pvt_t *tech_pvt;
4045 switch_caller_profile_t *caller_profile;
4046
4047 if (zstr(outbound_profile->destination_number)) {
4048 goto done;
4049 }
4050
4051 pickup = outbound_profile->destination_number;
4052
4053 flags |= SOF_NO_LIMITS;
4054
4055 if (!(nsession = switch_core_session_request_uuid(pickup_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND,
4056 flags, pool, switch_event_get_header(var_event, "origination_uuid")))) {
4057
4058 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error Creating Session\n");
4059 goto error;
4060 }
4061
4062 tech_pvt = switch_core_session_alloc(nsession, sizeof(*tech_pvt));
4063 tech_pvt->key = switch_core_session_strdup(nsession, pickup);
4064
4065
4066 switch_core_session_set_private(nsession, tech_pvt);
4067
4068 nchannel = switch_core_session_get_channel(nsession);
4069 switch_channel_set_cap(nchannel, CC_PROXY_MEDIA);
4070 switch_channel_set_cap(nchannel, CC_BYPASS_MEDIA);
4071
4072 caller_profile = switch_caller_profile_clone(nsession, outbound_profile);
4073 switch_channel_set_caller_profile(nchannel, caller_profile);
4074
4075 switch_channel_set_state(nchannel, CS_ROUTING);
4076
4077
4078
4079 *new_session = nsession;
4080 cause = SWITCH_CAUSE_SUCCESS;
4081 name = switch_core_session_sprintf(nsession, "pickup/%s", pickup);
4082 switch_channel_set_name(nchannel, name);
4083 switch_channel_set_variable(nchannel, "process_cdr", "false");
4084 switch_channel_set_variable(nchannel, "presence_id", NULL);
4085
4086 switch_event_del_header(var_event, "presence_id");
4087
4088 pickup_add_session(nsession, pickup);
4089 switch_channel_set_flag(nchannel, CF_PICKUP);
4090 switch_channel_set_flag(nchannel, CF_NO_PRESENCE);
4091
4092 switch_event_dup(&tech_pvt->vars, var_event);
4093
4094 goto done;
4095
4096 error:
4097
4098 if (pool) {
4099 *pool = NULL;
4100 }
4101
4102 done:
4103
4104
4105 return cause;
4106 }
4107
4108 #define PICKUP_SYNTAX "[<key>]"
4109 SWITCH_STANDARD_APP(pickup_function)
4110 {
4111 char *uuid = NULL;
4112 switch_core_session_t *pickup_session;
4113 switch_channel_t *channel = switch_core_session_get_channel(session);
4114
4115 if (zstr(data)) {
4116 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Missing data. Usage: pickup %s\n", PICKUP_SYNTAX);
4117 return;
4118 }
4119
4120 if ((uuid = pickup_pop_uuid((char *)data, NULL))) {
4121 if ((pickup_session = switch_core_session_locate(uuid))) {
4122 switch_channel_t *pickup_channel = switch_core_session_get_channel(pickup_session);
4123 switch_caller_profile_t *pickup_caller_profile = switch_channel_get_caller_profile(pickup_channel),
4124 *caller_profile = switch_channel_get_caller_profile(channel);
4125 const char *name, *num;
4126 switch_event_t *event;
4127 switch_event_header_t *hp;
4128 pickup_pvt_t *tech_pvt = switch_core_session_get_private(pickup_session);
4129
4130 for(hp = tech_pvt->vars->headers; hp; hp = hp->next) {
4131 switch_channel_set_variable(channel, hp->name, hp->value);
4132 }
4133
4134
4135 switch_channel_set_flag(pickup_channel, CF_CHANNEL_SWAP);
4136 switch_channel_set_variable(pickup_channel, "channel_swap_uuid", switch_core_session_get_uuid(session));
4137
4138 name = caller_profile->caller_id_name;
4139 num = caller_profile->caller_id_number;
4140
4141 caller_profile->caller_id_name = switch_core_strdup(caller_profile->pool, pickup_caller_profile->caller_id_name);
4142 caller_profile->caller_id_number = switch_core_strdup(caller_profile->pool, pickup_caller_profile->caller_id_number);
4143
4144 caller_profile->callee_id_name = name;
4145 caller_profile->callee_id_number = num;
4146
4147 if (switch_event_create(&event, SWITCH_EVENT_CALL_UPDATE) == SWITCH_STATUS_SUCCESS) {
4148 const char *partner_uuid = switch_channel_get_partner_uuid(channel);
4149 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Direction", "RECV");
4150
4151 if (partner_uuid) {
4152 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridged-To", partner_uuid);
4153 }
4154 switch_channel_event_set_data(channel, event);
4155 switch_event_fire(&event);
4156 }
4157
4158
4159 switch_channel_set_state(channel, CS_HIBERNATE);
4160
4161 switch_channel_mark_answered(pickup_channel);
4162 switch_core_session_rwunlock(pickup_session);
4163 }
4164 free(uuid);
4165 }
4166 }
4167
4168
4169
4170
4171
4172 /* fake chan_error */
4173 switch_endpoint_interface_t *error_endpoint_interface;
4174 static switch_call_cause_t error_outgoing_channel(switch_core_session_t *session,
4175 switch_event_t *var_event,
4176 switch_caller_profile_t *outbound_profile,
4177 switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
4178 switch_call_cause_t *cancel_cause);
4179 switch_io_routines_t error_io_routines = {
4180 /*.outgoing_channel */ error_outgoing_channel
4181 };
4182
4183 static switch_call_cause_t error_outgoing_channel(switch_core_session_t *session,
4184 switch_event_t *var_event,
4185 switch_caller_profile_t *outbound_profile,
4186 switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
4187 switch_call_cause_t *cancel_cause)
4188 {
4189 switch_call_cause_t cause = switch_channel_str2cause(outbound_profile->destination_number);
4190 if (cause == SWITCH_CAUSE_NONE) {
4191 cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
4192 }
4193
4194 return cause;
4195 }
4196
4197
4198 /* fake chan_group */
4199 switch_endpoint_interface_t *group_endpoint_interface;
4200 static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session,
4201 switch_event_t *var_event,
4202 switch_caller_profile_t *outbound_profile,
4203 switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
4204 switch_call_cause_t *cancel_cause);
4205 switch_io_routines_t group_io_routines = {
4206 /*.outgoing_channel */ group_outgoing_channel
4207 };
4208
4209 static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session,
4210 switch_event_t *var_event,
4211 switch_caller_profile_t *outbound_profile,
4212 switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
4213 switch_call_cause_t *cancel_cause)
4214 {
4215 char *group = NULL;
4216 switch_call_cause_t cause = SWITCH_CAUSE_NONE;
4217 char *template = NULL, *dest = NULL;
4218 switch_originate_flag_t myflags = SOF_NONE;
4219 char *cid_name_override = NULL;
4220 char *cid_num_override = NULL;
4221 char *domain = NULL, *dup_domain = NULL;
4222 switch_channel_t *new_channel = NULL;
4223 unsigned int timelimit = SWITCH_DEFAULT_TIMEOUT;
4224 const char *skip, *var;
4225
4226 group = strdup(outbound_profile->destination_number);
4227
4228 if (!group)
4229 goto done;
4230
4231 if ((domain = strchr(group, '@'))) {
4232 *domain++ = '\0';
4233 } else {
4234 domain = switch_core_get_domain(SWITCH_TRUE);
4235 dup_domain = domain;
4236 }
4237
4238 if (!domain) {
4239 goto done;
4240 }
4241
4242 if (var_event && (skip = switch_event_get_header(var_event, "group_recurse_variables")) && switch_false(skip)) {
4243 if ((var = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) || (var = switch_event_get_header(var_event, "leg_timeout"))) {
4244 timelimit = atoi(var);
4245 }
4246 var_event = NULL;
4247 }
4248
4249 template = switch_mprintf("${group_call(%s@%s)}", group, domain);
4250
4251 if (session) {
4252 switch_channel_t *channel = switch_core_session_get_channel(session);
4253 dest = switch_channel_expand_variables(channel, template);
4254 if ((var = switch_channel_get_variable(channel, SWITCH_CALL_TIMEOUT_VARIABLE)) || (var = switch_event_get_header(var_event, "leg_timeout"))) {
4255 timelimit = atoi(var);
4256 }
4257 } else if (var_event) {
4258 dest = switch_event_expand_headers(var_event, template);
4259 } else {
4260 switch_event_t *event = NULL;
4261 switch_event_create(&event, SWITCH_EVENT_REQUEST_PARAMS);
4262 dest = switch_event_expand_headers(event, template);
4263 switch_event_destroy(&event);
4264 }
4265
4266 if (!dest) {
4267 goto done;
4268 }
4269
4270 if (var_event) {
4271 cid_name_override = switch_event_get_header(var_event, "origination_caller_id_name");
4272 cid_num_override = switch_event_get_header(var_event, "origination_caller_id_number");
4273 if ((var = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) || (var = switch_event_get_header(var_event, "leg_timeout"))) {
4274 timelimit = atoi(var);
4275 }
4276 }
4277
4278 if ((flags & SOF_FORKED_DIAL)) {
4279 myflags |= SOF_NOBLOCK;
4280 }
4281
4282
4283 if (switch_ivr_originate(session, new_session, &cause, dest, timelimit, NULL,
4284 cid_name_override, cid_num_override, NULL, var_event, myflags, cancel_cause, NULL) == SWITCH_STATUS_SUCCESS) {
4285 const char *context;
4286 switch_caller_profile_t *cp;
4287
4288 new_channel = switch_core_session_get_channel(*new_session);
4289
4290 if ((context = switch_channel_get_variable(new_channel, "group_context"))) {
4291 if ((cp = switch_channel_get_caller_profile(new_channel))) {
4292 cp->context = switch_core_strdup(cp->pool, context);
4293 }
4294 }
4295 switch_core_session_rwunlock(*new_session);
4296 }
4297
4298
4299 done:
4300
4301 if (dest && dest != template) {
4302 switch_safe_free(dest);
4303 }
4304
4305 switch_safe_free(template);
4306 switch_safe_free(group);
4307 switch_safe_free(dup_domain);
4308
4309 if (cause == SWITCH_CAUSE_NONE) {
4310 cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
4311 }
4312
4313 return cause;
4314 }
4315
4316
4317
4318 /* fake chan_user */
4319 switch_endpoint_interface_t *user_endpoint_interface;
4320 static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
4321 switch_event_t *var_event,
4322 switch_caller_profile_t *outbound_profile,
4323 switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
4324 switch_call_cause_t *cancel_cause);
4325 switch_io_routines_t user_io_routines = {
4326 /*.outgoing_channel */ user_outgoing_channel
4327 };
4328
4329 static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
4330 switch_event_t *var_event,
4331 switch_caller_profile_t *outbound_profile,
4332 switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
4333 switch_call_cause_t *cancel_cause)
4334 {
4335 switch_xml_t x_user = NULL, x_param, x_params;
4336 char *user = NULL, *domain = NULL, *dup_domain = NULL, *dialed_user = NULL;
4337 const char *dest = NULL;
4338 switch_call_cause_t cause = SWITCH_CAUSE_NONE;
4339 unsigned int timelimit = SWITCH_DEFAULT_TIMEOUT;
4340 switch_channel_t *new_channel = NULL;
4341 switch_event_t *params = NULL, *var_event_orig = var_event;
4342 char stupid[128] = "";
4343 const char *skip = NULL, *var = NULL;
4344
4345 if (zstr(outbound_profile->destination_number)) {
4346 goto done;
4347 }
4348
4349 user = strdup(outbound_profile->destination_number);
4350
4351 if (!user)
4352 goto done;
4353
4354 if ((domain = strchr(user, '@'))) {
4355 *domain++ = '\0';
4356 } else {
4357 domain = switch_core_get_domain(SWITCH_TRUE);
4358 dup_domain = domain;
4359 }
4360
4361 if (!domain) {
4362 goto done;
4363 }
4364
4365
4366 switch_event_create(&params, SWITCH_EVENT_REQUEST_PARAMS);
4367 switch_assert(params);
4368 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "as_channel", "true");
4369 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "action", "user_call");
4370
4371 if (var_event) {
4372 switch_event_merge(params, var_event);
4373 }
4374
4375 if (var_event && (skip = switch_event_get_header(var_event, "user_recurse_variables")) && switch_false(skip)) {
4376 if ((var = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) || (var = switch_event_get_header(var_event, "leg_timeout"))) {
4377 timelimit = atoi(var);
4378 }
4379 var_event = NULL;
4380 }
4381
4382 if (switch_xml_locate_user_merged("id", user, domain, NULL, &x_user, params) != SWITCH_STATUS_SUCCESS) {
4383 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Can't find user [%s@%s]\n", user, domain);
4384 cause = SWITCH_CAUSE_SUBSCRIBER_ABSENT;
4385 goto done;
4386 }
4387
4388 if ((x_params = switch_xml_child(x_user, "params"))) {
4389 for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
4390 const char *pvar = switch_xml_attr_soft(x_param, "name");
4391 const char *val = switch_xml_attr(x_param, "value");
4392
4393 if (!strcasecmp(pvar, "dial-string")) {
4394 dest = val;
4395 } else if (!strncasecmp(pvar, "dial-var-", 9)) {
4396 if (!var_event) {
4397 switch_event_create(&var_event, SWITCH_EVENT_GENERAL);
4398 } else {
4399 switch_event_del_header(var_event, pvar + 9);
4400 }
4401 switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, pvar + 9, val);
4402 }
4403 }
4404 }
4405
4406 dialed_user = (char *)switch_xml_attr(x_user, "id");
4407
4408 if (var_event) {
4409 switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_user", dialed_user);
4410 switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
4411 if (!zstr(dest) && !strstr(dest, "presence_id=")) {
4412 switch_event_add_header(var_event, SWITCH_STACK_BOTTOM, "presence_id", "%s@%s", dialed_user, domain);
4413 }
4414 }
4415
4416 if (!dest) {
4417 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No dial-string available, please check your user directory.\n");
4418 cause = SWITCH_CAUSE_MANDATORY_IE_MISSING;
4419 } else {
4420 const char *varval;
4421 char *d_dest = NULL;
4422 switch_channel_t *channel;
4423 switch_originate_flag_t myflags = SOF_NONE;
4424 char *cid_name_override = NULL;
4425 char *cid_num_override = NULL;
4426
4427 if (var_event) {
4428 cid_name_override = switch_event_get_header(var_event, "origination_caller_id_name");
4429 cid_num_override = switch_event_get_header(var_event, "origination_caller_id_number");
4430 }
4431
4432 if (session) {
4433 channel = switch_core_session_get_channel(session);
4434 if ((varval = switch_channel_get_variable(channel, SWITCH_CALL_TIMEOUT_VARIABLE))
4435 || (var_event && (varval = switch_event_get_header(var_event, "leg_timeout")))) {
4436 timelimit = atoi(varval);
4437 }
4438
4439 switch_channel_set_variable(channel, "dialed_user", dialed_user);
4440 switch_channel_set_variable(channel, "dialed_domain", domain);
4441
4442 d_dest = switch_channel_expand_variables(channel, dest);
4443
4444 } else {
4445 switch_event_t *event = NULL;
4446
4447 if (var_event) {
4448 switch_event_dup(&event, var_event);
4449 switch_event_del_header(event, "dialed_user");
4450 switch_event_del_header(event, "dialed_domain");
4451 if ((varval = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) ||
4452 (varval = switch_event_get_header(var_event, "leg_timeout"))) {
4453 timelimit = atoi(varval);
4454 }
4455 } else {
4456 switch_event_create(&event, SWITCH_EVENT_REQUEST_PARAMS);
4457 switch_assert(event);
4458 }
4459
4460 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_user", dialed_user);
4461 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
4462 d_dest = switch_event_expand_headers(event, dest);
4463 switch_event_destroy(&event);
4464 }
4465
4466 if ((flags & SOF_NO_LIMITS)) {
4467 myflags |= SOF_NO_LIMITS;
4468 }
4469
4470 if ((flags & SOF_FORKED_DIAL)) {
4471 myflags |= SOF_NOBLOCK;
4472 }
4473
4474
4475 switch_snprintf(stupid, sizeof(stupid), "user/%s", dialed_user);
4476 if (switch_stristr(stupid, d_dest)) {
4477 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Waddya Daft? You almost called '%s' in an infinate loop!\n",
4478 stupid);
4479 cause = SWITCH_CAUSE_INVALID_IE_CONTENTS;
4480 } else if (switch_ivr_originate(session, new_session, &cause, d_dest, timelimit, NULL,
4481 cid_name_override, cid_num_override, outbound_profile, var_event, myflags,
4482 cancel_cause, NULL) == SWITCH_STATUS_SUCCESS) {
4483 const char *context;
4484 switch_caller_profile_t *cp;
4485
4486 if (var_event) {
4487 switch_event_del_header(var_event, "origination_uuid");
4488 }
4489
4490
4491 new_channel = switch_core_session_get_channel(*new_session);
4492
4493 if ((context = switch_channel_get_variable(new_channel, "user_context"))) {
4494 if ((cp = switch_channel_get_caller_profile(new_channel))) {
4495 cp->context = switch_core_strdup(cp->pool, context);
4496 }
4497 }
4498 switch_core_session_rwunlock(*new_session);
4499 }
4500
4501 if (d_dest != dest) {
4502 switch_safe_free(d_dest);
4503 }
4504 }
4505
4506 if (new_channel && x_user) {
4507 if ((x_params = switch_xml_child(x_user, "variables"))) {
4508 for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
4509 const char *pvar = switch_xml_attr(x_param, "name");
4510 const char *val = switch_xml_attr(x_param, "value");
4511 switch_channel_set_variable(new_channel, pvar, val);
4512 }
4513 }
4514 }
4515
4516 done:
4517
4518 if (x_user) {
4519 switch_xml_free(x_user);
4520 }
4521
4522 if (params) {
4523 switch_event_destroy(&params);
4524 }
4525
4526 if (var_event && var_event_orig != var_event) {
4527 switch_event_destroy(&var_event);
4528 }
4529
4530 switch_safe_free(user);
4531 switch_safe_free(dup_domain);
4532
4533 return cause;
4534 }
4535
4536 #define HOLD_SYNTAX "[<display message>]"
4537 SWITCH_STANDARD_APP(hold_function)
4538 {
4539 switch_ivr_hold_uuid(switch_core_session_get_uuid(session), data, 1);
4540 }
4541
4542 #define UNHOLD_SYNTAX ""
4543 SWITCH_STANDARD_APP(unhold_function)
4544 {
4545 switch_ivr_unhold_uuid(switch_core_session_get_uuid(session));
4546 }
4547
4548 SWITCH_STANDARD_APP(novideo_function)
4549 {
4550 switch_channel_set_flag(switch_core_session_get_channel(session), CF_NOVIDEO);
4551 }
4552
4553 SWITCH_STANDARD_APP(verbose_events_function)
4554 {
4555 switch_channel_set_flag(switch_core_session_get_channel(session), CF_VERBOSE_EVENTS);
4556 }
4557
4558 SWITCH_STANDARD_APP(cng_plc_function)
4559 {
4560 switch_channel_set_flag(switch_core_session_get_channel(session), CF_CNG_PLC);
4561 }
4562
4563 SWITCH_STANDARD_APP(early_hangup_function)
4564 {
4565 switch_channel_set_flag(switch_core_session_get_channel(session), CF_EARLY_HANGUP);
4566 }
4567
4568 #define WAIT_FOR_SILENCE_SYNTAX "<silence_thresh> <silence_hits> <listen_hits> <timeout_ms> [<file>]"
4569 SWITCH_STANDARD_APP(wait_for_silence_function)
4570 {
4571 char *argv[5] = { 0 };
4572 uint32_t thresh, silence_hits, listen_hits, timeout_ms = 0;
4573 char *lbuf = NULL;
4574
4575 if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
4576 && switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))) >= 4) {
4577 thresh = atoi(argv[0]);
4578 silence_hits = atoi(argv[1]);
4579 listen_hits = atoi(argv[2]);
4580
4581 if (argv[3]) {
4582 timeout_ms = switch_atoui(argv[3]);
4583 }
4584
4585 if (thresh > 0 && silence_hits > 0) {
4586 switch_ivr_wait_for_silence(session, thresh, silence_hits, listen_hits, timeout_ms, argv[4]);
4587 return;
4588 }
4589
4590 }
4591
4592 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", WAIT_FOR_SILENCE_SYNTAX);
4593 }
4594
4595 #define DETECT_AUDIO_SYNTAX "<threshold> <audio_hits> <timeout_ms> [<file>]"
4596 SWITCH_STANDARD_APP(detect_audio_function)
4597 {
4598 char *argv[4] = { 0 };
4599 uint32_t thresh, audio_hits, timeout_ms = 0;
4600 char *lbuf = NULL;
4601
4602 if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
4603 && switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))) >= 3) {
4604 thresh = atoi(argv[0]);
4605 audio_hits = atoi(argv[1]);
4606 timeout_ms = atoi(argv[2]);
4607
4608 if (thresh > 0 && audio_hits > 0) {
4609 switch_ivr_detect_audio(session, thresh, audio_hits, timeout_ms, argv[3]);
4610 return;
4611 }
4612
4613 }
4614
4615 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", DETECT_AUDIO_SYNTAX);
4616 }
4617
4618 #define DETECT_SILENCE_SYNTAX "<threshold> <silence_hits> <timeout_ms> [<file>]"
4619 SWITCH_STANDARD_APP(detect_silence_function)
4620 {
4621 char *argv[4] = { 0 };
4622 uint32_t thresh, silence_hits, timeout_ms = 0;
4623 char *lbuf = NULL;
4624
4625 if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
4626 && switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))) >= 3) {
4627 thresh = atoi(argv[0]);
4628 silence_hits = atoi(argv[1]);
4629 timeout_ms = atoi(argv[2]);
4630
4631 if (thresh > 0 && silence_hits > 0) {
4632 switch_ivr_detect_silence(session, thresh, silence_hits, timeout_ms, argv[3]);
4633 return;
4634 }
4635
4636 }
4637
4638 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", DETECT_SILENCE_SYNTAX);
4639 }
4640
4641 static switch_status_t event_chat_send(switch_event_t *message_event)
4642
4643 {
4644 switch_event_t *event;
4645 const char *to;
4646
4647 switch_event_dup(&event, message_event);
4648 event->event_id = SWITCH_EVENT_RECV_MESSAGE;
4649
4650 if ((to = switch_event_get_header(event, "to"))) {
4651 char *v;
4652 if ((v = switch_core_get_variable_dup(to))) {
4653 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Command", v);
4654 free(v);
4655 }
4656 }
4657
4658 if (switch_event_fire(&event) == SWITCH_STATUS_SUCCESS) {
4659 return SWITCH_STATUS_SUCCESS;
4660 }
4661
4662 switch_event_destroy(&event);
4663
4664 return SWITCH_STATUS_MEMERR;
4665 }
4666
4667 static switch_status_t api_chat_send(switch_event_t *message_event)
4668 {
4669 const char *proto;
4670 const char *from;
4671 const char *to;
4672 //const char *subject;
4673 //const char *body;
4674 const char *type;
4675 const char *hint;
4676
4677 proto = switch_event_get_header(message_event, "proto");
4678 from = switch_event_get_header(message_event, "from");
4679 to = switch_event_get_header(message_event, "to");
4680 //subject = switch_event_get_header(message_event, "subject");
4681 //body = switch_event_get_body(message_event);
4682 type = switch_event_get_header(message_event, "type");
4683 hint = switch_event_get_header(message_event, "hint");
4684
4685
4686 if (to) {
4687 char *v = NULL;
4688 switch_stream_handle_t stream = { 0 };
4689 char *cmd = NULL, *arg;
4690
4691 if (!(v = switch_core_get_variable_dup(to))) {
4692 v = strdup(to);
4693 }
4694
4695 cmd = v;
4696 switch_assert(cmd);
4697
4698 switch_url_decode(cmd);
4699
4700 if ((arg = strchr(cmd, ' '))) {
4701 *arg++ = '\0';
4702 }
4703
4704 SWITCH_STANDARD_STREAM(stream);
4705 switch_api_execute(cmd, arg, NULL, &stream);
4706
4707 if (proto) {
4708 switch_core_chat_send_args(proto, "api", to, hint && strchr(hint, '/') ? hint : from, !zstr(type) ? type : NULL, (char *) stream.data, NULL, NULL, SWITCH_TRUE);
4709 }
4710
4711 switch_safe_free(stream.data);
4712
4713 free(cmd);
4714
4715 }
4716
4717 return SWITCH_STATUS_SUCCESS;
4718 }
4719
4720
4721 #define SESSION_LOGLEVEL_SYNTAX "<level>"
4722 SWITCH_STANDARD_APP(session_loglevel_function)
4723 {
4724 if (!zstr(data)) {
4725 switch_log_level_t level = switch_log_str2level(data);
4726
4727 if (level == SWITCH_LOG_INVALID) {
4728 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid log level: %s\n", data);
4729 } else {
4730 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setting log level \"%s\" on session\n", switch_log_level2str(level));
4731 switch_core_session_set_loglevel(session, level);
4732 }
4733 } else {
4734 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No log level specified\n");
4735 }
4736 }
4737
4738 /* LIMIT STUFF */
4739 #define LIMIT_USAGE "<backend> <realm> <id> [<max>[/interval]] [number [dialplan [context]]]"
4740 #define LIMIT_DESC "limit access to a resource and transfer to an extension if the limit is exceeded"
4741 SWITCH_STANDARD_APP(limit_function)
4742 {
4743 int argc = 0;
4744 char *argv[7] = { 0 };
4745 char *mydata = NULL;
4746 char *backend = NULL;
4747 char *realm = NULL;
4748 char *id = NULL;
4749 char *xfer_exten = NULL;
4750 int max = -1;
4751 int interval = 0;
4752 switch_channel_t *channel = switch_core_session_get_channel(session);
4753
4754 /* Parse application data */
4755 if (!zstr(data)) {
4756 mydata = switch_core_session_strdup(session, data);
4757 argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
4758 }
4759
4760 backend = argv[0];
4761
4762 /* must have at least one item */
4763 if (argc < 1) {
4764 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "USAGE: limit %s\n", LIMIT_USAGE);
4765 return;
4766 }
4767
4768 /* if this is an invalid backend, fallback to db backend */
4769 /* TODO: remove this when we can! */
4770 if (switch_true(switch_channel_get_variable(channel, "switch_limit_backwards_compat_flag")) &&
4771 !switch_loadable_module_get_limit_interface(backend)) {
4772 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown backend '%s'. To maintain backwards compatability, falling back on db backend and shifting argumens. Either update your diaplan to include the backend, fix the typo, or load the appropriate limit implementation module.\n", backend);
4773 mydata = switch_core_session_sprintf(session, "db %s", data);
4774 argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
4775 backend = argv[0];
4776 }
4777
4778 if (argc < 3) {
4779 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "USAGE: limit %s\n", LIMIT_USAGE);
4780 return;
4781 }
4782
4783 realm = argv[1];
4784 id = argv[2];
4785
4786 /* If max is omitted or negative, only act as a counter and skip maximum checks */
4787 if (argc > 3) {
4788 if (argv[3][0] == '-') {
4789 max = -1;
4790 } else {
4791 char *szinterval = NULL;
4792 if ((szinterval = strchr(argv[3], '/'))) {
4793 *szinterval++ = '\0';
4794 interval = atoi(szinterval);
4795 }
4796
4797 max = atoi(argv[3]);
4798
4799 if (max < 0) {
4800 max = 0;
4801 }
4802 }
4803 }
4804
4805 if (argc > 4) {
4806 xfer_exten = argv[4];
4807 } else {
4808 xfer_exten = LIMIT_DEF_XFER_EXTEN;
4809 }
4810
4811 if (switch_limit_incr(backend, session, realm, id, max, interval) != SWITCH_STATUS_SUCCESS) {
4812 /* Limit exceeded */
4813 if (*xfer_exten == '!') {
4814 switch_channel_hangup(channel, switch_channel_str2cause(xfer_exten + 1));
4815 } else {
4816 switch_ivr_session_transfer(session, xfer_exten, argv[5], argv[6]);
4817 }
4818 }
4819 }
4820
4821 #define LIMIT_HASH_USAGE "<realm> <id> [<max>[/interval]] [number [dialplan [context]]]"
4822 #define LIMIT_HASH_DESC "DEPRECATED: limit access to a resource and transfer to an extension if the limit is exceeded"
4823 SWITCH_STANDARD_APP(limit_hash_function)
4824 {
4825 char *mydata = NULL;
4826 switch_channel_t *channel = switch_core_session_get_channel(session);
4827
4828 if (switch_true(switch_channel_get_variable(channel, "switch_limit_backwards_compat_flag"))) {
4829 mydata = switch_core_session_sprintf(session, "hash %s", data);
4830 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Using deprecated 'limit_hash' api: Please use 'limit hash'.\n");
4831 limit_function(session, mydata);
4832 } else {
4833 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "'limit_hash' (deprecated) is only available after loading mod_limit.\n");
4834 }
4835 }
4836
4837 #define LIMITEXECUTE_USAGE "<backend> <realm> <id> <max>[/interval] <application> [application arguments]"
4838 #define LIMITEXECUTE_DESC "limit access to a resource. the specified application will only be executed if the resource is available"
4839 SWITCH_STANDARD_APP(limit_execute_function)
4840 {
4841 int argc = 0;
4842 char *argv[6] = { 0 };
4843 char *mydata = NULL;
4844 char *backend = NULL;
4845 char *realm = NULL;
4846 char *id = NULL;
4847 char *app = NULL;
4848 char *app_arg = NULL;
4849 int max = -1;
4850 int interval = 0;
4851 switch_channel_t *channel = switch_core_session_get_channel(session);
4852
4853 /* Parse application data */
4854 if (!zstr(data)) {
4855 mydata = switch_core_session_strdup(session, data);
4856 argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
4857 }
4858
4859 /* backwards compat version, if we have 5, just prepend with db and reparse */
4860 if (switch_true(switch_channel_get_variable(channel, "switch_limit_backwards_compat_flag")) &&
4861 argc == 5) {
4862 mydata = switch_core_session_sprintf(session, "db %s", data);
4863 argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
4864 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Using deprecated limit api: Please specify backend. Defaulting to 'db' backend.\n");
4865 }
4866
4867 if (argc < 6) {
4868 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "USAGE: limit_execute %s\n", LIMITEXECUTE_USAGE);
4869 return;
4870 }
4871
4872 backend = argv[0];
4873 realm = argv[1];
4874 id = argv[2];
4875
4876 /* Accept '-' as unlimited (act as counter) */
4877 if (argv[3][0] == '-') {
4878 max = -1;
4879 } else {
4880 char *szinterval = NULL;
4881
4882 if ((szinterval = strchr(argv[3], '/'))) {
4883 *szinterval++ = '\0';
4884 interval = atoi(szinterval);
4885 }
4886
4887 max = atoi(argv[3]);
4888
4889 if (max < 0) {
4890 max = 0;
4891 }
4892 }
4893
4894 app = argv[4];
4895 app_arg = argv[5];
4896
4897 if (zstr(app)) {
4898 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Missing application\n");
4899 return;
4900 }
4901
4902 if (switch_limit_incr(backend, session, realm, id, max, interval) == SWITCH_STATUS_SUCCESS) {
4903 switch_core_session_execute_application(session, app, app_arg);
4904 /* Only release the resource if we are still in CS_EXECUTE */
4905 if (switch_channel_get_state(switch_core_session_get_channel(session)) == CS_EXECUTE) {
4906 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "immediately releasing\n");
4907 switch_limit_release(backend, session, realm, id);
4908 }
4909 }
4910 }
4911
4912 #define LIMITHASHEXECUTE_USAGE "<realm> <id> <max>[/interval] <application> [application arguments]"
4913 #define LIMITHASHEXECUTE_DESC "DEPRECATED: limit access to a resource. the specified application will only be executed if the resource is available"
4914 SWITCH_STANDARD_APP(limit_hash_execute_function)
4915 {
4916 char *mydata = NULL;
4917 switch_channel_t *channel = switch_core_session_get_channel(session);
4918
4919 if (switch_true(switch_channel_get_variable(channel, "switch_limit_backwards_compat_flag"))) {
4920 mydata = switch_core_session_sprintf(session, "hash %s", data);
4921 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Using deprecated 'limit_hash_execute' api: Please use 'limit_execute hash'.\n");
4922 limit_execute_function(session, mydata);
4923 } else {
4924 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "'limit_hash_execute' (deprecated) is only available after loading mod_limit.\n");
4925 }
4926 }
4927
4928
4929
4930 /* FILE STRING INTERFACE */
4931
4932 /* for apr_pstrcat */
4933 #define DEFAULT_PREBUFFER_SIZE 1024 * 64
4934
4935 struct file_string_audio_col {
4936 switch_audio_col_t col;
4937 char *value;
4938 struct file_string_audio_col *next;
4939 };
4940
4941 typedef struct file_string_audio_col file_string_audio_col_t;
4942
4943 struct file_string_context {
4944 char *file;
4945 char *argv[128];
4946 int argc;
4947 int index;
4948 int samples;
4949 switch_file_handle_t fh;
4950 file_string_audio_col_t *audio_cols;
4951 };
4952
4953 typedef struct file_string_context file_string_context_t;
4954
4955 #define FILE_STRING_OPEN "filestring::open"
4956 #define FILE_STRING_CLOSE "filestring::close"
4957 #define FILE_STRING_FAIL "filestring::fail"
4958
4959 static switch_status_t next_file(switch_file_handle_t *handle)
4960 {
4961 file_string_context_t *context = handle->private_info;
4962 char *file;
4963 const char *prefix = handle->prefix;
4964 switch_status_t status = SWITCH_STATUS_SUCCESS;
4965 switch_event_t *event = NULL;
4966
4967 top:
4968
4969 context->index++;
4970
4971 if (switch_test_flag((&context->fh), SWITCH_FILE_OPEN)) {
4972 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FILE_STRING_CLOSE) == SWITCH_STATUS_SUCCESS) {
4973 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "File", context->argv[(context->index - 1)]);
4974 switch_event_fire(&event);
4975 }
4976
4977 switch_core_file_close(&context->fh);
4978 }
4979
4980 if (context->index >= context->argc) {
4981 return SWITCH_STATUS_FALSE;
4982 }
4983
4984
4985 if (!prefix) {
4986 if (!(prefix = switch_core_get_variable_pdup("sound_prefix", handle->memory_pool))) {
4987 prefix = SWITCH_GLOBAL_dirs.sounds_dir;
4988 }
4989 }
4990
4991 if (!prefix || switch_is_file_path(context->argv[context->index])) {
4992 file = context->argv[context->index];
4993 } else {
4994 file = switch_core_sprintf(handle->memory_pool, "%s%s%s", prefix, SWITCH_PATH_SEPARATOR, context->argv[context->index]);
4995 }
4996
4997 if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
4998 char *path = switch_core_strdup(handle->memory_pool, file);
4999 char *p;
5000
5001 if ((p = strrchr(path, *SWITCH_PATH_SEPARATOR))) {
5002 *p = '\0';
5003 if (switch_dir_make_recursive(path, SWITCH_DEFAULT_DIR_PERMS, handle->memory_pool) != SWITCH_STATUS_SUCCESS) {
5004 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FILE_STRING_FAIL) == SWITCH_STATUS_SUCCESS) {
5005 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "File", context->argv[context->index]);
5006 switch_event_fire(&event);
5007 }
5008
5009 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", path);
5010 return SWITCH_STATUS_FALSE;
5011 }
5012
5013 } else {
5014 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error finding the folder path section in '%s'\n", path);
5015 }
5016 }
5017
5018 if (switch_core_file_open(&context->fh, file, handle->channels, handle->samplerate, handle->flags, NULL) != SWITCH_STATUS_SUCCESS) {
5019 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FILE_STRING_FAIL) == SWITCH_STATUS_SUCCESS) {
5020 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "File", context->argv[context->index]);
5021 switch_event_fire(&event);
5022 }
5023
5024 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open file %s\n", file);
5025 if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
5026 switch_file_remove(file, handle->memory_pool);
5027 }
5028 goto top;
5029 }
5030
5031 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FILE_STRING_OPEN) == SWITCH_STATUS_SUCCESS) {
5032 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "File", context->argv[context->index]);
5033 switch_event_fire(&event);
5034 }
5035
5036 if (handle->dbuflen) {
5037 free(handle->dbuf);
5038 handle->dbuflen = 0;
5039 handle->dbuf = NULL;
5040 }
5041
5042 if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
5043 file_string_audio_col_t *col_ptr = context->audio_cols;
5044
5045 while (col_ptr) {
5046 switch_core_file_set_string(&context->fh, col_ptr->col, col_ptr->value);
5047 col_ptr = col_ptr->next;
5048 }
5049
5050 if (context->file && switch_test_flag(handle, SWITCH_FILE_DATA_SHORT)) { /* TODO handle other data type flags */
5051 switch_size_t len;
5052 uint16_t buf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
5053 switch_file_handle_t fh = { 0 };
5054
5055 if (switch_core_file_open(&fh, context->file, handle->channels, handle->samplerate,
5056 SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) == SWITCH_STATUS_SUCCESS) {
5057 switch_status_t stat;
5058
5059 do {
5060 len = SWITCH_RECOMMENDED_BUFFER_SIZE / handle->channels;
5061 if ((stat = switch_core_file_read(&fh, buf, &len)) == SWITCH_STATUS_SUCCESS) {
5062 stat = switch_core_file_write(&context->fh, buf, &len);
5063 }
5064 } while (stat == SWITCH_STATUS_SUCCESS);
5065
5066 switch_core_file_close(&fh);
5067 switch_file_remove(context->file, handle->memory_pool);
5068
5069 } else {
5070 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", context->file);
5071 }
5072 }
5073 }
5074 context->file = file;
5075
5076 handle->samples = context->fh.samples;
5077 handle->cur_samplerate = context->fh.samplerate;
5078 handle->cur_channels = context->fh.real_channels;
5079 handle->format = context->fh.format;
5080 handle->sections = context->fh.sections;
5081 handle->seekable = context->fh.seekable;
5082 handle->speed = context->fh.speed;
5083 handle->interval = context->fh.interval;
5084 handle->max_samples = 0;
5085
5086
5087 if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) {
5088 switch_set_flag_locked(handle, SWITCH_FILE_NATIVE);
5089 } else {
5090 switch_clear_flag_locked(handle, SWITCH_FILE_NATIVE);
5091 }
5092
5093
5094 if (!switch_test_flag(handle, SWITCH_FILE_NATIVE)) {
5095 if (context->index == 0) {
5096 context->samples = (handle->samplerate / 1000) * 250;
5097 }
5098 }
5099
5100 return status;
5101 }
5102
5103
5104 static switch_status_t file_string_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
5105 {
5106 file_string_context_t *context = handle->private_info;
5107
5108 if (samples == 0 && whence == SEEK_SET) {
5109 context->index = -1;
5110 return next_file(handle);
5111 }
5112
5113 if (!handle->seekable) {
5114 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "File is not seekable\n");
5115 return SWITCH_STATUS_NOTIMPL;
5116 }
5117
5118 return switch_core_file_seek(&context->fh, cur_sample, samples, whence);
5119 }
5120
5121 static switch_status_t file_string_file_open(switch_file_handle_t *handle, const char *path)
5122 {
5123 file_string_context_t *context;
5124 char *file_dup;
5125
5126 context = switch_core_alloc(handle->memory_pool, sizeof(*context));
5127
5128 file_dup = switch_core_strdup(handle->memory_pool, path);
5129 context->argc = switch_separate_string(file_dup, '!', context->argv, (sizeof(context->argv) / sizeof(context->argv[0])));
5130 context->index = -1;
5131
5132 handle->private_info = context;
5133 handle->pre_buffer_datalen = 0;
5134
5135 return next_file(handle);
5136 }
5137
5138 static switch_status_t file_string_file_close(switch_file_handle_t *handle)
5139 {
5140 file_string_context_t *context = handle->private_info;
5141
5142 if (switch_test_flag((&context->fh), SWITCH_FILE_OPEN)) {
5143 switch_core_file_close(&context->fh);
5144 }
5145
5146 return SWITCH_STATUS_SUCCESS;
5147 }
5148
5149 static switch_status_t file_string_file_set_string(switch_file_handle_t *handle, switch_audio_col_t col, const char *string)
5150 {
5151 file_string_context_t *context = handle->private_info;
5152 file_string_audio_col_t *col_ptr = context->audio_cols;
5153
5154 while (col_ptr && col != col_ptr->col) {
5155 col_ptr = col_ptr->next;
5156 }
5157
5158 if (col_ptr) {
5159 col_ptr->value = switch_core_strdup(handle->memory_pool, string);
5160 } else {
5161 col_ptr = switch_core_alloc(handle->memory_pool, sizeof(*col_ptr));
5162 col_ptr->value = switch_core_strdup(handle->memory_pool, string);
5163 col_ptr->col = col;
5164 col_ptr->next = context->audio_cols;
5165 context->audio_cols = col_ptr;
5166 }
5167
5168 return switch_core_file_set_string(&context->fh, col, string);
5169 }
5170
5171 static switch_status_t file_string_file_get_string(switch_file_handle_t *handle, switch_audio_col_t col, const char **string)
5172 {
5173 file_string_context_t *context = handle->private_info;
5174
5175 return switch_core_file_get_string(&context->fh, col, string);
5176 }
5177
5178
5179 static switch_status_t file_string_file_read(switch_file_handle_t *handle, void *data, size_t *len)
5180 {
5181 file_string_context_t *context = handle->private_info;
5182 switch_status_t status;
5183 size_t llen = *len;
5184
5185 if (context->samples > 0) {
5186 if (*len > (size_t) context->samples) {
5187 *len = context->samples;
5188 }
5189
5190 context->samples -= (int) *len;
5191 memset(data, 255, *len *2);
5192 status = SWITCH_STATUS_SUCCESS;
5193 } else {
5194 status = switch_core_file_read(&context->fh, data, len);
5195 }
5196
5197 if (status != SWITCH_STATUS_SUCCESS) {
5198 if ((status = next_file(handle)) != SWITCH_STATUS_SUCCESS) {
5199 return status;
5200 }
5201 if (switch_test_flag(handle, SWITCH_FILE_BREAK_ON_CHANGE)) {
5202 *len = 0;
5203 status = SWITCH_STATUS_BREAK;
5204 } else {
5205 *len = llen;
5206 status = switch_core_file_read(&context->fh, data, len);
5207 }
5208 }
5209
5210 return status;
5211 }
5212
5213
5214 static switch_status_t file_string_file_write(switch_file_handle_t *handle, void *data, size_t *len)
5215 {
5216 file_string_context_t *context = handle->private_info;
5217 switch_status_t status;
5218 size_t llen = *len;
5219
5220 status = switch_core_file_write(&context->fh, data, len);
5221
5222 if (status != SWITCH_STATUS_SUCCESS) {
5223 if ((status = next_file(handle)) != SWITCH_STATUS_SUCCESS) {
5224 return status;
5225 }
5226 *len = llen;
5227 status = switch_core_file_write(&context->fh, data, len);
5228 }
5229 return status;
5230 }
5231
5232 static switch_status_t file_url_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
5233 {
5234 switch_file_handle_t *fh = handle->private_info;
5235 return switch_core_file_seek(fh, cur_sample, samples, whence);
5236 }
5237
5238 static switch_status_t file_url_file_close(switch_file_handle_t *handle)
5239 {
5240 switch_file_handle_t *fh = handle->private_info;
5241 if (switch_test_flag(fh, SWITCH_FILE_OPEN)) {
5242 switch_core_file_close(fh);
5243 }
5244
5245 return SWITCH_STATUS_SUCCESS;
5246 }
5247
5248 static switch_status_t file_url_file_read(switch_file_handle_t *handle, void *data, size_t *len)
5249 {
5250 switch_file_handle_t *fh = handle->private_info;
5251 return switch_core_file_read(fh, data, len);
5252 }
5253
5254 static switch_status_t file_url_file_open(switch_file_handle_t *handle, const char *path)
5255 {
5256 switch_file_handle_t *fh = switch_core_alloc(handle->memory_pool, sizeof(*fh));
5257 switch_status_t status;
5258 char *url_host;
5259 char *url_path;
5260
5261 if (zstr(path)) {
5262 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NULL path\n");
5263 return SWITCH_STATUS_FALSE;
5264 }
5265
5266 /* parse and check host */
5267 url_host = switch_core_strdup(handle->memory_pool, path);
5268 if (!(url_path = strchr(url_host, '/'))) {
5269 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing path\n");
5270 return SWITCH_STATUS_FALSE;
5271 }
5272 *url_path = '\0';
5273 /* TODO allow this host */
5274 if (!zstr(url_host) && strcasecmp(url_host, "localhost")) {
5275 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not localhost\n");
5276 return SWITCH_STATUS_FALSE;
5277 }
5278
5279 /* decode and check path */
5280 url_path++;
5281 if (zstr(url_path)) {
5282 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "empty path\n");
5283 return SWITCH_STATUS_FALSE;
5284 }
5285 if (strstr(url_path, "%2f") || strstr(url_path, "%2F")) {
5286 /* don't allow %2f or %2F encoding (/) */
5287 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "encoded slash is not allowed\n");
5288 return SWITCH_STATUS_FALSE;
5289 }
5290 url_path = switch_core_sprintf(handle->memory_pool, "/%s", url_path);
5291 switch_url_decode(url_path);
5292
5293 /* TODO convert to native file separators? */
5294
5295 handle->private_info = fh;
5296 status = switch_core_file_open(fh, url_path, handle->channels, handle->samplerate, handle->flags, NULL);
5297 if (status == SWITCH_STATUS_SUCCESS) {
5298 handle->samples = fh->samples;
5299 handle->cur_samplerate = fh->samplerate;
5300 handle->cur_channels = fh->real_channels;
5301 handle->format = fh->format;
5302 handle->sections = fh->sections;
5303 handle->seekable = fh->seekable;
5304 handle->speed = fh->speed;
5305 handle->interval = fh->interval;
5306 handle->max_samples = 0;
5307
5308 if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
5309 switch_set_flag_locked(handle, SWITCH_FILE_NATIVE);
5310 } else {
5311 switch_clear_flag_locked(handle, SWITCH_FILE_NATIVE);
5312 }
5313 }
5314 return status;
5315 }
5316
5317 static switch_status_t file_url_file_write(switch_file_handle_t *handle, void *data, size_t *len)
5318 {
5319 switch_file_handle_t *fh = handle->private_info;
5320 return switch_core_file_write(fh, data, len);
5321 }
5322
5323 /* Registration */
5324
5325 static char *file_string_supported_formats[SWITCH_MAX_CODECS] = { 0 };
5326 static char *file_url_supported_formats[SWITCH_MAX_CODECS] = { 0 };
5327
5328
5329 /* /FILE STRING INTERFACE */
5330
5331
5332 SWITCH_STANDARD_APP(blind_transfer_ack_function)
5333 {
5334 switch_bool_t val = 0;
5335
5336 if (data) {
5337 val = (switch_bool_t)switch_true((char *) data);
5338 }
5339
5340 switch_ivr_blind_transfer_ack(session, val);
5341 }
5342
5343 /* /// mutex /// */
5344
5345 typedef struct mutex_node_s {
5346 char *uuid;
5347 struct mutex_node_s *next;
5348 } mutex_node_t;
5349
5350 typedef enum {
5351 MUTEX_FLAG_WAIT = (1 << 0),
5352 MUTEX_FLAG_SET = (1 << 1)
5353 } mutex_flag_t;
5354
5355 struct read_frame_data {
5356 const char *dp;
5357 const char *exten;
5358 const char *context;
5359 const char *key;
5360 long to;
5361 };
5362
5363 typedef struct master_mutex_s {
5364 mutex_node_t *list;
5365 char *key;
5366 } master_mutex_t;
5367
5368 static switch_status_t mutex_hanguphook(switch_core_session_t *session);
5369 static void advance(master_mutex_t *master, switch_bool_t pop_current);
5370
5371 static switch_status_t read_frame_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data)
5372 {
5373 switch_channel_t *channel = switch_core_session_get_channel(session);
5374 struct read_frame_data *rf = (struct read_frame_data *) user_data;
5375
5376 if (rf->to && --rf->to <= 0) {
5377 rf->to = -1;
5378 return SWITCH_STATUS_FALSE;
5379 }
5380
5381 return switch_channel_test_app_flag_key(rf->key, channel, MUTEX_FLAG_WAIT) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
5382
5383 }
5384
5385 static void free_node(mutex_node_t **npp)
5386 {
5387 mutex_node_t *np;
5388
5389 if (npp) {
5390 np = *npp;
5391 *npp = NULL;
5392 switch_safe_free(np->uuid);
5393 free(np);
5394 }
5395 }
5396
5397 static void cancel(switch_core_session_t *session, master_mutex_t *master)
5398 {
5399 mutex_node_t *np, *lp = NULL;
5400 const char *uuid = switch_core_session_get_uuid(session);
5401
5402 switch_mutex_lock(globals.mutex_mutex);
5403 for (np = master->list; np; np = np->next) {
5404 if (!strcmp(np->uuid, uuid)) {
5405 switch_core_event_hook_remove_state_change(session, mutex_hanguphook);
5406 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s %s mutex %s canceled\n",
5407 switch_core_session_get_uuid(session),
5408 switch_core_session_get_name(session), master->key);
5409
5410 if (lp) {
5411 lp->next = np->next;
5412 } else {
5413 if ((master->list = np->next)) {
5414 advance(master, SWITCH_FALSE);
5415 }
5416 }
5417
5418 free_node(&np);
5419
5420 break;
5421 }
5422
5423 lp = np;
5424 }
5425
5426 switch_mutex_unlock(globals.mutex_mutex);
5427
5428 }
5429
5430 static void advance(master_mutex_t *master, switch_bool_t pop_current)
5431 {
5432
5433 switch_mutex_lock(globals.mutex_mutex);
5434
5435 if (!master || !master->list) {
5436 goto end;
5437 }
5438
5439 while (master->list) {
5440 mutex_node_t *np;
5441
5442
5443 if (!pop_current) {
5444 pop_current++;
5445 } else {
5446 np = master->list;
5447 master->list = master->list->next;
5448
5449 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "ADVANCE POP %p\n", (void *)np);
5450 free_node(&np);
5451 }
5452
5453
5454 if (master->list) {
5455 switch_core_session_t *session;
5456
5457 if ((session = switch_core_session_locate(master->list->uuid))) {
5458 switch_channel_t *channel = switch_core_session_get_channel(session);
5459 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
5460 "%s mutex %s advanced\n", switch_channel_get_name(channel), master->key);
5461 switch_channel_set_app_flag_key(master->key, channel, MUTEX_FLAG_SET);
5462 switch_channel_clear_app_flag_key(master->key, channel, MUTEX_FLAG_WAIT);
5463 switch_core_event_hook_add_state_change(session, mutex_hanguphook);
5464 switch_core_session_rwunlock(session);
5465 break;
5466 } else {
5467 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "uuid %s already gone\n", master->list->uuid);
5468 }
5469 }
5470 }
5471
5472
5473 end:
5474
5475 switch_mutex_unlock(globals.mutex_mutex);
5476
5477
5478 }
5479
5480 static void confirm(switch_core_session_t *session, master_mutex_t *master)
5481 {
5482 switch_channel_t *channel = switch_core_session_get_channel(session);
5483
5484 if (!master) {
5485 if (!(master = switch_channel_get_private(channel, "_mutex_master"))) {
5486 return;
5487 }
5488 }
5489
5490 switch_mutex_lock(globals.mutex_mutex);
5491
5492 if (master->list) {
5493 if (!strcmp(master->list->uuid, switch_core_session_get_uuid(session))) {
5494 switch_channel_clear_app_flag_key(master->key, channel, MUTEX_FLAG_SET);
5495 switch_core_event_hook_remove_state_change(session, mutex_hanguphook);
5496 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s %s mutex %s cleared\n",
5497 switch_core_session_get_uuid(session),
5498 switch_channel_get_name(channel), master->key);
5499 advance(master, SWITCH_TRUE);
5500 } else {
5501 cancel(session, master);
5502 }
5503 }
5504
5505 switch_mutex_unlock(globals.mutex_mutex);
5506 }
5507
5508
5509
5510 static switch_status_t mutex_hanguphook(switch_core_session_t *session)
5511 {
5512 switch_channel_t *channel = switch_core_session_get_channel(session);
5513 switch_channel_state_t state = switch_channel_get_state(channel);
5514
5515 if (state != CS_HANGUP) {
5516 return SWITCH_STATUS_SUCCESS;
5517 }
5518
5519 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s mutex hangup hook\n", switch_channel_get_name(channel));
5520
5521 confirm(session, NULL);
5522 switch_core_event_hook_remove_state_change(session, mutex_hanguphook);
5523
5524 return SWITCH_STATUS_SUCCESS;
5525 }
5526
5527 static switch_bool_t do_mutex(switch_core_session_t *session, const char *key, switch_bool_t on)
5528 {
5529 switch_channel_t *channel = switch_core_session_get_channel(session);
5530 const char *feedback, *var;
5531 switch_input_args_t args = { 0 };
5532 master_mutex_t *master = NULL;
5533 mutex_node_t *node, *np;
5534 int used;
5535 struct read_frame_data rf = { 0 };
5536 long to_val = 0;
5537
5538 switch_mutex_lock(globals.mutex_mutex);
5539 used = switch_channel_test_app_flag_key(key, channel, MUTEX_FLAG_WAIT) || switch_channel_test_app_flag_key(key, channel, MUTEX_FLAG_SET);
5540
5541 if (!on == !used) {
5542 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "INVALID STATE\n");
5543 switch_mutex_unlock(globals.mutex_mutex);
5544 return SWITCH_FALSE;
5545 }
5546
5547 if (!(master = switch_core_hash_find(globals.mutex_hash, key))) {
5548 master = switch_core_alloc(globals.pool, sizeof(*master));
5549 master->key = switch_core_strdup(globals.pool, key);
5550 master->list = NULL;
5551 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "NEW MASTER %s %p\n", key, (void *) master);
5552 switch_core_hash_insert(globals.mutex_hash, key, master);
5553 } else {
5554 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "EXIST MASTER %s %p\n", key, (void *) master);
5555 }
5556
5557 if (on) {
5558
5559 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "HIT ON\n");
5560
5561 switch_zmalloc(node, sizeof(*node));
5562 node->uuid = strdup(switch_core_session_get_uuid(session));
5563 node->next = NULL;
5564
5565 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "CHECK MASTER LIST %p\n", (void *) master->list);
5566
5567 for (np = master->list; np && np->next; np = np->next);
5568
5569 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "HIT ON np %p\n", (void *) np);
5570
5571 if (np) {
5572 np->next = node;
5573 switch_channel_set_app_flag_key(key, channel, MUTEX_FLAG_WAIT);
5574 } else {
5575 master->list = node;
5576 switch_channel_set_app_flag_key(key, channel, MUTEX_FLAG_SET);
5577 switch_channel_clear_app_flag_key(key, channel, MUTEX_FLAG_WAIT);
5578 switch_channel_set_private(channel, "_mutex_master", master);
5579 switch_core_event_hook_add_state_change(session, mutex_hanguphook);
5580 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s %s mutex %s acquired\n",
5581 switch_core_session_get_uuid(session),
5582 switch_channel_get_name(channel), key);
5583 switch_mutex_unlock(globals.mutex_mutex);
5584 return SWITCH_TRUE;
5585 }
5586 } else {
5587 confirm(session, master);
5588
5589 switch_mutex_unlock(globals.mutex_mutex);
5590 return SWITCH_TRUE;
5591 }
5592
5593 switch_mutex_unlock(globals.mutex_mutex);
5594
5595 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s mutex %s is busy, waiting...\n", switch_channel_get_name(channel), key);
5596
5597 if ((feedback = switch_channel_get_variable(channel, "mutex_feedback"))) {
5598 if (!strcasecmp(feedback, "silence")) {
5599 feedback = "silence_stream://-1";
5600 }
5601 }
5602
5603 if ((rf.exten = switch_channel_get_variable(channel, "mutex_orbit_exten"))) {
5604 to_val = 60;
5605 }
5606
5607 if ((var = switch_channel_get_variable(channel, "mutex_timeout"))) {
5608 long tmp = atol(var);
5609
5610 if (tmp > 0) {
5611 to_val = tmp;
5612 }
5613 }
5614
5615 if (to_val) {
5616 switch_codec_implementation_t read_impl;
5617 switch_core_session_get_read_impl(session, &read_impl);
5618
5619 rf.to = (1000 / (read_impl.microseconds_per_packet / 1000)) * to_val;
5620 rf.dp = switch_channel_get_variable(channel, "mutex_orbit_dialplan");
5621 rf.context = switch_channel_get_variable(channel, "mutex_orbit_context");
5622 }
5623
5624 rf.key = key;
5625
5626 args.read_frame_callback = read_frame_callback;
5627 args.user_data = &rf;
5628
5629 while(switch_channel_ready(channel) && switch_channel_test_app_flag_key(key, channel, MUTEX_FLAG_WAIT)) {
5630 switch_status_t st;
5631
5632 if (feedback) {
5633 switch_channel_pre_answer(channel);
5634 st = switch_ivr_play_file(session, NULL, feedback, &args);
5635 } else {
5636 if ((st = switch_ivr_sleep(session, 20, SWITCH_FALSE, NULL)) == SWITCH_STATUS_SUCCESS) {
5637 st = read_frame_callback(session, NULL, &rf);
5638 }
5639 }
5640
5641 if (st != SWITCH_STATUS_SUCCESS) {
5642 break;
5643 }
5644 }
5645
5646 switch_mutex_lock(globals.mutex_mutex);
5647 if (switch_channel_test_app_flag_key(key, channel, MUTEX_FLAG_WAIT) || !switch_channel_up(channel)) {
5648 cancel(session, master);
5649 } else {
5650 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s %s mutex %s acquired\n",
5651 switch_core_session_get_uuid(session),
5652 switch_channel_get_name(channel), key);
5653 switch_core_event_hook_add_state_change(session, mutex_hanguphook);
5654 switch_channel_set_private(channel, "_mutex_master", master);
5655 }
5656 switch_mutex_unlock(globals.mutex_mutex);
5657
5658 return SWITCH_TRUE;
5659 }
5660
5661 #define MUTEX_SYNTAX "<keyname>[ on|off]"
5662 SWITCH_STANDARD_APP(mutex_function)
5663 {
5664 char *key;
5665 char *arg;
5666 switch_bool_t on = SWITCH_TRUE;
5667
5668 if (zstr(data)) {
5669 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Missing keyname\n");
5670 return;
5671 }
5672
5673 key = switch_core_session_sprintf(session, "_mutex_key_%s", (char *)data);
5674
5675 if ((arg = strchr(key, ' '))) {
5676 *arg++ = '\0';
5677
5678 if (!strcasecmp(arg, "off")) {
5679 on = SWITCH_FALSE;
5680 }
5681 }
5682
5683 do_mutex(session, key, on);
5684
5685
5686 }
5687
5688 /* /// mutex /// */
5689
5690 typedef struct page_data_s {
5691 uint32_t *counter;
5692 const char *dial_str;
5693 const char *dp;
5694 const char *context;
5695 const char *exten;
5696 const char *path;
5697 switch_event_t *var_event;
5698 switch_memory_pool_t *pool;
5699 switch_mutex_t *mutex;
5700 } page_data_t;
5701
5702 static switch_status_t page_hanguphook(switch_core_session_t *session)
5703 {
5704 switch_channel_t *channel = switch_core_session_get_channel(session);
5705 switch_channel_state_t state = switch_channel_get_state(channel);
5706
5707 if (state == CS_HANGUP) {
5708 page_data_t *pd;
5709
5710 if ((pd = (page_data_t *) switch_channel_get_private(channel, "__PAGE_DATA"))) {
5711 uint32_t *counter = pd->counter;
5712
5713 switch_mutex_lock(pd->mutex);
5714 (*counter)--;
5715 switch_mutex_unlock(pd->mutex);
5716
5717
5718 }
5719
5720 switch_core_event_hook_remove_state_change(session, page_hanguphook);
5721 }
5722
5723 return SWITCH_STATUS_SUCCESS;
5724 }
5725
5726 void *SWITCH_THREAD_FUNC page_thread(switch_thread_t *thread, void *obj)
5727 {
5728 page_data_t *mypd, *pd = (page_data_t *) obj;
5729 switch_core_session_t *session;
5730 switch_call_cause_t cause = SWITCH_CAUSE_NONE;
5731 uint32_t *counter = pd->counter;
5732 switch_memory_pool_t *pool = pd->pool;
5733
5734
5735 if (switch_ivr_originate(NULL, &session, &cause, pd->dial_str, SWITCH_DEFAULT_TIMEOUT, NULL, NULL, NULL, NULL, pd->var_event, SOF_NONE, NULL, NULL) == SWITCH_STATUS_SUCCESS) {
5736 switch_channel_t *channel = switch_core_session_get_channel(session);
5737
5738 switch_channel_set_variable(channel, "page_file", pd->path);
5739
5740 mypd = switch_core_session_alloc(session, sizeof(*mypd));
5741 mypd->counter = pd->counter;
5742 mypd->mutex = pd->mutex;
5743 switch_core_event_hook_add_state_change(session, page_hanguphook);
5744 switch_channel_set_private(channel, "__PAGE_DATA", mypd);
5745 switch_ivr_session_transfer(session, pd->exten, pd->dp, pd->context);
5746 switch_core_session_rwunlock(session);
5747 } else {
5748 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "originate failed: %s [%s]\n", switch_channel_cause2str(cause), pd->dial_str);
5749 switch_mutex_lock(pd->mutex);
5750 (*counter)--;
5751 switch_mutex_unlock(pd->mutex);
5752 }
5753
5754 switch_event_safe_destroy(pd->var_event);
5755
5756 if (pool) {
5757 switch_core_destroy_memory_pool(&pool);
5758 }
5759
5760 return NULL;
5761 }
5762
5763 static void launch_call(const char *dial_str,
5764 const char *path, const char *exten, const char *context, const char *dp,
5765 switch_mutex_t *mutex, uint32_t *counter, switch_event_t **var_event)
5766 {
5767 switch_thread_data_t *td;
5768 switch_memory_pool_t *pool;
5769 page_data_t *pd;
5770
5771 switch_core_new_memory_pool(&pool);
5772
5773 pd = switch_core_alloc(pool, sizeof(*pd));
5774 pd->pool = pool;
5775 pd->exten = switch_core_strdup(pool, exten);
5776 pd->context = switch_core_strdup(pool, context);
5777 pd->dp = switch_core_strdup(pool, dp);
5778 pd->dial_str = switch_core_strdup(pool, dial_str);
5779 pd->path = switch_core_strdup(pool, path);
5780 pd->mutex = mutex;
5781
5782 if (var_event && *var_event) {
5783 switch_event_dup(&pd->var_event, *var_event);
5784 switch_event_destroy(var_event);
5785 }
5786
5787 switch_mutex_lock(pd->mutex);
5788 (*counter)++;
5789 switch_mutex_unlock(pd->mutex);
5790
5791 pd->counter = counter;
5792
5793 td = switch_core_alloc(pool, sizeof(*td));
5794 td->func = page_thread;
5795 td->obj = pd;
5796
5797 switch_thread_pool_launch_thread(&td);
5798
5799 }
5800
5801 typedef struct call_monitor_s {
5802 switch_memory_pool_t *pool;
5803 const char *path;
5804 char *data;
5805 const char *context;
5806 const char *exten;
5807 const char *dp;
5808 uint32_t chunk_size;
5809 int nuke;
5810 } call_monitor_t;
5811
5812
5813
5814 void *SWITCH_THREAD_FUNC call_monitor_thread(switch_thread_t *thread, void *obj)
5815 {
5816 call_monitor_t *cm = (call_monitor_t *) obj;
5817 uint32_t sent = 0;
5818 switch_mutex_t *mutex;
5819 uint32_t counter = 0;
5820 switch_memory_pool_t *pool = cm->pool;
5821 unsigned int size;
5822 char *argv[512] = { 0 };
5823 int busy = 0;
5824 switch_event_t *var_event = NULL;
5825 char *data;
5826
5827 switch_mutex_init(&mutex, SWITCH_MUTEX_NESTED, cm->pool);
5828
5829 if (switch_file_exists(cm->path, cm->pool) != SWITCH_STATUS_SUCCESS) {
5830 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File %s does not exist!\n", cm->path);
5831 goto end;
5832 }
5833
5834 data = cm->data;
5835
5836 while (data && *data && *data == ' ') {
5837 data++;
5838 }
5839
5840 while (data && *data == '<') {
5841 char *parsed = NULL;
5842
5843 if (switch_event_create_brackets(data, '<', '>', ',', &var_event, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
5844 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
5845 goto end;
5846 }
5847
5848 data = parsed;
5849 }
5850
5851 while (data && *data && *data == ' ') {
5852 data++;
5853 }
5854
5855 if (!(size = switch_separate_string_string(data, SWITCH_ENT_ORIGINATE_DELIM, argv, (sizeof(argv) / sizeof(argv[0]))))) {
5856 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No channels specified.\n");
5857 goto end;
5858 }
5859
5860
5861 if (cm->chunk_size > size) {
5862 cm->chunk_size = size;
5863 }
5864
5865 while (sent < size) {
5866 do {
5867 switch_mutex_lock(mutex);
5868 busy = (counter >= cm->chunk_size);
5869 switch_mutex_unlock(mutex);
5870
5871 if (busy) {
5872 switch_yield(100000);
5873 }
5874
5875 } while (busy);
5876
5877 launch_call(argv[sent++], cm->path, cm->exten, cm->context, cm->dp, mutex, &counter, &var_event);
5878 }
5879
5880
5881 end:
5882
5883 while(counter) {
5884 switch_mutex_lock(mutex);
5885 switch_mutex_unlock(mutex);
5886 switch_yield(100000);
5887 }
5888
5889 if (cm->nuke && !zstr(cm->path)) {
5890 unlink(cm->path);
5891 }
5892
5893 if (pool) {
5894 switch_core_destroy_memory_pool(&pool);
5895 }
5896
5897 return NULL;
5898 }
5899
5900 static void launch_call_monitor(const char *path, int del, const char *data, uint32_t chunk_size, const char *exten, const char *context, const char *dp)
5901 {
5902 switch_thread_data_t *td;
5903 switch_memory_pool_t *pool;
5904 call_monitor_t *cm;
5905
5906 switch_core_new_memory_pool(&pool);
5907
5908 cm = switch_core_alloc(pool, sizeof(*cm));
5909
5910 if (del) {
5911 cm->nuke = 1;
5912 }
5913
5914 cm->pool = pool;
5915 cm->path = switch_core_strdup(pool, path);
5916 cm->data = switch_core_strdup(pool, data);
5917 cm->exten = switch_core_strdup(pool, exten);
5918 cm->context = switch_core_strdup(pool, context);
5919 cm->dp = switch_core_strdup(pool, dp);
5920 cm->chunk_size = chunk_size;
5921
5922 td = switch_core_alloc(pool, sizeof(*td));
5923 td->func = call_monitor_thread;
5924 td->obj = cm;
5925
5926 switch_thread_pool_launch_thread(&td);
5927
5928 }
5929
5930
5931 #define PAGE_SYNTAX "<var1=val1,var2=val2><chan1>[:_:<chanN>]"
5932 SWITCH_STANDARD_APP(page_function)
5933 {
5934 switch_channel_t *channel = switch_core_session_get_channel(session);
5935 uint32_t limit = 0;
5936 const char *path = NULL;
5937 switch_input_args_t args = { 0 };
5938 switch_file_handle_t fh = { 0 };
5939 uint32_t chunk_size = 10;
5940 const char *l = NULL;
5941 const char *tmp;
5942 int del = 0, rate;
5943 const char *exten;
5944 const char *context = NULL;
5945 const char *dp = "inline";
5946 const char *pdata = data;
5947
5948 if (zstr(pdata)) {
5949 pdata = switch_channel_get_variable(channel, "page_data");
5950 }
5951
5952 if (zstr(pdata)) {
5953 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No channels specified.\n");
5954 return;
5955 }
5956
5957
5958 exten = switch_channel_get_variable(channel, "page_exten");
5959 context = switch_channel_get_variable(channel, "page_context");
5960
5961 if ((l = switch_channel_get_variable(channel, "page_dp"))) {
5962 dp = l;
5963 }
5964
5965
5966 l = switch_channel_get_variable(channel, "page_record_limit");
5967
5968 if (l) {
5969 if (*l == '+') {
5970 l++;
5971 }
5972 if (!zstr(l)) {
5973 limit = switch_atoui(l);
5974 }
5975 }
5976
5977 if ((l = switch_channel_get_variable(channel, "page_record_thresh"))) {
5978 fh.thresh = switch_atoui(l);
5979 }
5980
5981 if ((l = switch_channel_get_variable(channel, "page_chunk_size"))) {
5982 uint32_t chunk = switch_atoui(l);
5983
5984 if (chunk > 0) {
5985 chunk_size = chunk;
5986 }
5987 }
5988
5989 if ((l = switch_channel_get_variable(channel, "page_record_silence_hits"))) {
5990 fh.silence_hits = switch_atoui(l);
5991 }
5992
5993 if ((tmp = switch_channel_get_variable(channel, "record_rate"))) {
5994 rate = atoi(tmp);
5995 if (rate > 0) {
5996 fh.samplerate = rate;
5997 }
5998 }
5999
6000 args.input_callback = on_dtmf;
6001
6002 switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
6003
6004
6005 if (!(path = switch_channel_get_variable(channel, "page_path"))) {
6006 const char *beep;
6007
6008 path = switch_core_session_sprintf(session, "%s%s%s.wav", SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session));
6009 del = 1;
6010
6011 if (!(beep = switch_channel_get_variable(channel, "page_beep"))) {
6012 beep = "tone_stream://%(500,0, 620)";
6013 }
6014
6015 switch_ivr_play_file(session, NULL, beep, NULL);
6016
6017
6018 switch_ivr_record_file(session, &fh, path, &args, limit);
6019 }
6020
6021 if (zstr(exten)) {
6022 exten = switch_core_session_sprintf(session, "playback:%s", path);
6023 }
6024
6025 if (switch_file_exists(path, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
6026 launch_call_monitor(path, del, pdata, chunk_size, exten, context, dp);
6027 } else {
6028 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "File %s does not exist\n", path);
6029 }
6030
6031 }
6032
6033
6034 SWITCH_STANDARD_API(page_api_function)
6035 {
6036 char *odata = NULL, *data = NULL;
6037 switch_event_t *var_event = NULL;
6038 const char *exten;
6039 char *oexten = NULL;
6040 const char *context = NULL;
6041 const char *dp = "inline";
6042 const char *pdata = NULL;
6043 const char *l;
6044 uint32_t chunk_size = 10;
6045 const char *path;
6046
6047
6048 if (zstr(cmd)) {
6049 stream->write_function(stream, "-ERR no data");
6050 goto end;
6051 }
6052
6053 odata = strdup(cmd);
6054 data = odata;
6055
6056 while (data && *data && *data == ' ') {
6057 data++;
6058 }
6059
6060 while (data && *data == '(') {
6061 char *parsed = NULL;
6062
6063 if (switch_event_create_brackets(data, '(', ')', ',', &var_event, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
6064 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
6065 goto end;
6066 }
6067
6068 data = parsed;
6069 }
6070
6071 while (data && *data && *data == ' ') {
6072 data++;
6073 }
6074
6075 if (!var_event) {
6076 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
6077 goto end;
6078 }
6079
6080 pdata = data;
6081
6082 if (zstr(pdata)) {
6083 pdata = switch_event_get_header(var_event, "page_data");
6084 }
6085
6086 if (zstr(pdata)) {
6087 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No channels specified.\n");
6088 goto end;
6089 }
6090
6091
6092 exten = switch_event_get_header(var_event, "page_exten");
6093 context = switch_event_get_header(var_event, "page_context");
6094
6095 if ((l = switch_event_get_header(var_event, "page_dp"))) {
6096 dp = l;
6097 }
6098
6099
6100 if ((l = switch_event_get_header(var_event, "page_chunk_size"))) {
6101 uint32_t tmp = switch_atoui(l);
6102
6103 if (tmp > 0) {
6104 chunk_size = tmp;
6105 }
6106 }
6107
6108 if (!(path = switch_event_get_header(var_event, "page_path"))) {
6109 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No file specified.\n");
6110 goto end;
6111 }
6112
6113 if (zstr(exten)) {
6114 oexten = switch_mprintf("playback:%s", path);
6115 exten = oexten;
6116 }
6117
6118 if (switch_file_exists(path, NULL) == SWITCH_STATUS_SUCCESS) {
6119 launch_call_monitor(path, 0, pdata, chunk_size, exten, context, dp);
6120 } else {
6121 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File %s does not exist\n", path);
6122 }
6123
6124
6125 end:
6126
6127
6128 switch_safe_free(odata);
6129 switch_safe_free(oexten);
6130
6131 return SWITCH_STATUS_SUCCESS;
6132 }
6133
6134 /**
6135 * Convert DTMF source to human readable string
6136 */
6137 static const char *to_dtmf_source_string(switch_dtmf_source_t source)
6138 {
6139 switch(source) {
6140 case SWITCH_DTMF_ENDPOINT: return "SIP INFO";
6141 case SWITCH_DTMF_INBAND_AUDIO: return "INBAND";
6142 case SWITCH_DTMF_RTP: return "2833";
6143 case SWITCH_DTMF_UNKNOWN: return "UNKNOWN";
6144 case SWITCH_DTMF_APP: return "APP";
6145 }
6146 return "UNKNOWN";
6147 }
6148
6149 struct deduplicate_dtmf_filter {
6150 int only_rtp;
6151 char last_dtmf;
6152 switch_dtmf_source_t last_dtmf_source;
6153 };
6154
6155 /**
6156 * Filter incoming DTMF and ignore any duplicates
6157 */
6158 static switch_status_t deduplicate_recv_dtmf_hook(switch_core_session_t *session, const switch_dtmf_t *dtmf, switch_dtmf_direction_t direction)
6159 {
6160 switch_status_t status = SWITCH_STATUS_FALSE;
6161 int only_rtp = 0;
6162 struct deduplicate_dtmf_filter *filter = switch_channel_get_private(switch_core_session_get_channel(session), "deduplicate_dtmf_filter");
6163
6164 if (!filter) {
6165 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Accept %s digit %c: deduplicate filter missing!\n", to_dtmf_source_string(dtmf->source), dtmf->digit);
6166 return SWITCH_STATUS_SUCCESS;
6167 }
6168
6169 /* remember current state as it might change */
6170 only_rtp = filter->only_rtp;
6171
6172 /* RTP DTMF is preferred over all others- and if it's demonstrated to be available, inband / info detection is disabled */
6173 if (only_rtp) {
6174 switch (dtmf->source) {
6175 case SWITCH_DTMF_ENDPOINT:
6176 switch_channel_set_variable(switch_core_session_get_channel(session), "deduplicate_dtmf_seen_endpoint", "true");
6177 break;
6178 case SWITCH_DTMF_INBAND_AUDIO:
6179 switch_channel_set_variable(switch_core_session_get_channel(session), "deduplicate_dtmf_seen_inband", "true");
6180 break;
6181 case SWITCH_DTMF_RTP:
6182 switch_channel_set_variable(switch_core_session_get_channel(session), "deduplicate_dtmf_seen_rtp", "true");
6183 /* pass through */
6184 case SWITCH_DTMF_UNKNOWN:
6185 case SWITCH_DTMF_APP:
6186 /* always allow */
6187 status = SWITCH_STATUS_SUCCESS;
6188 break;
6189 }
6190 } else {
6191 /* accept everything except duplicates until RTP digit is detected */
6192 switch (dtmf->source) {
6193 case SWITCH_DTMF_INBAND_AUDIO:
6194 switch_channel_set_variable(switch_core_session_get_channel(session), "deduplicate_dtmf_seen_inband", "true");
6195 break;
6196 case SWITCH_DTMF_RTP:
6197 switch_channel_set_variable(switch_core_session_get_channel(session), "deduplicate_dtmf_seen_rtp", "true");
6198 /* change state to only allow RTP events */
6199 filter->only_rtp = 1;
6200
6201 /* stop inband detector */
6202 switch_ivr_broadcast(switch_core_session_get_uuid(session), "spandsp_stop_dtmf::", SMF_ECHO_ALEG);
6203 break;
6204 case SWITCH_DTMF_ENDPOINT:
6205 switch_channel_set_variable(switch_core_session_get_channel(session), "deduplicate_dtmf_seen_endpoint", "true");
6206 break;
6207 case SWITCH_DTMF_UNKNOWN:
6208 case SWITCH_DTMF_APP:
6209 /* always allow */
6210 status = SWITCH_STATUS_SUCCESS;
6211 break;
6212 }
6213
6214 /* make sure not a duplicate DTMF */
6215 if (filter->last_dtmf_source == dtmf->source || filter->last_dtmf != dtmf->digit) {
6216 status = SWITCH_STATUS_SUCCESS;
6217 }
6218 filter->last_dtmf = dtmf->digit;
6219 filter->last_dtmf_source = dtmf->source;
6220 }
6221
6222 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "(%s) %s %s digit %c\n",
6223 (only_rtp) ? "ALLOW 2833" : "ALLOW ALL",
6224 (status == SWITCH_STATUS_SUCCESS) ? "Accept" : "Ignore", to_dtmf_source_string(dtmf->source), dtmf->digit);
6225
6226 return status;
6227 }
6228
6229 SWITCH_STANDARD_APP(deduplicate_dtmf_app_function)
6230 {
6231 struct deduplicate_dtmf_filter *filter = switch_channel_get_private(switch_core_session_get_channel(session), "deduplicate_dtmf_filter");
6232 if (!filter) {
6233 filter = switch_core_session_alloc(session, sizeof(*filter));
6234 filter->only_rtp = !zstr(data) && !strcmp("only_rtp", data);
6235 filter->last_dtmf = 0;
6236 switch_channel_set_private(switch_core_session_get_channel(session), "deduplicate_dtmf_filter", filter);
6237 switch_core_event_hook_add_recv_dtmf(session, deduplicate_recv_dtmf_hook);
6238 }
6239 }
6240
6241 SWITCH_STANDARD_APP(vad_test_function)
6242 {
6243 switch_channel_t *channel = switch_core_session_get_channel(session);
6244 switch_codec_implementation_t imp = { 0 };
6245 switch_vad_t *vad;
6246 switch_frame_t *frame = { 0 };
6247 switch_vad_state_t vad_state;
6248 int mode = -1;
6249 const char *var = NULL;
6250 int tmp;
6251
6252 if (!zstr(data)) {
6253 mode = atoi(data);
6254
6255 if (mode > 3) mode = 3;
6256 }
6257
6258 switch_core_session_raw_read(session);
6259 switch_core_session_get_read_impl(session, &imp);
6260
6261 vad = switch_vad_init(imp.samples_per_second, imp.number_of_channels);
6262 switch_assert(vad);
6263
6264 if ((var = switch_channel_get_variable(channel, "vad_debug"))) {
6265 tmp = atoi(var);
6266
6267 if (tmp < 0) tmp = 0;
6268 if (tmp > 1) tmp = 1;
6269
6270 switch_vad_set_param(vad, "debug", tmp);
6271 }
6272
6273 switch_vad_set_mode(vad, mode);
6274
6275 if ((var = switch_channel_get_variable(channel, "vad_silence_ms"))) {
6276 tmp = atoi(var);
6277
6278 if (tmp > 0) switch_vad_set_param(vad, "silence_ms", tmp);
6279 }
6280
6281 if ((var = switch_channel_get_variable(channel, "vad_thresh"))) {
6282 tmp = atoi(var);
6283
6284 if (tmp > 0) switch_vad_set_param(vad, "thresh", tmp);
6285 }
6286
6287 if ((var = switch_channel_get_variable(channel, "vad_voice_ms"))) {
6288 tmp = atoi(var);
6289
6290 if (tmp > 0) switch_vad_set_param(vad, "voice_ms", tmp);
6291 }
6292
6293 while (switch_channel_ready(channel)) {
6294 switch_status_t status = switch_core_session_read_frame(session, &frame, SWITCH_IO_FLAG_NONE, 0);
6295
6296 if (!SWITCH_READ_ACCEPTABLE(status)) {
6297 break;
6298 }
6299
6300 if (switch_test_flag(frame, SFF_CNG)) {
6301 continue;
6302 }
6303
6304 vad_state = switch_vad_process(vad, frame->data, frame->datalen / 2);
6305
6306 if (vad_state == SWITCH_VAD_STATE_START_TALKING) {
6307 switch_core_session_write_frame(session, frame, SWITCH_IO_FLAG_NONE, 0);
6308 } else if (vad_state == SWITCH_VAD_STATE_STOP_TALKING) {
6309 switch_vad_reset(vad);
6310 } else if (vad_state == SWITCH_VAD_STATE_TALKING) {
6311 switch_core_session_write_frame(session, frame, SWITCH_IO_FLAG_NONE, 0);
6312 } else {
6313 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "vad_state: %s\n", switch_vad_state2str(vad_state));
6314 }
6315 }
6316
6317 switch_vad_destroy(&vad);
6318 switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
6319 }
6320
6321 #define DEBUG_MEDIA_SYNTAX "<read|write|both|vread|vwrite|vboth|all> <on|off>"
6322 SWITCH_STANDARD_APP(debug_media_function)
6323 {
6324 char *mycmd = NULL, *argv[2] = { 0 };
6325 int argc = 0;
6326 switch_status_t status = SWITCH_STATUS_FALSE;
6327
6328 if (!zstr(data) && (mycmd = strdup(data))) {
6329 argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
6330 }
6331
6332 if (zstr(data) || argc < 2 || zstr(argv[0]) || zstr(argv[1])) {
6333 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "USAGE: %s\n", DEBUG_MEDIA_SYNTAX);
6334 goto done;
6335 } else {
6336 switch_core_session_message_t msg = { 0 };
6337
6338 msg.message_id = SWITCH_MESSAGE_INDICATE_DEBUG_MEDIA;
6339 msg.string_array_arg[0] = argv[0];
6340 msg.string_array_arg[1] = argv[1];
6341 msg.from = __FILE__;
6342
6343 if (!strcasecmp(argv[0], "all")) {
6344 msg.string_array_arg[0] = "both";
6345 }
6346
6347 again:
6348 status = switch_core_session_receive_message(session, &msg);
6349
6350 if (status == SWITCH_STATUS_SUCCESS && !strcasecmp(argv[0], "all") && !strcmp(msg.string_array_arg[0], "both")) {
6351 msg.string_array_arg[0] = "vboth";
6352 goto again;
6353 }
6354 }
6355
6356 if (status == SWITCH_STATUS_SUCCESS) {
6357 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "media debug on\n");
6358 } else {
6359 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "error to turn on media debug status=%d\n", status);
6360 }
6361
6362 done:
6363
6364 switch_safe_free(mycmd);
6365 }
6366
6367 #define SPEAK_DESC "Speak text to a channel via the tts interface"
6368 #define DISPLACE_DESC "Displace audio from a file to the channels input"
6369 #define SESS_REC_DESC "Starts a background recording of the entire session"
6370
6371 #define SESS_REC_MASK_DESC "Replace audio in a recording with blank data to mask critical voice sections"
6372 #define SESS_REC_UNMASK_DESC "Resume normal operation after calling mask"
6373
6374 #define STOP_SESS_REC_DESC "Stops a background recording of the entire session"
6375 #define SCHED_TRANSF_DESCR "Schedule a transfer in the future"
6376 #define SCHED_BROADCAST_DESCR "Schedule a broadcast in the future"
6377 #define SCHED_HANGUP_DESCR "Schedule a hangup in the future"
6378 #define UNSET_LONG_DESC "Unset a channel variable for the channel calling the application."
6379 #define SET_LONG_DESC "Set a channel variable for the channel calling the application."
6380 #define SET_GLOBAL_LONG_DESC "Set a global variable."
6381 #define SET_PROFILE_VAR_LONG_DESC "Set a caller profile variable for the channel calling the application."
6382 #define EXPORT_LONG_DESC "Set and export a channel variable for the channel calling the application."
6383 #define LOG_LONG_DESC "Logs a channel variable for the channel calling the application."
6384 #define TRANSFER_LONG_DESC "Immediately transfer the calling channel to a new extension"
6385 #define SLEEP_LONG_DESC "Pause the channel for a given number of milliseconds, consuming the audio for that period of time."
6386
6387 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_dptools_shutdown)
6388 {
6389
6390 switch_event_free_subclass(FILE_STRING_CLOSE);
6391 switch_event_free_subclass(FILE_STRING_FAIL);
6392 switch_event_free_subclass(FILE_STRING_OPEN);
6393
6394 switch_event_unbind_callback(pickup_pres_event_handler);
6395 switch_mutex_destroy(globals.pickup_mutex);
6396 switch_core_hash_destroy(&globals.pickup_hash);
6397 switch_mutex_destroy(globals.mutex_mutex);
6398 switch_core_hash_destroy(&globals.mutex_hash);
6399
6400 return SWITCH_STATUS_SUCCESS;
6401 }
6402
6403 SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
6404 {
6405 switch_api_interface_t *api_interface;
6406 switch_application_interface_t *app_interface;
6407 switch_dialplan_interface_t *dp_interface;
6408 switch_chat_interface_t *chat_interface;
6409 switch_file_interface_t *file_interface;
6410 int use_system_commands = 1;
6411
6412 if (switch_true(switch_core_get_variable("disable_system_app_commands"))) {
6413 use_system_commands = 0;
6414 }
6415
6416 if (switch_event_reserve_subclass(FILE_STRING_CLOSE) != SWITCH_STATUS_SUCCESS) {
6417 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", FILE_STRING_CLOSE);
6418 return SWITCH_STATUS_TERM;
6419 }
6420
6421 if (switch_event_reserve_subclass(FILE_STRING_FAIL) != SWITCH_STATUS_SUCCESS) {
6422 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", FILE_STRING_FAIL);
6423 return SWITCH_STATUS_TERM;
6424 }
6425
6426 if (switch_event_reserve_subclass(FILE_STRING_OPEN) != SWITCH_STATUS_SUCCESS) {
6427 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", FILE_STRING_OPEN);
6428 return SWITCH_STATUS_TERM;
6429 }
6430
6431 globals.pool = pool;
6432 switch_core_hash_init(&globals.pickup_hash);
6433 switch_mutex_init(&globals.pickup_mutex, SWITCH_MUTEX_NESTED, globals.pool);
6434 switch_core_hash_init(&globals.mutex_hash);
6435 switch_mutex_init(&globals.mutex_mutex, SWITCH_MUTEX_NESTED, globals.pool);
6436
6437 /* connect my internal structure to the blank pointer passed to me */
6438 *module_interface = switch_loadable_module_create_module_interface(pool, modname);
6439
6440 switch_event_bind(modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY, pickup_pres_event_handler, NULL);
6441
6442
6443 file_string_supported_formats[0] = "file_string";
6444
6445 file_interface = (switch_file_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
6446 file_interface->interface_name = modname;
6447 file_interface->extens = file_string_supported_formats;
6448 file_interface->file_open = file_string_file_open;
6449 file_interface->file_close = file_string_file_close;
6450 file_interface->file_read = file_string_file_read;
6451 file_interface->file_write = file_string_file_write;
6452 file_interface->file_seek = file_string_file_seek;
6453 file_interface->file_set_string = file_string_file_set_string;
6454 file_interface->file_get_string = file_string_file_get_string;
6455
6456 file_url_supported_formats[0] = "file";
6457
6458 file_interface = (switch_file_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
6459 file_interface->interface_name = modname;
6460 file_interface->extens = file_url_supported_formats;
6461 file_interface->file_open = file_url_file_open;
6462 file_interface->file_close = file_url_file_close;
6463 file_interface->file_read = file_url_file_read;
6464 file_interface->file_write = file_url_file_write;
6465 file_interface->file_seek = file_url_file_seek;
6466
6467
6468 error_endpoint_interface = (switch_endpoint_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
6469 error_endpoint_interface->interface_name = "error";
6470 error_endpoint_interface->io_routines = &error_io_routines;
6471
6472 group_endpoint_interface = (switch_endpoint_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
6473 group_endpoint_interface->interface_name = "group";
6474 group_endpoint_interface->io_routines = &group_io_routines;
6475
6476 user_endpoint_interface = (switch_endpoint_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
6477 user_endpoint_interface->interface_name = "user";
6478 user_endpoint_interface->io_routines = &user_io_routines;
6479
6480 pickup_endpoint_interface = (switch_endpoint_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
6481 pickup_endpoint_interface->interface_name = "pickup";
6482 pickup_endpoint_interface->io_routines = &pickup_io_routines;
6483 pickup_endpoint_interface->state_handler = &pickup_event_handlers;
6484
6485 SWITCH_ADD_CHAT(chat_interface, "event", event_chat_send);
6486 SWITCH_ADD_CHAT(chat_interface, "api", api_chat_send);
6487
6488
6489 SWITCH_ADD_API(api_interface, "strepoch", "Convert a date string into epoch time", strepoch_api_function, "<string>");
6490 SWITCH_ADD_API(api_interface, "page", "Send a file as a page", page_api_function, "(var1=val1,var2=val2)<var1=val1,var2=val2><chan1>[:_:<chanN>]");
6491 SWITCH_ADD_API(api_interface, "strmicroepoch", "Convert a date string into micoepoch time", strmicroepoch_api_function, "<string>");
6492 SWITCH_ADD_API(api_interface, "chat", "chat", chat_api_function, "<proto>|<from>|<to>|<message>|[<content-type>]");
6493 SWITCH_ADD_API(api_interface, "strftime", "strftime", strftime_api_function, "<format_string>");
6494 SWITCH_ADD_API(api_interface, "presence", "presence", presence_api_function, PRESENCE_USAGE);
6495
6496 SWITCH_ADD_APP(app_interface, "blind_transfer_ack", "", "", blind_transfer_ack_function, "[true|false]", SAF_NONE);
6497
6498 SWITCH_ADD_APP(app_interface, "bind_digit_action", "bind a key sequence or regex to an action",
6499 "bind a key sequence or regex to an action", bind_digit_action_function, BIND_DIGIT_ACTION_USAGE, SAF_SUPPORT_NOMEDIA);
6500
6501 SWITCH_ADD_APP(app_interface, "capture", "capture data into a var", "capture data into a var",
6502 capture_function, "<varname>|<data>|<regex>", SAF_SUPPORT_NOMEDIA);
6503
6504 SWITCH_ADD_APP(app_interface, "clear_digit_action", "clear all digit bindings", "",
6505 clear_digit_action_function, CLEAR_DIGIT_ACTION_USAGE, SAF_SUPPORT_NOMEDIA);
6506
6507 SWITCH_ADD_APP(app_interface, "digit_action_set_realm", "change binding realm", "",
6508 digit_action_set_realm_function, DIGIT_ACTION_SET_REALM_USAGE, SAF_SUPPORT_NOMEDIA);
6509
6510 SWITCH_ADD_APP(app_interface, "privacy", "Set privacy on calls", "Set caller privacy on calls.", privacy_function, "off|on|name|full|number",
6511 SAF_SUPPORT_NOMEDIA);
6512
6513 SWITCH_ADD_APP(app_interface, "set_audio_level", "set volume", "set volume", set_audio_level_function, "", SAF_NONE);
6514 SWITCH_ADD_APP(app_interface, "set_mute", "set mute", "set mute", set_mute_function, "", SAF_NONE);
6515
6516 SWITCH_ADD_APP(app_interface, "flush_dtmf", "flush any queued dtmf", "flush any queued dtmf", flush_dtmf_function, "", SAF_SUPPORT_NOMEDIA);
6517 SWITCH_ADD_APP(app_interface, "hold", "Send a hold message", "Send a hold message", hold_function, HOLD_SYNTAX, SAF_SUPPORT_NOMEDIA);
6518 SWITCH_ADD_APP(app_interface, "unhold", "Send a un-hold message", "Send a un-hold message", unhold_function, UNHOLD_SYNTAX, SAF_SUPPORT_NOMEDIA);
6519 SWITCH_ADD_APP(app_interface, "mutex", "block on a call flow only allowing one at a time", "", mutex_function, MUTEX_SYNTAX, SAF_SUPPORT_NOMEDIA);
6520 SWITCH_ADD_APP(app_interface, "page", "", "", page_function, PAGE_SYNTAX, SAF_NONE);
6521 SWITCH_ADD_APP(app_interface, "transfer", "Transfer a channel", TRANSFER_LONG_DESC, transfer_function, "<exten> [<dialplan> <context>]",
6522 SAF_SUPPORT_NOMEDIA);
6523 SWITCH_ADD_APP(app_interface, "check_acl", "Check an ip against an ACL list", "Check an ip against an ACL list", check_acl_function,
6524 "<ip> <acl | cidr> [<hangup_cause>]", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
6525 SWITCH_ADD_APP(app_interface, "verbose_events", "Make ALL Events verbose.", "Make ALL Events verbose.", verbose_events_function, "",
6526 SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
6527 SWITCH_ADD_APP(app_interface, "novideo", "Refuse Inbound Video", "Refuse Inbound Video", novideo_function, "",
6528 SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
6529 SWITCH_ADD_APP(app_interface, "cng_plc", "Do PLC on CNG frames", "", cng_plc_function, "",
6530 SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
6531 SWITCH_ADD_APP(app_interface, "early_hangup", "Enable early hangup", "", early_hangup_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
6532 SWITCH_ADD_APP(app_interface, "sleep", "Pause a channel", SLEEP_LONG_DESC, sleep_function, "<pausemilliseconds>", SAF_SUPPORT_NOMEDIA);
6533 SWITCH_ADD_APP(app_interface, "delay_echo", "echo audio at a specified delay", "Delay n ms", delay_function, "<delay ms>", SAF_NONE);
6534 SWITCH_ADD_APP(app_interface, "strftime", "strftime", "strftime", strftime_function, "[<epoch>|]<format string>", SAF_SUPPORT_NOMEDIA);
6535 SWITCH_ADD_APP(app_interface, "phrase", "Say a Phrase", "Say a Phrase", phrase_function, "<macro_name>,<data>", SAF_NONE);
6536 SWITCH_ADD_APP(app_interface, "eval", "Do Nothing", "Do Nothing", eval_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
6537 SWITCH_ADD_APP(app_interface, "set_media_stats", "Set Media Stats", "Set Media Stats", set_media_stats_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
6538 SWITCH_ADD_APP(app_interface, "stop", "Do Nothing", "Do Nothing", eval_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
6539 SWITCH_ADD_APP(app_interface, "set_zombie_exec", "Enable Zombie Execution", "Enable Zombie Execution",
6540 zombie_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
6541 SWITCH_ADD_APP(app_interface, "pre_answer", "Pre-Answer the call", "Pre-Answer the call for a channel.", pre_answer_function, "", SAF_SUPPORT_NOMEDIA);
6542 SWITCH_ADD_APP(app_interface, "answer", "Answer the call", "Answer the call for a channel.", answer_function, "", SAF_SUPPORT_NOMEDIA);
6543 SWITCH_ADD_APP(app_interface, "wait_for_answer", "Wait for call to be answered", "Wait for call to be answered.", wait_for_answer_function, "", SAF_SUPPORT_NOMEDIA);
6544 SWITCH_ADD_APP(app_interface, "wait_for_video_ready", "Wait for video stream to be ready", "Wait for video stream to be ready.", wait_for_video_ready_function, WAIT_FOR_VIDEO_READY_SYNTAX, SAF_NONE);
6545 SWITCH_ADD_APP(app_interface, "hangup", "Hangup the call", "Hangup the call for a channel.", hangup_function, "[<cause>]", SAF_SUPPORT_NOMEDIA);
6546 SWITCH_ADD_APP(app_interface, "set_name", "Name the channel", "Name the channel", set_name_function, "<name>", SAF_SUPPORT_NOMEDIA);
6547 SWITCH_ADD_APP(app_interface, "presence", "Send Presence", "Send Presence.", presence_function, "<rpid> <status> [<id>]",
6548 SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
6549 SWITCH_ADD_APP(app_interface, "log", "Logs to the logger", LOG_LONG_DESC, log_function, "<log_level> <log_string>",
6550 SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
6551 SWITCH_ADD_APP(app_interface, "info", "Display Call Info", "Display Call Info", info_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
6552 SWITCH_ADD_APP(app_interface, "event", "Fire an event", "Fire an event", event_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
6553 SWITCH_ADD_APP(app_interface, "sound_test", "Analyze Audio", "Analyze Audio", sound_test_function, "", SAF_NONE);
6554 SWITCH_ADD_APP(app_interface, "export", "Export a channel variable across a bridge", EXPORT_LONG_DESC, export_function, "<varname>=<value>",
6555 SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
6556 SWITCH_ADD_APP(app_interface, "bridge_export", "Export a channel variable across a bridge", EXPORT_LONG_DESC, bridge_export_function, "<varname>=<value>",
6557 SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
6558 SWITCH_ADD_APP(app_interface, "set", "Set a channel variable", SET_LONG_DESC, set_function, "<varname>=<value>",
6559 SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
6560
6561 SWITCH_ADD_APP(app_interface, "multiset", "Set many channel variables", SET_LONG_DESC, multiset_function, "[^^<delim>]<varname>=<value> <var2>=<val2>",
6562 SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
6563
6564 SWITCH_ADD_APP(app_interface, "push", "Set a channel variable", SET_LONG_DESC, push_function, "<varname>=<value>",
6565 SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
6566
6567 SWITCH_ADD_APP(app_interface, "unshift", "Set a channel variable", SET_LONG_DESC, unshift_function, "<varname>=<value>",
6568 SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
6569
6570 SWITCH_ADD_APP(app_interface, "set_global", "Set a global variable", SET_GLOBAL_LONG_DESC, set_global_function, "<varname>=<value>",
6571 SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
6572 SWITCH_ADD_APP(app_interface, "set_profile_var", "Set a caller profile variable", SET_PROFILE_VAR_LONG_DESC, set_profile_var_function,
6573 "<varname>=<value>", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
6574 SWITCH_ADD_APP(app_interface, "unset", "Unset a channel variable", UNSET_LONG_DESC, unset_function, "<varname>",
6575 SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
6576 SWITCH_ADD_APP(app_interface, "multiunset", "Unset many channel variables", SET_LONG_DESC, multiunset_function, "[^^<delim>]<varname> <var2> <var3>",
6577 SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
6578
6579 SWITCH_ADD_APP(app_interface, "capture_text", "capture text", "capture text", capture_text_function, "", SAF_SUPPORT_NOMEDIA | SAF_SUPPORT_TEXT_ONLY);
6580 SWITCH_ADD_APP(app_interface, "acknowledge_call", "Indicate Call Acknowledged", "Indicate Call Acknowledged on a channel.", acknowledge_call_function, "", SAF_SUPPORT_NOMEDIA);
6581 SWITCH_ADD_APP(app_interface, "ring_ready", "Indicate Ring_Ready", "Indicate Ring_Ready on a channel.", ring_ready_function, "", SAF_SUPPORT_NOMEDIA);
6582 SWITCH_ADD_APP(app_interface, "remove_bugs", "Remove media bugs", "Remove all media bugs from a channel.", remove_bugs_function, "[<function>]", SAF_NONE);
6583 SWITCH_ADD_APP(app_interface, "break", "Break", "Set the break flag.", break_function, "", SAF_SUPPORT_NOMEDIA);
6584 SWITCH_ADD_APP(app_interface, "detect_speech", "Detect speech", "Detect speech on a channel.", detect_speech_function, DETECT_SPEECH_SYNTAX, SAF_NONE);
6585 SWITCH_ADD_APP(app_interface, "play_and_detect_speech", "Play and do speech recognition", "Play and do speech recognition", play_and_detect_speech_function, PLAY_AND_DETECT_SPEECH_SYNTAX, SAF_NONE);
6586 SWITCH_ADD_APP(app_interface, "ivr", "Run an ivr menu", "Run an ivr menu.", ivr_application_function, "<menu_name>", SAF_NONE);
6587 SWITCH_ADD_APP(app_interface, "redirect", "Send session redirect", "Send a redirect message to a session.", redirect_function, "<redirect_data>",
6588 SAF_SUPPORT_NOMEDIA);
6589 SWITCH_ADD_APP(app_interface, "video_refresh", "Send video refresh.", "Send video refresh.", video_refresh_function, "[manual|auto]",
6590 SAF_SUPPORT_NOMEDIA);
6591 SWITCH_ADD_APP(app_interface, "video_decode", "Set video decode.", "Set video decode.", video_set_decode_function, "[[on|wait]|off]",
6592 SAF_NONE);
6593 SWITCH_ADD_APP(app_interface, "send_info", "Send info", "Send info", send_info_function, "<info>", SAF_SUPPORT_NOMEDIA);
6594 SWITCH_ADD_APP(app_interface, "jitterbuffer", "Send session jitterbuffer", "Send a jitterbuffer message to a session.",
6595 jitterbuffer_function, "<jitterbuffer_data>", SAF_SUPPORT_NOMEDIA);
6596 SWITCH_ADD_APP(app_interface, "send_display", "Send session a new display", "Send session a new display.", display_function, "<text>",
6597 SAF_SUPPORT_NOMEDIA);
6598 SWITCH_ADD_APP(app_interface, "respond", "Send session respond", "Send a respond message to a session.", respond_function, "<respond_data>",
6599 SAF_SUPPORT_NOMEDIA);
6600 SWITCH_ADD_APP(app_interface, "deflect", "Send call deflect", "Send a call deflect.", deflect_function, "<deflect_data>", SAF_SUPPORT_NOMEDIA);
6601 SWITCH_ADD_APP(app_interface, "recovery_refresh", "Send call recovery_refresh", "Send a call recovery_refresh.", recovery_refresh_function, "", SAF_SUPPORT_NOMEDIA);
6602 SWITCH_ADD_APP(app_interface, "reuse_caller_profile", "Reuse the caller profile", "Reuse the caller profile", reuse_caller_profile_function, "", SAF_SUPPORT_NOMEDIA);
6603 SWITCH_ADD_APP(app_interface, "queue_dtmf", "Queue dtmf to be sent", "Queue dtmf to be sent from a session", queue_dtmf_function, "<dtmf_data>",
6604 SAF_SUPPORT_NOMEDIA);
6605 SWITCH_ADD_APP(app_interface, "send_dtmf", "Send dtmf to be sent", "Send dtmf to be sent from a session", send_dtmf_function, "<dtmf_data>",
6606 SAF_SUPPORT_NOMEDIA);
6607 SWITCH_ADD_APP(app_interface, "sched_cancel", "cancel scheduled tasks", "cancel scheduled tasks", sched_cancel_function, "[group]",
6608 SAF_SUPPORT_NOMEDIA);
6609 SWITCH_ADD_APP(app_interface, "sched_hangup", SCHED_HANGUP_DESCR, SCHED_HANGUP_DESCR, sched_hangup_function, "[+]<time> [<cause>]",
6610 SAF_SUPPORT_NOMEDIA);
6611 SWITCH_ADD_APP(app_interface, "sched_broadcast", SCHED_BROADCAST_DESCR, SCHED_BROADCAST_DESCR, sched_broadcast_function,
6612 "[+]<time> <path> [aleg|bleg|both]", SAF_SUPPORT_NOMEDIA);
6613 SWITCH_ADD_APP(app_interface, "sched_transfer", SCHED_TRANSF_DESCR, SCHED_TRANSF_DESCR, sched_transfer_function,
6614 "[+]<time> <extension> <dialplan> <context>", SAF_SUPPORT_NOMEDIA);
6615 SWITCH_ADD_APP(app_interface, "execute_extension", "Execute an extension", "Execute an extension", exe_function, EXE_SYNTAX, SAF_SUPPORT_NOMEDIA);
6616 SWITCH_ADD_APP(app_interface, "sched_heartbeat", "Enable Scheduled Heartbeat", "Enable Scheduled Heartbeat",
6617 sched_heartbeat_function, SCHED_HEARTBEAT_SYNTAX, SAF_SUPPORT_NOMEDIA);
6618 SWITCH_ADD_APP(app_interface, "enable_heartbeat", "Enable Media Heartbeat", "Enable Media Heartbeat",
6619 heartbeat_function, HEARTBEAT_SYNTAX, SAF_SUPPORT_NOMEDIA);
6620
6621 SWITCH_ADD_APP(app_interface, "filter_codecs", "Filter Codecs", "Filter Codecs", filter_codecs_function, FILTER_CODECS_SYNTAX, SAF_SUPPORT_NOMEDIA);
6622
6623 SWITCH_ADD_APP(app_interface, "enable_keepalive", "Enable Keepalive", "Enable Keepalive",
6624 keepalive_function, KEEPALIVE_SYNTAX, SAF_SUPPORT_NOMEDIA);
6625
6626 SWITCH_ADD_APP(app_interface, "media_reset", "Reset all bypass/proxy media flags", "Reset all bypass/proxy media flags", media_reset_function, "", SAF_SUPPORT_NOMEDIA);
6627 SWITCH_ADD_APP(app_interface, "mkdir", "Create a directory", "Create a directory", mkdir_function, MKDIR_SYNTAX, SAF_SUPPORT_NOMEDIA);
6628 SWITCH_ADD_APP(app_interface, "rename", "Rename file", "Rename file", rename_function, RENAME_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ZOMBIE_EXEC);
6629 SWITCH_ADD_APP(app_interface, "transfer_vars", "Transfer variables", "Transfer variables", transfer_vars_function, TRANSFER_VARS_SYNTAX,
6630 SAF_SUPPORT_NOMEDIA | SAF_ZOMBIE_EXEC);
6631 SWITCH_ADD_APP(app_interface, "soft_hold", "Put a bridged channel on hold", "Put a bridged channel on hold", soft_hold_function, SOFT_HOLD_SYNTAX,
6632 SAF_NONE);
6633 SWITCH_ADD_APP(app_interface, "bind_meta_app", "Bind a key to an application", "Bind a key to an application", dtmf_bind_function, BIND_SYNTAX,
6634 SAF_SUPPORT_NOMEDIA);
6635 SWITCH_ADD_APP(app_interface, "unbind_meta_app", "Unbind a key from an application", "Unbind a key from an application", dtmf_unbind_function,
6636 UNBIND_SYNTAX, SAF_SUPPORT_NOMEDIA);
6637 SWITCH_ADD_APP(app_interface, "block_dtmf", "Block DTMF", "Block DTMF", dtmf_block_function, "", SAF_SUPPORT_NOMEDIA);
6638 SWITCH_ADD_APP(app_interface, "unblock_dtmf", "Stop blocking DTMF", "Stop blocking DTMF", dtmf_unblock_function, "", SAF_SUPPORT_NOMEDIA);
6639 SWITCH_ADD_APP(app_interface, "intercept", "intercept", "intercept", intercept_function, INTERCEPT_SYNTAX, SAF_NONE);
6640 SWITCH_ADD_APP(app_interface, "eavesdrop", "eavesdrop on a uuid", "eavesdrop on a uuid", eavesdrop_function, eavesdrop_SYNTAX, SAF_MEDIA_TAP);
6641 SWITCH_ADD_APP(app_interface, "native_eavesdrop", "eavesdrop on a uuid", "eavesdrop on a uuid", native_eavesdrop_function, native_eavesdrop_SYNTAX, SAF_MEDIA_TAP);
6642 SWITCH_ADD_APP(app_interface, "three_way", "three way call with a uuid", "three way call with a uuid", three_way_function, threeway_SYNTAX,
6643 SAF_MEDIA_TAP);
6644 SWITCH_ADD_APP(app_interface, "set_user", "Set a User", "Set a User", set_user_function, SET_USER_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
6645 SWITCH_ADD_APP(app_interface, "stop_dtmf", "stop inband dtmf", "Stop detecting inband dtmf.", stop_dtmf_session_function, "", SAF_NONE);
6646 SWITCH_ADD_APP(app_interface, "start_dtmf", "Detect dtmf", "Detect inband dtmf on the session", dtmf_session_function, "", SAF_MEDIA_TAP);
6647 SWITCH_ADD_APP(app_interface, "stop_dtmf_generate", "stop inband dtmf generation", "Stop generating inband dtmf.",
6648 stop_dtmf_session_generate_function, "[write]", SAF_NONE);
6649 SWITCH_ADD_APP(app_interface, "start_dtmf_generate", "Generate dtmf", "Generate inband dtmf on the session", dtmf_session_generate_function, "",
6650 SAF_NONE);
6651 SWITCH_ADD_APP(app_interface, "stop_tone_detect", "stop detecting tones", "Stop detecting tones", stop_fax_detect_session_function, "", SAF_NONE);
6652 SWITCH_ADD_APP(app_interface, "fax_detect", "Detect faxes", "Detect fax send tone", fax_detect_session_function, "", SAF_MEDIA_TAP);
6653 SWITCH_ADD_APP(app_interface, "tone_detect", "Detect tones", "Detect tones", tone_detect_session_function, "", SAF_MEDIA_TAP);
6654 SWITCH_ADD_APP(app_interface, "echo", "Echo", "Perform an echo test against the calling channel", echo_function, "", SAF_SUPPORT_TEXT_ONLY);
6655 SWITCH_ADD_APP(app_interface, "park", "Park", "Park", park_function, "", SAF_SUPPORT_NOMEDIA);
6656 SWITCH_ADD_APP(app_interface, "park_state", "Park State", "Park State", park_state_function, "", SAF_NONE);
6657 SWITCH_ADD_APP(app_interface, "gentones", "Generate Tones", "Generate tones to the channel", gentones_function, "<tgml_script>[|<loops>]", SAF_NONE);
6658 SWITCH_ADD_APP(app_interface, "playback", "Playback File", "Playback a file to the channel", playback_function, "<path>", SAF_NONE);
6659 SWITCH_ADD_APP(app_interface, "broadcast", "Broadcast File", "Broadcast a file to the session", broadcast_function, "<path> <leg>", SAF_NONE);
6660 SWITCH_ADD_APP(app_interface, "endless_playback", "Playback File Endlessly", "Endlessly Playback a file to the channel",
6661 endless_playback_function, "<path>", SAF_NONE);
6662 SWITCH_ADD_APP(app_interface, "loop_playback", "Playback File looply", "Playback a file to the channel looply for limted times",
6663 loop_playback_function, "[+loops] <path>", SAF_NONE);
6664 SWITCH_ADD_APP(app_interface, "att_xfer", "Attended Transfer", "Attended Transfer", att_xfer_function, "<channel_url>", SAF_NONE);
6665 SWITCH_ADD_APP(app_interface, "read", "Read Digits", "Read Digits", read_function,
6666 "<min> <max> <file> <var_name> <timeout> <terminators> <digit_timeout>", SAF_NONE);
6667 SWITCH_ADD_APP(app_interface, "play_and_get_digits", "Play and get Digits", "Play and get Digits",
6668 play_and_get_digits_function,
6669 "\n\t<min> <max> <tries> <timeout> <terminators> <file> <invalid_file> <var_name> <regexp> [<digit_timeout>] ['<failure_ext> [failure_dp [failure_context]]']", SAF_NONE);
6670
6671 SWITCH_ADD_APP(app_interface, "stop_video_write_overlay", "Stop video write overlay", "Stop video write overlay", stop_video_write_overlay_session_function, "<path>", SAF_NONE);
6672 SWITCH_ADD_APP(app_interface, "video_write_overlay", "Video write overlay", "Video write overlay", video_write_overlay_session_function, "<path> [<pos>] [<alpha>]", SAF_MEDIA_TAP);
6673
6674 SWITCH_ADD_APP(app_interface, "stop_record_session", "Stop Record Session", STOP_SESS_REC_DESC, stop_record_session_function, "<path>", SAF_NONE);
6675 SWITCH_ADD_APP(app_interface, "record_session", "Record Session", SESS_REC_DESC, record_session_function, "<path> [+<timeout>]", SAF_MEDIA_TAP);
6676 SWITCH_ADD_APP(app_interface, "record_session_mask", "Mask audio in recording", SESS_REC_MASK_DESC, record_session_mask_function, "<path>", SAF_MEDIA_TAP);
6677 SWITCH_ADD_APP(app_interface, "record_session_unmask", "Stop masking audio in recording", SESS_REC_UNMASK_DESC, record_session_unmask_function, "<path>", SAF_MEDIA_TAP);
6678 SWITCH_ADD_APP(app_interface, "record_session_pause", "Pause recording", "Temporarily pause writing call recording audio to file", record_session_pause_function, "<path>", SAF_MEDIA_TAP);
6679 SWITCH_ADD_APP(app_interface, "record_session_resume", "Resume paused recording", "Resume writing call recording audio to file", record_session_resume_function, "<path>", SAF_MEDIA_TAP);
6680 SWITCH_ADD_APP(app_interface, "record", "Record File", "Record a file from the channels input", record_function,
6681 "<path> [<time_limit_secs>] [<silence_thresh>] [<silence_hits>]", SAF_NONE);
6682 SWITCH_ADD_APP(app_interface, "preprocess", "pre-process", "pre-process", preprocess_session_function, "", SAF_NONE);
6683 SWITCH_ADD_APP(app_interface, "stop_displace_session", "Stop Displace File", "Stop Displacing to a file", stop_displace_session_function, "<path>",
6684 SAF_NONE);
6685 SWITCH_ADD_APP(app_interface, "displace_session", "Displace File", DISPLACE_DESC, displace_session_function, "<path> [<flags>] [+time_limit_ms]",
6686 SAF_MEDIA_TAP);
6687 SWITCH_ADD_APP(app_interface, "speak", "Speak text", SPEAK_DESC, speak_function, "<engine>|<voice>|<text>", SAF_NONE);
6688 SWITCH_ADD_APP(app_interface, "clear_speech_cache", "Clear Speech Handle Cache", "Clear Speech Handle Cache", clear_speech_cache_function, "",
6689 SAF_NONE);
6690 SWITCH_ADD_APP(app_interface, "bridge", "Bridge Audio", "Bridge the audio between two sessions", audio_bridge_function, "<channel_url>",
6691 SAF_SUPPORT_NOMEDIA|SAF_SUPPORT_TEXT_ONLY);
6692 if (use_system_commands) {
6693 SWITCH_ADD_APP(app_interface, "system", "Execute a system command", "Execute a system command", system_session_function, "<command>",
6694 SAF_SUPPORT_NOMEDIA | SAF_ZOMBIE_EXEC);
6695 SWITCH_ADD_APP(app_interface, "bgsystem", "Execute a system command in the background", "Execute a background system command", bgsystem_session_function, "<command>",
6696 SAF_SUPPORT_NOMEDIA | SAF_ZOMBIE_EXEC);
6697 }
6698 SWITCH_ADD_APP(app_interface, "say", "say", "say", say_function, SAY_SYNTAX, SAF_NONE);
6699
6700 SWITCH_ADD_APP(app_interface, "detect_audio", "detect_audio", "detect_audio", detect_audio_function, DETECT_AUDIO_SYNTAX,
6701 SAF_NONE);
6702 SWITCH_ADD_APP(app_interface, "detect_silence", "detect_silence", "detect_silence", detect_silence_function, DETECT_SILENCE_SYNTAX,
6703 SAF_NONE);
6704 SWITCH_ADD_APP(app_interface, "wait_for_silence", "wait_for_silence", "wait_for_silence", wait_for_silence_function, WAIT_FOR_SILENCE_SYNTAX,
6705 SAF_NONE);
6706 SWITCH_ADD_APP(app_interface, "session_loglevel", "session_loglevel", "session_loglevel", session_loglevel_function, SESSION_LOGLEVEL_SYNTAX,
6707 SAF_SUPPORT_NOMEDIA);
6708 SWITCH_ADD_APP(app_interface, "limit", "Limit", LIMIT_DESC, limit_function, LIMIT_USAGE, SAF_SUPPORT_NOMEDIA);
6709 SWITCH_ADD_APP(app_interface, "limit_hash", "Limit", LIMIT_HASH_DESC, limit_hash_function, LIMIT_HASH_USAGE, SAF_SUPPORT_NOMEDIA);
6710 SWITCH_ADD_APP(app_interface, "limit_execute", "Limit", LIMITEXECUTE_DESC, limit_execute_function, LIMITEXECUTE_USAGE, SAF_SUPPORT_NOMEDIA);
6711 SWITCH_ADD_APP(app_interface, "limit_hash_execute", "Limit", LIMITHASHEXECUTE_DESC, limit_hash_execute_function, LIMITHASHEXECUTE_USAGE, SAF_SUPPORT_NOMEDIA);
6712
6713 SWITCH_ADD_APP(app_interface, "pickup", "Pickup", "Pickup a call", pickup_function, PICKUP_SYNTAX, SAF_SUPPORT_NOMEDIA);
6714 SWITCH_ADD_APP(app_interface, "deduplicate_dtmf", "Prevent duplicate inband + 2833 dtmf", "", deduplicate_dtmf_app_function, "[only_rtp]", SAF_SUPPORT_NOMEDIA);
6715
6716 SWITCH_ADD_APP(app_interface, "vad_test", "VAD test", "VAD test, mode = -1(default), 0, 1, 2, 3", vad_test_function, "[mode]", SAF_NONE);
6717 SWITCH_ADD_APP(app_interface, "debug_media", "Debug Media", "Debug Media", debug_media_function, DEBUG_MEDIA_SYNTAX, SAF_SUPPORT_NOMEDIA);
6718
6719 SWITCH_ADD_DIALPLAN(dp_interface, "inline", inline_dialplan_hunt);
6720
6721 /* indicate that the module should continue to be loaded */
6722 return SWITCH_STATUS_SUCCESS;
6723 }
6724
6725 /* For Emacs:
6726 * Local Variables:
6727 * mode:c
6728 * indent-tabs-mode:t
6729 * tab-width:4
6730 * c-basic-offset:4
6731 * End:
6732 * For VIM:
6733 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
6734 */