2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2020, Anthony Minessale II <anthm@freeswitch.org>
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/
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
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
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.
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>
37 * mod_dptools.c -- Raw Audio File Streaming Application Module
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
);
46 SWITCH_STANDARD_DIALPLAN(inline_dialplan_hunt
)
48 switch_caller_extension_t
*extension
= NULL
;
49 char *argv
[128] = { 0 };
51 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
57 if (!caller_profile
) {
58 caller_profile
= switch_channel_get_caller_profile(channel
);
61 if ((extension
= switch_caller_extension_new(session
, "inline", "inline")) == 0) {
66 target
= caller_profile
->destination_number
;
73 lbuf
= switch_core_session_strdup(session
, target
);
76 if (*lbuf
== 'm' && *(lbuf
+ 1) == ':' && *(lbuf
+ 3) == ':') {
81 argc
= switch_separate_string(lbuf
, delim
, argv
, (sizeof(argv
) / sizeof(argv
[0])));
83 for (x
= 0; x
< argc
; x
++) {
85 char *data
= strchr(app
, ':');
95 switch_caller_extension_add_application(session
, extension
, app
, data
);
98 caller_profile
->destination_number
= (char *) caller_profile
->rdnis
;
99 caller_profile
->rdnis
= SWITCH_BLANK_STRING
;
104 struct action_binding
{
109 switch_digit_action_target_t target
;
110 switch_core_session_t
*session
;
113 static switch_status_t
digit_nomatch_action_callback(switch_ivr_dmachine_match_t
*match
)
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
;
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
;
126 channel
= switch_core_session_get_channel(use_session
);
129 switch_channel_set_variable(channel
, "last_non_matching_digits", match
->match_digits
);
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
);
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
);
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
));
144 /* send it back around and skip the dmachine */
145 switch_channel_queue_dtmf_string(channel
, match
->match_digits
);
147 if (use_session
!= session
) {
148 switch_core_session_rwunlock(use_session
);
152 return SWITCH_STATUS_SUCCESS
;
155 static switch_status_t
digit_action_callback(switch_ivr_dmachine_match_t
*match
)
157 struct action_binding
*act
= (struct action_binding
*) match
->user_data
;
158 switch_event_t
*event
;
162 switch_channel_t
*channel
;
163 switch_core_session_t
*use_session
= act
->session
;
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
;
174 string
= switch_core_session_strdup(use_session
, act
->string
);
178 channel
= switch_core_session_get_channel(use_session
);
180 switch_channel_set_variable(channel
, "last_matching_digits", match
->match_digits
);
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
);
187 if (!strncasecmp(string
, "exec", 4)) {
191 if (*string
== ':') {
194 } else if (*string
== '[') {
196 if ((e
= switch_find_end_paren(flags
, '[', ']'))) {
201 exec
= strchr(flags
, 'i') ? 2 : 1;
205 } else if (!strncasecmp(string
, "api:", 4)) {
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
);
214 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, "execute", exec
== 1 ? "non-blocking" : "blocking");
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
));
226 switch_core_session_execute_application(use_session
, string
, act
->value
);
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
;
231 if (act
->target
!= DIGIT_TARGET_BOTH
&& !strchr(flags
, 'H')) {
232 exec_flags
|= SMF_HOLD_BLEG
;
235 switch_ivr_broadcast_in_thread(use_session
, cmd
, exec_flags
);
238 switch_stream_handle_t stream
= { 0 };
239 SWITCH_STANDARD_STREAM(stream
);
240 switch_api_execute(string
, act
->value
, NULL
, &stream
);
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
);
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
);
249 switch_safe_free(stream
.data
);
253 if (use_session
!= act
->session
) {
254 switch_core_session_rwunlock(use_session
);
256 if (act
->target
== DIGIT_TARGET_BOTH
) {
257 use_session
= act
->session
;
262 return SWITCH_STATUS_SUCCESS
;
265 static switch_digit_action_target_t
str2target(const char *target_str
)
267 if (!strcasecmp(target_str
, "peer")) {
268 return DIGIT_TARGET_PEER
;
271 if (!strcasecmp(target_str
, "both")) {
272 return DIGIT_TARGET_BOTH
;
275 return DIGIT_TARGET_SELF
;
278 #define CLEAR_DIGIT_ACTION_USAGE "<realm>|all[,target]"
279 SWITCH_STANDARD_APP(clear_digit_action_function
)
281 //switch_channel_t *channel = switch_core_session_get_channel(session);
282 switch_ivr_dmachine_t
*dmachine
;
285 switch_digit_action_target_t t
, target
= DIGIT_TARGET_SELF
;
287 if (zstr((char *)data
)) {
288 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_WARNING
, "clear_digit_action called with no args");
292 realm
= switch_core_session_strdup(session
, data
);
294 if ((target_str
= strchr(realm
, ','))) {
295 *target_str
++ = '\0';
296 target
= str2target(target_str
);
300 if (target
== DIGIT_TARGET_BOTH
) {
301 t
= DIGIT_TARGET_PEER
;
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
);
312 switch_ivr_dmachine_clear_realm(dmachine
, realm
);
316 if (target
== DIGIT_TARGET_BOTH
) {
317 target
= DIGIT_TARGET_SELF
;
322 #define DIGIT_ACTION_SET_REALM_USAGE "<realm>[,<target>]"
323 SWITCH_STANDARD_APP(digit_action_set_realm_function
)
325 switch_ivr_dmachine_t
*dmachine
;
326 char *realm
= switch_core_session_strdup(session
, data
);
328 switch_digit_action_target_t target
= DIGIT_TARGET_SELF
;
330 if ((target_str
= strchr(realm
, ','))) {
331 *target_str
++ = '\0';
332 target
= str2target(target_str
);
336 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Syntax Error, USAGE %s\n", DIGIT_ACTION_SET_REALM_USAGE
);
341 if ((dmachine
= switch_core_session_get_dmachine(session
, target
))) {
342 switch_ivr_dmachine_set_realm(dmachine
, realm
);
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
)
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;
358 if (!(dmachine
= switch_core_session_get_dmachine(session
, target
))) {
359 uint32_t digit_timeout
= 1500;
360 uint32_t input_timeout
= 0;
363 if ((var
= switch_channel_get_variable(channel
, "bind_digit_digit_timeout"))) {
364 digit_timeout
= switch_atoul(var
);
367 if ((var
= switch_channel_get_variable(channel
, "bind_digit_input_timeout"))) {
368 input_timeout
= switch_atoul(var
);
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
);
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
;
384 if (!strncasecmp(act
->string
, "exec", 4) || !strncasecmp(act
->string
, "api:", 4)) {
386 char *string
= switch_core_session_strdup(session
, act
->string
);
389 if (*string
== '[') {
391 if ((e
= switch_find_end_paren(flags
, '[', ']'))) {
395 if (strchr(flags
, 'P'))
402 switch_ivr_dmachine_bind(dmachine
, act
->realm
, act
->input
, is_priority
, 0, digit_action_callback
, act
);
404 if ((terminators
= switch_channel_get_variable(channel
, "bda_terminators"))) {
405 switch_ivr_dmachine_set_terminators(dmachine
, terminators
);
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
)
415 char *argv
[6] = { 0 };
416 switch_digit_action_target_t target
, bind_target
;
417 char *target_str
= "self", *bind_target_str
= "self";
421 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Syntax Error, USAGE %s\n", BIND_DIGIT_ACTION_USAGE
);
425 mydata
= switch_core_session_strdup(session
, data
);
427 argc
= switch_separate_string(mydata
, ',', argv
, (sizeof(argv
) / sizeof(argv
[0])));
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
);
439 target_str
= argv
[4];
443 bind_target_str
= argv
[5];
446 target
= str2target(target_str
);
447 bind_target
= str2target(bind_target_str
);
451 case DIGIT_TARGET_PEER
:
452 bind_to_session(session
, argv
[0], argv
[1], argv
[2], value
, DIGIT_TARGET_PEER
, bind_target
);
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
);
459 bind_to_session(session
, argv
[0], argv
[1], argv
[2], value
, DIGIT_TARGET_SELF
, bind_target
);
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
)
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
);
502 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Usage: %s\n", DETECT_SPEECH_SYNTAX
);
506 #define PLAY_AND_DETECT_SPEECH_SYNTAX "<file> detect:<engine> {param1=val1,param2=val2}<grammar>"
507 SWITCH_STANDARD_APP(play_and_detect_speech_function
)
509 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
512 const char *response
= "DONE";
516 switch_channel_set_variable(channel
, "detect_speech_result", "");
518 if (zstr(data
) || !(lbuf
= switch_core_session_strdup(session
, data
)) || !(detect
= strstr(lbuf
, "detect:"))) {
520 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Usage: %s\n", PLAY_AND_DETECT_SPEECH_SYNTAX
);
521 response
= "USAGE ERROR";
525 /* trim any trailing space */
527 while (--s
>= lbuf
&& switch_isspace(*s
)) {
531 /* split input at "detect:" */
536 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Usage: %s\n", PLAY_AND_DETECT_SPEECH_SYNTAX
);
537 response
= "USAGE ERROR";
541 /* need to have at 2 parameters for detect */
542 if (switch_separate_string(detect
, ' ', argv
, (sizeof(argv
) / sizeof(argv
[0]))) == 2) {
544 char *engine
= argv
[0];
545 char *grammar
= argv
[1];
547 switch_status_t status
= switch_ivr_play_and_detect_speech(session
, file
, engine
, grammar
, &result
, 0, NULL
);
548 if (status
== SWITCH_STATUS_SUCCESS
) {
550 switch_channel_set_variable(channel
, "detect_speech_result", result
);
552 } else if (status
== SWITCH_STATUS_GENERR
) {
553 response
= "GRAMMAR ERROR";
554 } else if (status
== SWITCH_STATUS_NOT_INITALIZED
) {
555 response
= "ASR INIT ERROR";
561 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Usage: %s\n", PLAY_AND_DETECT_SPEECH_SYNTAX
);
562 response
= "USAGE ERROR";
566 switch_channel_set_variable(channel
, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE
, response
);
569 #define SCHED_HEARTBEAT_SYNTAX "[0|<seconds>]"
570 SWITCH_STANDARD_APP(sched_heartbeat_function
)
575 seconds
= atoi(data
);
577 switch_core_session_sched_heartbeat(session
, seconds
);
582 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Usage: %s\n", SCHED_HEARTBEAT_SYNTAX
);
586 #define FILTER_CODECS_SYNTAX "<codec string>"
587 SWITCH_STANDARD_APP(filter_codecs_function
)
590 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
593 r_sdp
= switch_channel_get_variable(channel
, SWITCH_R_SDP_VARIABLE
);
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
);
599 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Incomplete data\n");
604 #define HEARTBEAT_SYNTAX "[0|<seconds>]"
605 SWITCH_STANDARD_APP(heartbeat_function
)
610 seconds
= atoi(data
);
613 switch_core_session_enable_heartbeat(session
, seconds
);
618 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Usage: %s\n", HEARTBEAT_SYNTAX
);
623 #define KEEPALIVE_SYNTAX "[0|<seconds>]"
624 SWITCH_STANDARD_APP(keepalive_function
)
629 seconds
= atoi(data
);
631 switch_core_session_message_t msg
= { 0 };
633 msg
.message_id
= SWITCH_MESSAGE_INDICATE_KEEPALIVE
;
634 msg
.numeric_arg
= seconds
;
635 switch_core_session_receive_message(session
, &msg
);
637 switch_core_session_enable_heartbeat(session
, seconds
);
642 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Usage: %s\n", HEARTBEAT_SYNTAX
);
646 #define EXE_SYNTAX "<extension> <dialplan> <context>"
647 SWITCH_STANDARD_APP(exe_function
)
649 char *argv
[4] = { 0 };
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]);
656 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Usage: %s\n", EXE_SYNTAX
);
660 #define MKDIR_SYNTAX "<path>"
661 SWITCH_STANDARD_APP(mkdir_function
)
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
);
667 #define RENAME_SYNTAX "<from_path> <to_path>"
668 SWITCH_STANDARD_APP(rename_function
)
670 char *argv
[2] = { 0 };
673 if (!zstr(data
) && (lbuf
= switch_core_session_strdup(session
, data
))
674 && switch_split(lbuf
, ' ', argv
) == 2) {
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]);
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]);
685 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Usage: %s\n", RENAME_SYNTAX
);
689 #define TRANSFER_VARS_SYNTAX "<~variable_prefix|variable>"
690 SWITCH_STANDARD_APP(transfer_vars_function
)
692 char *argv
[1] = { 0 };
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
;
699 switch_core_session_get_partner(session
, &nsession
);
702 switch_ivr_transfer_variable(session
, nsession
, argv
[0]);
703 switch_core_session_rwunlock(nsession
);
705 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Usage: %s\n", TRANSFER_VARS_SYNTAX
);
710 #define SOFT_HOLD_SYNTAX "<unhold key> [<moh_a>] [<moh_b>]"
711 SWITCH_STANDARD_APP(soft_hold_function
)
713 char *argv
[3] = { 0 };
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]);
720 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Usage: %s\n", SOFT_HOLD_SYNTAX
);
724 SWITCH_STANDARD_APP(dtmf_unblock_function
)
726 switch_ivr_unblock_dtmf_session(session
);
729 SWITCH_STANDARD_APP(media_reset_function
)
731 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
732 const char *name
= switch_channel_get_name(channel
);
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
);
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
);
744 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_INFO
, "%sReset MEDIA flags.\n", name
);
747 SWITCH_STANDARD_APP(dtmf_block_function
)
749 switch_ivr_block_dtmf_session(session
);
752 #define UNBIND_SYNTAX "[<key>]"
753 SWITCH_STANDARD_APP(dtmf_unbind_function
)
755 char *key
= (char *) data
;
759 kval
= switch_dtmftoi(key
);
762 switch_ivr_unbind_dtmf_meta_session(session
, kval
);
766 #define BIND_SYNTAX "<key> [a|b|ab] [a|b|o|s|i|1] <app>"
767 SWITCH_STANDARD_APP(dtmf_bind_function
)
769 char *argv
[4] = { 0 };
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;
777 if (strchr(argv
[1], 'a')) {
778 bind_flags
|= SBF_DIAL_ALEG
;
781 if (strchr(argv
[1], 'b')) {
782 bind_flags
|= SBF_DIAL_BLEG
;
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");
789 bind_flags
|= SBF_EXEC_ALEG
;
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");
797 bind_flags
|= SBF_EXEC_BLEG
;
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");
805 bind_flags
|= SBF_EXEC_ALEG
;
809 if (strchr(argv
[2], 'i')) {
810 bind_flags
|= SBF_EXEC_INLINE
;
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");
817 bind_flags
|= SBF_EXEC_OPPOSITE
;
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");
825 bind_flags
|= SBF_EXEC_SAME
;
829 if (strchr(argv
[2], '1')) {
830 bind_flags
|= SBF_ONCE
;
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");
837 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Usage: %s\n", BIND_SYNTAX
);
841 #define INTERCEPT_SYNTAX "[-bleg] <uuid>"
842 SWITCH_STANDARD_APP(intercept_function
)
844 char *argv
[4] = { 0 };
847 switch_bool_t bleg
= SWITCH_FALSE
;
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")) {
856 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Usage: %s\n", INTERCEPT_SYNTAX
);
863 switch_ivr_intercept_session(session
, uuid
, bleg
);
868 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Usage: %s\n", INTERCEPT_SYNTAX
);
873 char *uuid_list
[MAX_SPY
];
877 static int e_callback(void *pArg
, int argc
, char **argv
, char **columnNames
)
879 char *uuid
= argv
[0];
880 struct e_data
*e_data
= (struct e_data
*) pArg
;
882 if (uuid
&& e_data
) {
883 e_data
->uuid_list
[e_data
->total
++] = strdup(uuid
);
890 #define native_eavesdrop_SYNTAX "<uuid> [read|write]"
891 SWITCH_STANDARD_APP(native_eavesdrop_function
)
893 switch_eavesdrop_flag_t flags
= ED_TAP_READ
;
894 char *argv
[2] = { 0 };
900 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "INVALID ARGS usage (%s)\n", native_eavesdrop_SYNTAX
);
904 mydata
= switch_core_session_strdup(session
, data
);
905 argc
= switch_split(mydata
, ' ', argv
);
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
;
915 switch_ivr_eavesdrop_session(session
, argv
[0], NULL
, flags
);
919 #define eavesdrop_SYNTAX "[all | <uuid>]"
920 SWITCH_STANDARD_APP(eavesdrop_function
)
923 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Usage: %s\n", eavesdrop_SYNTAX
);
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");
935 flags
= switch_true(enable_dtmf
) ? ED_DTMF
: ED_NONE
;
938 if (switch_true(whisper_aleg
)) {
939 flags
|= ED_MUX_READ
;
941 if (switch_true(whisper_bleg
)) {
942 flags
|= ED_MUX_WRITE
;
945 /* Defaults to both, if neither is set */
946 if (switch_true(bridge_aleg
)) {
947 flags
|= ED_BRIDGE_READ
;
949 if (switch_true(bridge_bleg
)) {
950 flags
|= ED_BRIDGE_WRITE
;
953 if (!strcasecmp((char *) data
, "all")) {
954 switch_cache_db_handle_t
*db
= 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
;
961 switch_size_t buflen
= sizeof(buf
);
963 switch_status_t status
;
965 while (switch_channel_ready(channel
)) {
966 for (x
= 0; x
< MAX_SPY
; x
++) {
967 switch_safe_free(e_data
.uuid_list
[x
]);
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");
975 switch_cache_db_execute_sql_callback(db
, sql
, e_callback
, &e_data
, &errmsg
);
976 switch_cache_db_release_db_handle(&db
);
978 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "Error: %s\n", errmsg
);
980 if ((file
= switch_channel_get_variable(channel
, "eavesdrop_indicate_failed"))) {
981 switch_ivr_play_file(session
, NULL
, file
, NULL
);
984 switch_ivr_collect_digits_count(session
, buf
, buflen
, 1, "*", &terminator
, 5000, 0, 0);
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;
991 /* If we have a group and 1000 concurrent calls, we will flood the logs. This check avoids this */
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
);
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
);
1004 switch_ivr_collect_digits_count(session
, buf
, buflen
, 1, "*", &terminator
, 5000, 0, 0);
1009 if ((file
= switch_channel_get_variable(channel
, "eavesdrop_indicate_idle"))) {
1010 switch_ivr_play_file(session
, NULL
, file
, NULL
);
1013 switch_ivr_collect_digits_count(session
, buf
, buflen
, 1, "*", &terminator
, 2000, 0, 0);
1017 for (x
= 0; x
< MAX_SPY
; x
++) {
1018 switch_safe_free(e_data
.uuid_list
[x
]);
1024 switch_ivr_eavesdrop_session(session
, data
, require_group
, flags
);
1029 #define threeway_SYNTAX "<uuid>"
1030 SWITCH_STANDARD_APP(three_way_function
)
1033 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Usage: %s\n", threeway_SYNTAX
);
1035 switch_ivr_eavesdrop_session(session
, data
, NULL
, ED_MUX_READ
| ED_MUX_WRITE
);
1039 #define SET_USER_SYNTAX "<user>@<domain> [prefix]"
1040 SWITCH_STANDARD_APP(set_user_function
)
1042 switch_ivr_set_user(session
, data
);
1045 #define SET_AUDIO_LEVEL_SYNTAX "[read|write] <vol>"
1046 SWITCH_STANDARD_APP(set_audio_level_function
)
1048 char *argv
[2] = { 0 };
1053 mydata
= switch_core_session_strdup(session
, data
);
1054 argc
= switch_split(mydata
, ' ', argv
);
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
);
1062 level
= atoi(argv
[1]);
1064 switch_ivr_session_audio(session
, "level", argv
[0], level
);
1069 #define SET_MUTE_SYNTAX "[read|write] [[true|cn level]|false]"
1070 SWITCH_STANDARD_APP(set_mute_function
)
1072 char *argv
[2] = { 0 };
1077 mydata
= switch_core_session_strdup(session
, data
);
1078 argc
= switch_split(mydata
, ' ', argv
);
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
);
1086 if ((level
= atoi(argv
[1])) <= 0) {
1087 level
= switch_true(argv
[1]);
1090 switch_ivr_session_audio(session
, "mute", argv
[0], level
);
1094 SWITCH_STANDARD_APP(capture_text_function
)
1096 switch_ivr_capture_text(session
, switch_true((char *)data
));
1099 SWITCH_STANDARD_APP(acknowledge_call_function
)
1101 switch_channel_acknowledge_call(switch_core_session_get_channel(session
));
1104 SWITCH_STANDARD_APP(ring_ready_function
)
1107 if (!strcasecmp(data
, "queued")) {
1108 switch_channel_ring_ready_value(switch_core_session_get_channel(session
), SWITCH_RING_READY_QUEUED
);
1113 switch_channel_ring_ready(switch_core_session_get_channel(session
));
1116 SWITCH_STANDARD_APP(remove_bugs_function
)
1118 const char *function
= NULL
;
1120 if (!zstr((char *)data
)) {
1124 switch_core_media_bug_remove_all_function(session
, function
);
1127 SWITCH_STANDARD_APP(break_function
)
1129 switch_channel_t
*channel
;
1131 channel
= switch_core_session_get_channel(session
);
1133 if (data
&& strcasecmp(data
, "all")) {
1134 switch_core_session_flush_private_events(session
);
1137 if (switch_channel_test_flag(channel
, CF_BROADCAST
)) {
1138 switch_channel_stop_broadcast(channel
);
1140 switch_channel_set_flag(channel
, CF_BREAK
);
1144 SWITCH_STANDARD_APP(reuse_caller_profile_function
)
1146 switch_channel_t
*channel
;
1147 channel
= switch_core_session_get_channel(session
);
1148 switch_channel_set_flag(channel
, CF_REUSE_CALLER_PROFILE
);
1151 SWITCH_STANDARD_APP(queue_dtmf_function
)
1153 switch_channel_queue_dtmf_string(switch_core_session_get_channel(session
), (const char *) data
);
1156 SWITCH_STANDARD_APP(send_dtmf_function
)
1158 switch_core_session_send_dtmf_string(session
, (const char *) data
);
1161 SWITCH_STANDARD_APP(check_acl_function
)
1164 char *argv
[3] = { 0 };
1166 switch_call_cause_t cause
= SWITCH_CAUSE_CALL_REJECTED
;
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
);
1173 cause
= switch_channel_str2cause(argv
[2]);
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
);
1183 SWITCH_STANDARD_APP(flush_dtmf_function
)
1185 switch_channel_flush_dtmf(switch_core_session_get_channel(session
));
1188 SWITCH_STANDARD_APP(transfer_function
)
1190 char *argv
[4] = { 0 };
1192 int bleg
= 0, both
= 0;
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");
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
);
1210 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "No B-leg present.\n");
1213 switch_ivr_session_transfer(session
, argv
[1], argv
[2], argv
[3]);
1216 switch_ivr_session_transfer(session
, argv
[0], argv
[1], argv
[2]);
1219 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No extension specified.\n");
1224 SWITCH_STANDARD_APP(sched_transfer_function
)
1226 char *argv
[4] = { 0 };
1229 if (!zstr(data
) && (mydata
= switch_core_session_strdup(session
, data
))) {
1230 if (switch_separate_string(mydata
, ' ', argv
, (sizeof(argv
) / sizeof(argv
[0]))) >= 2) {
1235 if (*argv
[0] == '+') {
1236 when
= switch_epoch_time_now(NULL
) + atol(argv
[0] + 1);
1238 when
= atol(argv
[0]);
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
);
1245 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Invalid Args\n");
1250 SWITCH_STANDARD_APP(sched_hangup_function
)
1252 char *argv
[5] = { 0 };
1255 if (!zstr(data
) && (mydata
= switch_core_session_strdup(session
, data
))) {
1256 if (switch_separate_string(mydata
, ' ', argv
, (sizeof(argv
) / sizeof(argv
[0]))) >= 1) {
1258 switch_call_cause_t cause
= SWITCH_CAUSE_ALLOTTED_TIMEOUT
;
1259 switch_bool_t bleg
= SWITCH_FALSE
;
1260 int sec
= atol(argv
[0] + 1);
1262 if (*argv
[0] == '+') {
1263 when
= switch_epoch_time_now(NULL
) + sec
;
1265 when
= atol(argv
[0]);
1269 cause
= switch_channel_str2cause(argv
[1]);
1272 if (argv
[2] && !strcasecmp(argv
[2], "bleg")) {
1277 switch_channel_hangup(switch_core_session_get_channel(session
), cause
);
1279 switch_ivr_schedule_hangup(when
, switch_core_session_get_uuid(session
), cause
, bleg
);
1282 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No time specified.\n");
1287 SWITCH_STANDARD_APP(sched_broadcast_function
)
1289 char *argv
[6] = { 0 };
1292 if (!zstr(data
) && (mydata
= switch_core_session_strdup(session
, data
))) {
1293 if (switch_separate_string(mydata
, ' ', argv
, (sizeof(argv
) / sizeof(argv
[0]))) >= 2) {
1295 switch_media_flag_t flags
= SMF_NONE
;
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);
1304 when
= atol(argv
[0]);
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
;
1316 flags
|= SMF_ECHO_ALEG
;
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
);
1323 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Invalid Args\n");
1328 SWITCH_STANDARD_APP(delay_function
)
1338 switch_ivr_delay_echo(session
, len
);
1341 SWITCH_STANDARD_APP(eval_function
)
1346 SWITCH_STANDARD_APP(set_media_stats_function
)
1348 switch_core_media_set_stats(session
);
1353 SWITCH_STANDARD_APP(zombie_function
)
1355 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
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
);
1366 SWITCH_STANDARD_APP(hangup_function
)
1368 switch_call_cause_t cause
= SWITCH_CAUSE_NORMAL_CLEARING
;
1371 cause
= switch_channel_str2cause(data
);
1374 switch_channel_hangup(switch_core_session_get_channel(session
), cause
);
1377 SWITCH_STANDARD_APP(set_name_function
)
1381 switch_channel_set_name(switch_core_session_get_channel(session
), (char *) data
);
1385 SWITCH_STANDARD_APP(answer_function
)
1387 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
1388 const char *arg
= (char *) data
;
1391 arg
= switch_channel_get_variable(channel
, "answer_flags");
1395 if (switch_stristr("is_conference", arg
)) {
1396 switch_channel_set_flag(channel
, CF_CONFERENCE
);
1398 if (switch_stristr("decode_video", arg
)) {
1399 switch_channel_set_flag_recursive(channel
, CF_VIDEO_DECODED_READ
);
1401 if (switch_stristr("debug_video", arg
)) {
1402 switch_channel_set_flag_recursive(channel
, CF_VIDEO_DEBUG_READ
);
1406 switch_channel_answer(channel
);
1409 SWITCH_STANDARD_APP(wait_for_answer_function
)
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
);
1418 #define WAIT_FOR_VIDEO_READY_SYNTAX "[<ms, 1..10000>]"
1419 SWITCH_STANDARD_APP(wait_for_video_ready_function
)
1421 uint32_t delay
= 0, delay_def
= 10000;
1422 switch_status_t res
;
1424 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
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
);
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
);
1439 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Error (%d) waiting for video stream to be ready\n", res
);
1442 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_NOTICE
, "Cannot wait for video stream on a non video call\n");
1446 SWITCH_STANDARD_APP(presence_function
)
1448 char *argv
[6] = { 0 };
1449 char *mydata
= NULL
;
1450 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
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");
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");
1462 switch_channel_presence(channel
, argv
[0], argv
[1], argv
[2]);
1465 SWITCH_STANDARD_APP(pre_answer_function
)
1467 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
1468 const char *arg
= (char *) data
;
1471 if (switch_stristr("is_conference", arg
)) {
1472 switch_channel_set_flag(channel
, CF_CONFERENCE
);
1476 switch_channel_pre_answer(channel
);
1479 SWITCH_STANDARD_APP(redirect_function
)
1481 switch_core_session_message_t msg
= { 0 };
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
);
1491 SWITCH_STANDARD_APP(video_set_decode_function
)
1493 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
1494 char *txt
= (char *) data
;
1495 int on
= 0, wait
= 0;
1498 on
= !strcasecmp(txt
, "on");
1499 wait
= !strcasecmp(txt
, "wait");
1502 if (data
&& (on
|| wait
)) {
1503 switch_channel_set_flag_recursive(channel
, CF_VIDEO_DECODED_READ
);
1505 switch_core_session_wait_for_video_input_params(session
, 10000);
1508 switch_channel_clear_flag_recursive(channel
, CF_VIDEO_DECODED_READ
);
1512 SWITCH_STANDARD_APP(video_refresh_function
)
1514 switch_core_session_message_t msg
= { 0 };
1515 char *cmd
= (char *)data
;
1518 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
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
);
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");
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
);
1541 SWITCH_STANDARD_APP(send_info_function
)
1543 switch_core_session_message_t msg
= { 0 };
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
;
1551 switch_core_session_receive_message(session
, &msg
);
1554 SWITCH_STANDARD_APP(jitterbuffer_function
)
1556 switch_core_session_message_t msg
= { 0 };
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
);
1565 SWITCH_STANDARD_APP(display_function
)
1567 switch_core_session_message_t msg
= { 0 };
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
);
1576 SWITCH_STANDARD_APP(respond_function
)
1578 switch_core_session_message_t msg
= { 0 };
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
);
1588 SWITCH_STANDARD_APP(deflect_function
)
1590 switch_core_session_message_t msg
= { 0 };
1591 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
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
);
1601 SWITCH_STANDARD_APP(recovery_refresh_function
)
1603 switch_core_session_message_t msg
= { 0 };
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
);
1613 SWITCH_STANDARD_APP(sched_cancel_function
)
1615 const char *group
= data
;
1618 group
= switch_core_session_get_uuid(session
);
1621 if (switch_is_digit_string(group
)) {
1623 tmp
= (uint32_t) atoi(group
);
1625 switch_scheduler_del_task_id((uint32_t) tmp
);
1628 switch_scheduler_del_task_group(group
);
1632 static void base_set (switch_core_session_t
*session
, const char *data
, switch_stack_t stack
)
1634 char *var
, *val
= NULL
;
1635 const char *what
= "SET";
1638 case SWITCH_STACK_PUSH
:
1641 case SWITCH_STACK_UNSHIFT
:
1649 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No variable name specified.\n");
1651 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
1652 char *expanded
= NULL
;
1654 var
= switch_core_session_strdup(session
, data
);
1656 if (!(val
= strchr(var
, '='))) {
1657 val
= strchr(var
, ',');
1668 expanded
= switch_channel_expand_variables(channel
, val
);
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");
1674 switch_channel_add_variable_var_check(channel
, var
, expanded
, SWITCH_FALSE
, stack
);
1676 if (expanded
&& expanded
!= val
) {
1677 switch_safe_free(expanded
);
1682 SWITCH_STANDARD_APP(multiset_function
)
1685 char *arg
= (char *) data
;
1687 if (!zstr(arg
) && *arg
== '^' && *(arg
+1) == '^') {
1693 char *array
[256] = {0};
1696 arg
= switch_core_session_strdup(session
, arg
);
1697 argc
= switch_split(arg
, delim
, array
);
1699 for(i
= 0; i
< argc
; i
++) {
1700 base_set(session
, array
[i
], SWITCH_STACK_BOTTOM
);
1705 base_set(session
, data
, SWITCH_STACK_BOTTOM
);
1709 SWITCH_STANDARD_APP(set_function
)
1711 base_set(session
, data
, SWITCH_STACK_BOTTOM
);
1714 SWITCH_STANDARD_APP(push_function
)
1716 base_set(session
, data
, SWITCH_STACK_PUSH
);
1719 SWITCH_STANDARD_APP(unshift_function
)
1721 base_set(session
, data
, SWITCH_STACK_UNSHIFT
);
1724 SWITCH_STANDARD_APP(set_global_function
)
1726 char *var
, *val
= NULL
;
1729 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No variable name specified.\n");
1733 val
= strchr(var
, '=');
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
);
1748 SWITCH_STANDARD_APP(set_profile_var_function
)
1750 char *name
, *val
= NULL
;
1753 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No variable name specified.\n");
1755 name
= switch_core_session_strdup(session
, data
);
1756 val
= strchr(name
, '=');
1765 switch_channel_set_profile_var(switch_core_session_get_channel(session
), name
, val
);
1769 SWITCH_STANDARD_APP(export_function
)
1771 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
1772 char *var
, *val
= NULL
;
1775 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No variable name specified.\n");
1777 var
= switch_core_session_strdup(session
, data
);
1779 if ((val
= strchr(var
, '='))) {
1786 switch_channel_export_variable_var_check(channel
, var
, val
, SWITCH_EXPORT_VARS_VARIABLE
, SWITCH_FALSE
);
1790 SWITCH_STANDARD_APP(bridge_export_function
)
1792 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
1793 char *var
, *val
= NULL
;
1796 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No variable name specified.\n");
1798 var
= switch_core_session_strdup(session
, data
);
1800 if ((val
= strchr(var
, '='))) {
1807 switch_channel_export_variable(channel
, var
, val
, SWITCH_BRIDGE_EXPORT_VARS_VARIABLE
);
1811 SWITCH_STANDARD_APP(unset_function
)
1814 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No variable name specified.\n");
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
);
1821 SWITCH_STANDARD_APP(multiunset_function
)
1824 char *arg
= (char *) data
;
1826 if (!zstr(arg
) && *arg
== '^' && *(arg
+1) == '^') {
1832 char *array
[256] = {0};
1835 arg
= switch_core_session_strdup(session
, arg
);
1836 argc
= switch_split(arg
, delim
, array
);
1838 for(i
= 0; i
< argc
; i
++) {
1839 switch_channel_set_variable(switch_core_session_get_channel(session
), array
[i
], NULL
);
1843 switch_channel_set_variable(switch_core_session_get_channel(session
), arg
, NULL
);
1848 SWITCH_STANDARD_APP(log_function
)
1850 char *level
, *log_str
;
1852 if (data
&& (level
= strdup(data
))) {
1853 switch_log_level_t ltype
= SWITCH_LOG_DEBUG
;
1855 if ((log_str
= strchr(level
, ' '))) {
1857 ltype
= switch_log_str2level(level
);
1861 if (ltype
== SWITCH_LOG_INVALID
) {
1862 ltype
= SWITCH_LOG_DEBUG
;
1865 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), ltype
, "%s\n", log_str
);
1866 switch_safe_free(level
);
1870 SWITCH_STANDARD_APP(info_function
)
1872 switch_event_t
*event
;
1874 int level
= SWITCH_LOG_INFO
;
1877 level
= switch_log_str2level(data
);
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
);
1884 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), level
, "CHANNEL_DATA:\n%s\n", buf
);
1885 switch_event_destroy(&event
);
1890 SWITCH_STANDARD_APP(sound_test_function
)
1892 switch_ivr_sound_test(session
);
1895 SWITCH_STANDARD_APP(event_function
)
1897 switch_event_t
*event
;
1898 char *argv
[25] = { 0 };
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]))))) {
1907 for (x
= 0; x
< argc
; x
++) {
1908 char *p
, *this = argv
[x
];
1918 if ((val
= strchr(var
, '='))) {
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
);
1935 memcpy(new, val
, len
);
1936 event
->subclass_name
= new;
1937 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, var
, val
);
1939 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, var
, val
);
1945 switch_channel_event_set_data(switch_core_session_get_channel(session
), event
);
1946 switch_event_fire(&event
);
1950 SWITCH_STANDARD_APP(privacy_function
)
1952 switch_caller_profile_t
*caller_profile
= switch_channel_get_caller_profile(switch_core_session_get_channel(session
));
1955 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No privacy mode specified.\n");
1957 switch_set_flag(caller_profile
, SWITCH_CPF_SCREEN
);
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
);
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");
1975 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "Set Privacy to %s [%d]\n", data
, caller_profile
->flags
);
1979 SWITCH_STANDARD_APP(strftime_function
)
1981 char *argv
[2] = { 0 };
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
;
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
);
1997 SWITCH_STANDARD_API(strepoch_api_function
)
2002 out
= switch_micro_time_now();
2004 out
= switch_str_time(cmd
);
2007 stream
->write_function(stream
, "%d", (uint32_t) ((out
) / (int64_t) (1000000)));
2009 return SWITCH_STATUS_SUCCESS
;
2013 SWITCH_STANDARD_API(strmicroepoch_api_function
)
2018 out
= switch_micro_time_now();
2020 out
= switch_str_time(cmd
);
2023 stream
->write_function(stream
, "%"SWITCH_TIME_T_FMT
, out
);
2025 return SWITCH_STATUS_SUCCESS
;
2028 SWITCH_STANDARD_API(strftime_api_function
)
2030 switch_size_t retsize
;
2031 switch_time_exp_t tm
;
2033 switch_time_t thetime
;
2038 mycmd
= strdup(cmd
);
2042 if (!zstr(q
) && (p
= strchr(q
, '|'))) {
2045 thetime
= switch_time_make(atol(q
), 0);
2048 thetime
= switch_micro_time_now();
2050 switch_time_exp_lt(&tm
, thetime
);
2053 switch_strftime_nocheck(date
, &retsize
, sizeof(date
), "%Y-%m-%d %T", &tm
);
2055 switch_strftime(date
, &retsize
, sizeof(date
), q
, &tm
);
2057 stream
->write_function(stream
, "%s", date
);
2058 switch_safe_free(mycmd
);
2060 return SWITCH_STATUS_SUCCESS
;
2064 #define PRESENCE_USAGE "[in|out] <user> <rpid> <message>"
2065 SWITCH_STANDARD_API(presence_api_function
)
2067 switch_event_t
*event
;
2068 char *lbuf
= NULL
, *argv
[4];
2070 switch_event_types_t type
= SWITCH_EVENT_PRESENCE_IN
;
2073 if (!zstr(cmd
) && (lbuf
= strdup(cmd
))
2074 && (argc
= switch_separate_string(lbuf
, ' ', argv
, (sizeof(argv
) / sizeof(argv
[0])))) > 0) {
2076 if (!strcasecmp(argv
[0], "out")) {
2077 type
= SWITCH_EVENT_PRESENCE_OUT
;
2079 } else if (strcasecmp(argv
[0], "in")) {
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");
2099 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, "status", "CS_HANGUP");
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
);
2106 stream
->write_function(stream
, "Event Sent");
2111 switch_safe_free(lbuf
);
2112 return SWITCH_STATUS_SUCCESS
;
2116 switch_safe_free(lbuf
);
2117 stream
->write_function(stream
, "Invalid: presence %s", PRESENCE_USAGE
);
2118 return SWITCH_STATUS_SUCCESS
;
2121 SWITCH_STANDARD_API(chat_api_function
)
2123 char *lbuf
= NULL
, *argv
[5];
2125 if (!zstr(cmd
) && (lbuf
= strdup(cmd
))
2126 && switch_separate_string(lbuf
, '|', argv
, (sizeof(argv
) / sizeof(argv
[0]))) >= 4) {
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");
2131 stream
->write_function(stream
, "Error! Message Not Sent");
2134 stream
->write_function(stream
, "Invalid");
2137 switch_safe_free(lbuf
);
2138 return SWITCH_STATUS_SUCCESS
;
2141 static char *ivr_cf_name
= "ivr.conf";
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
)
2146 switch_ivr_action_t action
= SWITCH_IVR_ACTION_NOOP
;
2148 if (param
!= NULL
) {
2149 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "menu_handler '%s'\n", param
);
2156 SWITCH_STANDARD_APP(ivr_application_function
)
2158 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
2159 switch_event_t
*params
;
2160 const char *name
= (const char *) data
;
2163 switch_xml_t cxml
= NULL
, cfg
= NULL
, xml_menus
= NULL
, xml_menu
= NULL
;
2165 /* Open the config from the xml registry */
2166 switch_event_create(¶ms
, 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
);
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
);
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
;
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
2185 && switch_ivr_menu_stack_xml_build(xml_ctx
, &menu_stack
, xml_menus
, xml_menu
) == SWITCH_STATUS_SUCCESS
) {
2186 switch_xml_free(cxml
);
2188 switch_ivr_menu_execute(session
, menu_stack
, (char *) name
, NULL
);
2189 switch_ivr_menu_stack_free(menu_stack
);
2191 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Unable to create menu\n");
2194 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Unable to find menu\n");
2197 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No menus configured\n");
2199 switch_xml_free(cxml
);
2201 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Open of %s failed\n", ivr_cf_name
);
2203 switch_event_destroy(¶ms
);
2207 SWITCH_STANDARD_APP(dtmf_session_function
)
2209 switch_ivr_inband_dtmf_session(session
);
2212 SWITCH_STANDARD_APP(stop_dtmf_session_function
)
2214 switch_ivr_stop_inband_dtmf_session(session
);
2217 SWITCH_STANDARD_APP(dtmf_session_generate_function
)
2219 switch_bool_t do_read
= SWITCH_TRUE
;
2222 if (!strcasecmp(data
, "write")) {
2223 do_read
= SWITCH_FALSE
;
2226 switch_ivr_inband_dtmf_generate_session(session
, do_read
);
2229 SWITCH_STANDARD_APP(stop_dtmf_session_generate_function
)
2231 switch_ivr_stop_inband_dtmf_generate_session(session
);
2234 SWITCH_STANDARD_APP(fax_detect_session_function
)
2236 switch_ivr_tone_detect_session(session
, "fax", "1100.0", "r", 0, 1, NULL
, NULL
, NULL
);
2239 SWITCH_STANDARD_APP(system_session_function
)
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
);
2247 SWITCH_STANDARD_APP(bgsystem_session_function
)
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
);
2255 SWITCH_STANDARD_APP(tone_detect_session_function
)
2257 char *argv
[7] = { 0 };
2258 char *mydata
= NULL
;
2261 const char *hp
= NULL
;
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");
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");
2275 if (*argv
[3] == '+') {
2276 if ((mto
= atol(argv
[3] + 1)) > 0) {
2277 to
= switch_epoch_time_now(NULL
) + mto
;
2279 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "INVALID Timeout!\n");
2282 if ((to
= atol(argv
[3])) < switch_epoch_time_now(NULL
)) {
2284 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "INVALID Timeout!\n");
2291 if (argv
[4] && argv
[5]) {
2293 } else if (argv
[4] && !argv
[6]) {
2304 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_NOTICE
, "Enabling tone detection '%s' '%s'\n", argv
[0], argv
[1]);
2306 switch_ivr_tone_detect_session(session
, argv
[0], argv
[1], argv
[2], to
, hits
, argv
[4], argv
[5], NULL
);
2309 SWITCH_STANDARD_APP(stop_fax_detect_session_function
)
2311 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_NOTICE
, "Disabling tone detection\n");
2312 switch_ivr_stop_tone_detect_session(session
);
2315 SWITCH_STANDARD_APP(echo_function
)
2317 switch_ivr_session_echo(session
, NULL
);
2320 SWITCH_STANDARD_APP(park_function
)
2322 switch_ivr_park(session
, NULL
);
2325 SWITCH_STANDARD_APP(park_state_function
)
2327 switch_ivr_park_session(session
);
2330 /********************************************************************************/
2331 /* Playback/Record Functions */
2332 /********************************************************************************/
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.
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
)
2340 char *str
= (char *) buf
;
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
;
2348 return SWITCH_STATUS_SUCCESS
;
2351 static switch_status_t
on_dtmf(switch_core_session_t
*session
, void *input
, switch_input_type_t itype
, void *buf
, unsigned int buflen
)
2356 case SWITCH_INPUT_TYPE_DTMF
:
2358 switch_dtmf_t
*dtmf
= (switch_dtmf_t
*) input
;
2359 const char *terminators
;
2360 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
2363 if (!(terminators
= switch_channel_get_variable(channel
, SWITCH_PLAYBACK_TERMINATORS_VARIABLE
))) {
2366 if (!strcasecmp(terminators
, "any")) {
2367 terminators
= "1234567890*#";
2369 if (!strcasecmp(terminators
, "none")) {
2372 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "Digit %c\n", dtmf
->digit
);
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
;
2387 return SWITCH_STATUS_SUCCESS
;
2390 SWITCH_STANDARD_APP(sleep_function
)
2392 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
2395 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No timeout specified.\n");
2397 uint32_t ms
= atoi(data
);
2399 switch_input_args_t args
= { 0 };
2401 if (switch_true(switch_channel_get_variable(channel
, "sleep_eat_digits"))) {
2402 args
.input_callback
= on_dtmf
;
2404 args
.buflen
= sizeof(buf
);
2405 switch_channel_set_variable(channel
, SWITCH_PLAYBACK_TERMINATOR_USED
, "");
2408 switch_ivr_sleep(session
, ms
, SWITCH_TRUE
, &args
);
2412 SWITCH_STANDARD_APP(clear_speech_cache_function
)
2414 switch_ivr_clear_speech_cache(session
);
2417 SWITCH_STANDARD_APP(speak_function
)
2419 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
2421 char *argv
[3] = { 0 };
2423 const char *engine
= NULL
;
2424 const char *voice
= NULL
;
2426 char *mydata
= NULL
;
2427 switch_input_args_t args
= { 0 };
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");
2434 argc
= switch_separate_string(mydata
, '|', argv
, sizeof(argv
) / sizeof(argv
[0]));
2437 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Invalid Params!\n");
2439 } else if (argc
== 1) {
2440 text
= switch_core_session_strdup(session
, data
); /* unstripped text */
2441 } else if (argc
== 2) {
2443 text
= switch_core_session_strdup(session
, data
+ (argv
[1] - argv
[0])); /* unstripped text */
2447 text
= switch_core_session_strdup(session
, data
+ (argv
[2] - argv
[0])); /* unstripped text */
2451 engine
= switch_channel_get_variable(channel
, "tts_engine");
2455 voice
= switch_channel_get_variable(channel
, "tts_voice");
2458 if (!(engine
&& voice
&& text
)) {
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
);
2472 args
.input_callback
= on_dtmf
;
2474 args
.buflen
= sizeof(buf
);
2476 switch_channel_set_variable(channel
, SWITCH_PLAYBACK_TERMINATOR_USED
, "");
2478 switch_ivr_speak_text(session
, engine
, voice
, text
, &args
);
2482 const char *attxfer_cancel_key
;
2483 const char *attxfer_hangup_key
;
2484 const char *attxfer_conf_key
;
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
)
2489 switch_core_session_t
*peer_session
= (switch_core_session_t
*) buf
;
2490 if (!buf
|| !peer_session
) {
2491 return SWITCH_STATUS_SUCCESS
;
2495 case SWITCH_INPUT_TYPE_DTMF
:
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");
2502 if (dtmf
->digit
== *keys
->attxfer_hangup_key
) {
2503 switch_channel_hangup(channel
, SWITCH_CAUSE_NORMAL_CLEARING
);
2504 return SWITCH_STATUS_FALSE
;
2507 if (dtmf
->digit
== *keys
->attxfer_cancel_key
) {
2508 switch_channel_hangup(peer_channel
, SWITCH_CAUSE_NORMAL_CLEARING
);
2509 return SWITCH_STATUS_FALSE
;
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
;
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
)) {
2524 switch_core_session_rwunlock(b_session
);
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");
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
;
2547 return SWITCH_STATUS_SUCCESS
;
2550 static switch_status_t
tmp_hanguphook(switch_core_session_t
*session
)
2552 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
2553 switch_channel_state_t state
= switch_channel_get_state(channel
);
2555 if (state
== CS_HANGUP
|| state
== CS_ROUTING
) {
2556 const char *bond
= switch_channel_get_variable(channel
, SWITCH_SOFT_HOLDING_UUID_VARIABLE
);
2559 switch_core_session_t
*b_session
;
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
);
2566 switch_core_session_rwunlock(b_session
);
2570 switch_core_event_hook_remove_state_change(session
, tmp_hanguphook
);
2573 return SWITCH_STATUS_SUCCESS
;
2576 static switch_status_t
hanguphook(switch_core_session_t
*session
)
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
;
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
);
2592 switch_core_event_hook_remove_state_change(session
, hanguphook
);
2594 return SWITCH_STATUS_SUCCESS
;
2598 static void att_xfer_set_result(switch_channel_t
*channel
, switch_status_t status
)
2600 switch_channel_set_variable(channel
, SWITCH_ATT_XFER_RESULT_VARIABLE
, status
== SWITCH_STATUS_SUCCESS
? "success" : "failure");
2604 switch_core_session_t
*session
;
2609 void *SWITCH_THREAD_FUNC
att_thread_run(switch_thread_t
*thread
, void *obj
)
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
;
2625 if (switch_core_session_read_lock(session
) != SWITCH_STATUS_SUCCESS
) {
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
);
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
);
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
);
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
);
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
= "#";
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
= "*";
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";
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
);
2672 switch_ivr_multi_threaded_bridge(session
, peer_session
, xfer_on_dtmf
, peer_session
, NULL
);
2674 switch_channel_clear_flag(peer_channel
, CF_INNER_BRIDGE
);
2675 switch_channel_clear_flag(channel
, CF_INNER_BRIDGE
);
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
);
2686 switch_channel_set_variable(channel
, SWITCH_SIGNAL_BOND_VARIABLE
, bond
);
2688 if (!switch_channel_down(peer_channel
)) {
2689 if (!switch_channel_ready(channel
)) {
2690 switch_status_t status
;
2692 if (follow_recording
) {
2693 switch_ivr_transfer_recordings(session
, peer_session
);
2695 status
= switch_ivr_uuid_bridge(switch_core_session_get_uuid(peer_session
), bond
);
2696 att_xfer_set_result(peer_channel
, status
);
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
);
2703 switch_core_event_hook_add_state_change(session
, hanguphook
);
2704 switch_core_event_hook_add_state_change(b_session
, hanguphook
);
2706 switch_core_session_rwunlock(b_session
);
2711 switch_status_t status
= switch_ivr_uuid_bridge(switch_core_session_get_uuid(session
), bond
);
2712 att_xfer_set_result(channel
, status
);
2717 switch_core_session_rwunlock(peer_session
);
2721 switch_core_event_hook_remove_state_change(session
, tmp_hanguphook
);
2723 switch_channel_set_variable(channel
, SWITCH_SOFT_HOLDING_UUID_VARIABLE
, NULL
);
2724 switch_channel_clear_flag(channel
, CF_XFER_ZOMBIE
);
2726 switch_core_session_rwunlock(session
);
2732 SWITCH_STANDARD_APP(att_xfer_function
)
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
);
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
);
2744 att
= switch_core_session_alloc(session
, sizeof(*att
));
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
);
2750 while(att
->running
&& switch_channel_up(channel
)) {
2751 switch_yield(100000);
2755 SWITCH_STANDARD_APP(read_function
)
2758 char *argv
[7] = { 0 };
2760 int32_t min_digits
= 0;
2761 int32_t max_digits
= 0;
2762 uint32_t digit_timeout
= 0;
2764 char digit_buffer
[128] = "";
2765 const char *prompt_audio_file
= NULL
;
2766 const char *var_name
= NULL
;
2767 const char *valid_terminators
= NULL
;
2769 if (!zstr(data
) && (mydata
= switch_core_session_strdup(session
, data
))) {
2770 argc
= switch_separate_string(mydata
, ' ', argv
, (sizeof(argv
) / sizeof(argv
[0])));
2772 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No arguments specified.\n");
2776 min_digits
= atoi(argv
[0]);
2779 max_digits
= atoi(argv
[1]);
2783 prompt_audio_file
= argv
[2];
2791 timeout
= atoi(argv
[4]);
2795 valid_terminators
= argv
[5];
2799 digit_timeout
= switch_atoui(argv
[6]);
2802 if (min_digits
<= 1) {
2806 if (max_digits
< min_digits
) {
2807 max_digits
= min_digits
;
2810 if (timeout
<= 1000) {
2814 if (zstr(valid_terminators
)) {
2815 valid_terminators
= "#";
2818 switch_ivr_read(session
, min_digits
, max_digits
, prompt_audio_file
, var_name
, digit_buffer
, sizeof(digit_buffer
), timeout
, valid_terminators
,
2822 SWITCH_STANDARD_APP(play_and_get_digits_function
)
2825 char *argv
[11] = { 0 };
2827 int32_t min_digits
= 0;
2828 int32_t max_digits
= 0;
2829 int32_t max_tries
= 0;
2830 uint32_t digit_timeout
= 0;
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
;
2840 if (!zstr(data
) && (mydata
= switch_core_session_strdup(session
, data
))) {
2841 argc
= switch_separate_string(mydata
, ' ', argv
, (sizeof(argv
) / sizeof(argv
[0])));
2843 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No arguments specified.\n");
2847 min_digits
= atoi(argv
[0]);
2850 max_digits
= atoi(argv
[1]);
2854 max_tries
= atoi(argv
[2]);
2858 timeout
= atoi(argv
[3]);
2862 valid_terminators
= argv
[4];
2866 prompt_audio_file
= argv
[5];
2870 bad_input_audio_file
= argv
[6];
2878 digits_regex
= argv
[8];
2882 digit_timeout
= switch_atoui(argv
[9]);
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
);
2890 if (min_digits
<= 0) {
2894 if (max_digits
< min_digits
) {
2895 max_digits
= min_digits
;
2898 if (timeout
<= 1000) {
2902 if (zstr(valid_terminators
)) {
2903 valid_terminators
= "#";
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
);
2911 #define SAY_SYNTAX "<module_name>[:<lang>] <say_type> <say_method> [<say_gender>] <text>"
2912 SWITCH_STANDARD_APP(say_function
)
2914 char *argv
[5] = { 0 };
2917 switch_input_args_t args
= { 0 };
2918 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
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)) {
2923 args
.input_callback
= on_dtmf
;
2925 switch_channel_set_variable(channel
, SWITCH_PLAYBACK_TERMINATOR_USED
, "");
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]);
2932 switch_ivr_say(session
, (argc
== 4) ? argv
[3] : argv
[4], argv
[0], argv
[1], argv
[2], (argc
== 5) ? argv
[3] : NULL
,&args
);
2934 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Usage: %s\n", SAY_SYNTAX
);
2940 SWITCH_STANDARD_APP(phrase_function
)
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
;
2947 if (!zstr(data
) && (mydata
= switch_core_session_strdup(session
, data
))) {
2949 char *macro
= mydata
;
2952 if ((mdata
= strchr(macro
, ','))) {
2956 lang
= switch_channel_get_variable(channel
, "language");
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
));
2961 args
.input_callback
= on_dtmf
;
2963 switch_channel_set_variable(channel
, SWITCH_PLAYBACK_TERMINATOR_USED
, "");
2965 status
= switch_ivr_phrase_macro(session
, macro
, mdata
, lang
, &args
);
2967 status
= SWITCH_STATUS_NOOP
;
2971 case SWITCH_STATUS_SUCCESS
:
2972 case SWITCH_STATUS_BREAK
:
2973 switch_channel_set_variable(channel
, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE
, "PHRASE PLAYED");
2975 case SWITCH_STATUS_NOOP
:
2976 switch_channel_set_variable(channel
, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE
, "NOTHING");
2979 switch_channel_set_variable(channel
, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE
, "UNKNOWN ERROR");
2985 SWITCH_STANDARD_APP(broadcast_function
)
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 };
2994 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "invalid args for broadcast app\n");
2998 mycmd
= switch_core_session_strdup(session
, data
);
2999 argc
= switch_separate_string(mycmd
, ' ', argv
, (sizeof(argv
) / sizeof(argv
[0])));
3002 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "invalid args for broadcast app [%s]\n", data
);
3006 if (switch_stristr("both", (argv
[1]))) {
3007 flags
|= (SMF_ECHO_ALEG
| SMF_ECHO_BLEG
);
3010 if (switch_stristr("aleg", argv
[1])) {
3011 flags
|= SMF_ECHO_ALEG
;
3014 if (switch_stristr("bleg", argv
[1])) {
3015 flags
&= ~SMF_HOLD_BLEG
;
3016 flags
|= SMF_ECHO_BLEG
;
3019 if (switch_stristr("holdb", argv
[1])) {
3020 flags
&= ~SMF_ECHO_BLEG
;
3021 flags
|= SMF_HOLD_BLEG
;
3024 switch_ivr_broadcast(uuid
, argv
[0], flags
);
3025 switch_channel_set_variable(channel
, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE
, "BROADCAST_SENT");
3029 SWITCH_STANDARD_APP(playback_function
)
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 };
3036 const char *file
= NULL
;
3039 file
= switch_core_session_strdup(session
, data
);
3040 if ((p
= strchr(file
, '@')) && *(p
+ 1) == '@') {
3044 fh
.samples
= atoi(p
);
3051 args
.input_callback
= on_dtmf
;
3053 switch_channel_set_variable(channel
, SWITCH_PLAYBACK_TERMINATOR_USED
, "");
3055 status
= switch_ivr_play_file(session
, &fh
, file
, &args
);
3056 switch_assert(!(fh
.flags
& SWITCH_FILE_OPEN
));
3059 case SWITCH_STATUS_SUCCESS
:
3060 case SWITCH_STATUS_BREAK
:
3061 switch_channel_set_variable(channel
, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE
, "FILE PLAYED");
3063 case SWITCH_STATUS_NOTFOUND
:
3064 switch_channel_set_variable(channel
, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE
, "FILE NOT FOUND");
3067 switch_channel_set_variable(channel
, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE
, "PLAYBACK ERROR");
3075 SWITCH_STANDARD_APP(endless_playback_function
)
3077 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
3078 switch_status_t status
= SWITCH_STATUS_SUCCESS
;
3079 const char *file
= data
;
3081 while (switch_channel_ready(channel
)) {
3082 status
= switch_ivr_play_file(session
, NULL
, file
, NULL
);
3084 if (status
!= SWITCH_STATUS_SUCCESS
&& status
!= SWITCH_STATUS_BREAK
) {
3090 case SWITCH_STATUS_SUCCESS
:
3091 case SWITCH_STATUS_BREAK
:
3092 switch_channel_set_variable(channel
, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE
, "FILE PLAYED");
3094 case SWITCH_STATUS_NOTFOUND
:
3095 switch_channel_set_variable(channel
, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE
, "FILE NOT FOUND");
3098 switch_channel_set_variable(channel
, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE
, "PLAYBACK ERROR");
3104 SWITCH_STANDARD_APP(loop_playback_function
)
3106 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
3107 switch_status_t status
= SWITCH_STATUS_SUCCESS
;
3108 const char *file
= data
;
3112 const char *p
= ++file
;
3113 while(*file
&& *file
++ != ' ') { }
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
);
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
);
3130 while (switch_channel_ready(channel
) && (loop
< 0 || loop
-- > 0)) {
3131 status
= switch_ivr_play_file(session
, NULL
, file
, NULL
);
3133 if (status
!= SWITCH_STATUS_SUCCESS
&& status
!= SWITCH_STATUS_BREAK
) {
3139 case SWITCH_STATUS_SUCCESS
:
3140 case SWITCH_STATUS_BREAK
:
3141 switch_channel_set_variable(channel
, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE
, "FILE PLAYED");
3143 case SWITCH_STATUS_NOTFOUND
:
3144 switch_channel_set_variable(channel
, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE
, "FILE NOT FOUND");
3147 switch_channel_set_variable(channel
, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE
, "PLAYBACK ERROR");
3153 SWITCH_STANDARD_APP(gentones_function
)
3155 char *tone_script
= NULL
;
3156 switch_input_args_t args
= { 0 };
3159 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
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");
3166 if ((l
= strchr(tone_script
, '|'))) {
3175 args
.input_callback
= on_dtmf
;
3177 switch_channel_set_variable(channel
, SWITCH_PLAYBACK_TERMINATOR_USED
, "");
3179 switch_ivr_gentones(session
, tone_script
, loops
, &args
);
3182 SWITCH_STANDARD_APP(displace_session_function
)
3186 char *argv
[6] = { 0 };
3191 if (!zstr(data
) && (lbuf
= switch_core_session_strdup(session
, data
))
3192 && (argc
= switch_separate_string(lbuf
, ' ', argv
, (sizeof(argv
) / sizeof(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
])) {
3201 switch_ivr_displace_session(session
, path
, limit
, flags
);
3205 SWITCH_STANDARD_APP(stop_displace_session_function
)
3207 switch_ivr_stop_displace_session(session
, data
);
3210 SWITCH_STANDARD_APP(capture_function
)
3212 char *argv
[3] = { 0 };
3213 switch_regex_t
*re
= NULL
;
3214 int ovector
[30] = {0};
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
);
3223 switch_regex_safe_free(re
);
3225 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No data specified.\n");
3229 SWITCH_STANDARD_APP(record_function
)
3231 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
3232 switch_status_t status
;
3235 switch_input_args_t args
= { 0 };
3236 switch_file_handle_t fh
= { 0 };
3238 char *mydata
, *argv
[4] = { 0 };
3243 if (!zstr(data
) && (mydata
= switch_core_session_strdup(session
, data
))) {
3244 switch_separate_string(mydata
, ' ', argv
, (sizeof(argv
) / sizeof(argv
[0])));
3246 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No file specified.\n");
3258 limit
= switch_atoui(l
);
3262 fh
.thresh
= switch_atoui(argv
[2]);
3266 fh
.silence_hits
= switch_atoui(argv
[3]);
3269 if ((tmp
= switch_channel_get_variable(channel
, "record_rate"))) {
3272 fh
.samplerate
= rate
;
3276 args
.input_callback
= on_dtmf
;
3278 switch_channel_set_variable(channel
, SWITCH_PLAYBACK_TERMINATOR_USED
, "");
3280 status
= switch_ivr_record_file(session
, &fh
, path
, &args
, limit
);
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
);
3287 SWITCH_STANDARD_APP(preprocess_session_function
)
3289 switch_ivr_preprocess_session(session
, (char *) data
);
3292 SWITCH_STANDARD_APP(record_session_mask_function
)
3294 switch_ivr_record_session_mask(session
, (char *) data
, SWITCH_TRUE
);
3297 SWITCH_STANDARD_APP(record_session_unmask_function
)
3299 switch_ivr_record_session_mask(session
, (char *) data
, SWITCH_FALSE
);
3302 SWITCH_STANDARD_APP(record_session_pause_function
)
3304 switch_ivr_record_session_pause(session
, (char *) data
, SWITCH_TRUE
);
3307 SWITCH_STANDARD_APP(record_session_resume_function
)
3309 switch_ivr_record_session_pause(session
, (char *) data
, SWITCH_FALSE
);
3312 SWITCH_STANDARD_APP(record_session_function
)
3314 char *array
[5] = {0};
3320 switch_event_t
*vars
= NULL
;
3321 char *new_fp
= NULL
;
3327 args
= switch_core_session_strdup(session
, data
);
3328 argc
= switch_split(args
, ' ', array
);
3331 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "usage: <path> [+<timeout>] [{var1=x,var2=y}]\n");
3337 if (*array
[1] == '+') {
3338 limit
= atoi(++array
[1]);
3340 switch_url_decode(array
[2]);
3341 switch_event_create_brackets(array
[2], '{', '}',',', &vars
, &new_fp
, SWITCH_FALSE
);
3344 switch_url_decode(array
[1]);
3345 switch_event_create_brackets(array
[1], '{', '}',',', &vars
, &new_fp
, SWITCH_FALSE
);
3349 switch_ivr_record_session_event(session
, path
, limit
, NULL
, vars
);
3350 switch_event_safe_destroy(vars
);
3353 SWITCH_STANDARD_APP(stop_record_session_function
)
3355 switch_ivr_stop_record_session(session
, data
);
3359 SWITCH_STANDARD_APP(video_write_overlay_session_function
)
3362 char *argv
[3] = { 0 };
3364 switch_img_position_t pos
= POS_LEFT_BOT
;
3365 uint8_t alpha
= 255;
3371 mydata
= switch_core_session_strdup(session
, data
);
3372 argc
= switch_split(mydata
, ' ', argv
);
3375 pos
= parse_img_position(argv
[1]);
3379 int x
= atoi(argv
[2]);
3380 if (x
> 0 && x
< 256) {
3381 alpha
= (uint8_t) x
;
3385 switch_ivr_video_write_overlay_session(session
, argv
[0], pos
, alpha
);
3388 SWITCH_STANDARD_APP(stop_video_write_overlay_session_function
)
3390 switch_ivr_stop_video_write_overlay_session(session
);
3393 /********************************************************************************/
3394 /* Bridge Functions */
3395 /********************************************************************************/
3397 static switch_status_t
camp_fire(switch_core_session_t
*session
, void *input
, switch_input_type_t itype
, void *buf
, unsigned int buflen
)
3400 case SWITCH_INPUT_TYPE_DTMF
:
3402 switch_dtmf_t
*dtmf
= (switch_dtmf_t
*) input
;
3403 char *key
= (char *) buf
;
3405 if (dtmf
->digit
== *key
) {
3406 return SWITCH_STATUS_BREAK
;
3413 return SWITCH_STATUS_SUCCESS
;
3416 struct camping_stake
{
3417 switch_core_session_t
*session
;
3423 static void *SWITCH_THREAD_FUNC
camp_music_thread(switch_thread_t
*thread
, void *obj
)
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 };
3431 switch_status_t status
= SWITCH_STATUS_FALSE
;
3434 session
= stake
->session
;
3436 if (switch_core_session_read_lock(session
) != SWITCH_STATUS_SUCCESS
) {
3440 channel
= switch_core_session_get_channel(stake
->session
);
3442 if ((stop
= switch_channel_get_variable(channel
, "campon_stop_key"))) {
3446 args
.input_callback
= camp_fire
;
3448 args
.buflen
= sizeof(dbuf
);
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
);
3455 while (stake
->running
&& switch_channel_ready(channel
)) {
3456 switch_ivr_parse_signal_data(session
, SWITCH_TRUE
, SWITCH_FALSE
);
3458 if (status
!= SWITCH_STATUS_BREAK
) {
3459 if (!strcasecmp(moh
, "silence")) {
3460 status
= switch_ivr_collect_digits_callback(session
, &args
, 0, 0);
3462 status
= switch_ivr_play_file(session
, NULL
, stake
->moh
, &args
);
3466 if (status
== SWITCH_STATUS_BREAK
) {
3467 switch_channel_set_flag(channel
, CF_NOT_READY
);
3471 switch_core_session_rwunlock(session
);
3478 SWITCH_STANDARD_APP(audio_bridge_function
)
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
;
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
;
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");
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");
3509 if (cid_name
&& !cid_number
) {
3510 cid_number
= cid_name
;
3513 if (cid_number
&& !cid_name
) {
3514 cid_name
= cid_number
;
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");
3522 if (v_campon_retries
) {
3523 if ((tmp
= atoi(v_campon_retries
)) > 0) {
3524 campon_retries
= tmp
;
3528 if (v_campon_timeout
) {
3529 if ((tmp
= atoi(v_campon_timeout
)) > 0) {
3530 campon_timeout
= tmp
;
3534 if (v_campon_sleep
) {
3535 if ((tmp
= atoi(v_campon_sleep
)) > 0) {
3540 switch_channel_answer(caller_channel
);
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
);
3547 camp_data
= (char *) data
;
3550 if (!(moh
= switch_channel_get_variable(caller_channel
, "campon_hold_music"))) {
3551 moh
= switch_channel_get_hold_music(caller_channel
);
3554 if (!zstr(moh
) && !strcasecmp(moh
, "silence")) {
3561 if (!switch_channel_ready(caller_channel
)) {
3566 if (status
== SWITCH_STATUS_SUCCESS
) {
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
);
3579 stake
.session
= session
;
3580 switch_thread_create(&thread
, thd_attr
, camp_music_thread
, &stake
, switch_core_session_get_pool(session
));
3585 int64_t wait
= (int64_t)campon_sleep
* 1000000;
3587 if (--campon_retries
<= 0 || stake
.do_xfer
) {
3592 while (stake
.running
&& wait
> 0 && switch_channel_ready(caller_channel
)) {
3593 switch_yield(100000);
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
);
3603 } while (camping
&& switch_channel_ready(caller_channel
));
3607 switch_channel_set_flag(caller_channel
, CF_NOT_READY
);
3608 switch_thread_join(&status
, thread
);
3611 switch_channel_clear_flag(caller_channel
, CF_NOT_READY
);
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"));
3620 switch_channel_hangup(switch_core_session_get_channel(peer_session
), SWITCH_CAUSE_ORIGINATOR_CANCEL
);
3621 switch_core_session_rwunlock(peer_session
);
3629 switch_ivr_originate(session
, &peer_session
, &cause
, data
, 0, NULL
, NULL
, NULL
, NULL
, NULL
, SOF_NONE
, NULL
, NULL
)) != SWITCH_STATUS_SUCCESS
) {
3635 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_INFO
, "Originate Failed. Cause: %s\n", switch_channel_cause2str(cause
));
3637 switch_channel_set_variable(caller_channel
, "originate_failed_cause", switch_channel_cause2str(cause
));
3639 switch_channel_handle_cause(caller_channel
, cause
);
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
);
3650 if (switch_channel_test_flag(caller_channel
, CF_PROXY_MODE
)) {
3651 switch_ivr_signal_bridge(session
, peer_session
);
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");
3656 switch_input_callback_function_t func
= NULL
;
3659 a_key
= switch_core_session_strdup(session
, a_key
);
3663 b_key
= switch_core_session_strdup(session
, b_key
);
3667 func
= bridge_on_dtmf
;
3673 switch_ivr_multi_threaded_bridge(session
, peer_session
, func
, a_key
, b_key
);
3677 switch_core_session_rwunlock(peer_session
);
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
;
3690 /* pickup channel */
3694 typedef struct pickup_node_s
{
3697 struct pickup_node_s
*next
;
3701 #define PICKUP_PROTO "pickup"
3704 static int pickup_count(const char *key_name
)
3707 pickup_node_t
*head
, *np
;
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
++;
3713 switch_mutex_unlock(globals
.pickup_mutex
);
3719 static void pickup_send_presence(const char *key_name
)
3722 char *domain_name
, *dup_key_name
= NULL
, *dup_domain_name
= NULL
, *dup_id
= NULL
;
3723 switch_event_t
*event
;
3727 dup_key_name
= strdup(key_name
);
3728 switch_assert(dup_key_name
);
3729 key_name
= dup_key_name
;
3731 if ((domain_name
= strchr(dup_key_name
, '@'))) {
3732 *domain_name
++ = '\0';
3735 if (zstr(domain_name
)) {
3736 dup_domain_name
= switch_core_get_domain(SWITCH_TRUE
);
3737 domain_name
= dup_domain_name
;
3740 if (zstr(domain_name
)) {
3741 domain_name
= "cluecon.com";
3744 dup_id
= switch_mprintf("%s@%s", key_name
, domain_name
);
3746 count
= pickup_count(dup_id
);
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
);
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
);
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
);
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
);
3786 switch_safe_free(dup_domain_name
);
3787 switch_safe_free(dup_key_name
);
3788 switch_safe_free(dup_id
);
3792 static void pickup_pres_event_handler(switch_event_t
*event
)
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
;
3798 if (!to
|| strncasecmp(to
, "pickup+", 7) || !strchr(to
, '@')) {
3802 if (!(dup_to
= strdup(to
))) {
3806 key_name
= dup_to
+ 7;
3808 if ((domain_name
= strchr(key_name
, '@'))) {
3809 *domain_name
++ = '\0';
3811 dup_domain_name
= switch_core_get_domain(SWITCH_TRUE
);
3812 domain_name
= dup_domain_name
;
3815 if (zstr(domain_name
)) {
3816 switch_safe_free(dup_to
);
3817 switch_safe_free(dup_domain_name
);
3821 dup_key_name
= switch_mprintf("%q@%q", key_name
, domain_name
);
3822 count
= pickup_count(dup_key_name
);
3824 switch_event_create(&event
, SWITCH_EVENT_PRESENCE_IN
);
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
);
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");
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
);
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");
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
);
3865 static void pickup_add_session(switch_core_session_t
*session
, const char *key
)
3867 pickup_node_t
*head
, *node
, *np
;
3868 char *dup_key
= NULL
;
3870 if (!strchr(key
, '@')) {
3871 dup_key
= switch_mprintf("%s@%s", key
, switch_core_get_domain(SWITCH_FALSE
));
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
));
3881 switch_mutex_lock(globals
.pickup_mutex
);
3882 head
= switch_core_hash_find(globals
.pickup_hash
, key
);
3885 for (np
= head
; np
&& np
->next
; np
= np
->next
);
3889 switch_core_hash_insert(globals
.pickup_hash
, key
, head
);
3892 switch_mutex_unlock(globals
.pickup_mutex
);
3894 pickup_send_presence(key
);
3896 switch_safe_free(dup_key
);
3899 static char *pickup_pop_uuid(const char *key
, const char *uuid
)
3901 pickup_node_t
*node
= NULL
, *head
;
3903 char *dup_key
= NULL
;
3905 if (!strchr(key
, '@')) {
3906 dup_key
= switch_mprintf("%s@%s", key
, switch_core_get_domain(SWITCH_FALSE
));
3910 switch_mutex_lock(globals
.pickup_mutex
);
3912 if ((head
= switch_core_hash_find(globals
.pickup_hash
, key
))) {
3914 switch_core_hash_delete(globals
.pickup_hash
, key
);
3917 pickup_node_t
*np
, *lp
= NULL
;
3919 for(np
= head
; np
; np
= np
->next
) {
3920 if (!strcmp(np
->uuid
, uuid
)) {
3922 lp
->next
= np
->next
;
3941 switch_core_hash_insert(globals
.pickup_hash
, key
, head
);
3951 switch_mutex_unlock(globals
.pickup_mutex
);
3953 if (r
) pickup_send_presence(key
);
3955 switch_safe_free(dup_key
);
3961 typedef struct pickup_pvt_s
{
3963 switch_event_t
*vars
;
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
3976 static switch_status_t
pickup_event_handler(switch_core_session_t
*session
)
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
);
3985 if (tech_pvt
->vars
) {
3986 switch_event_destroy(&tech_pvt
->vars
);
3990 return SWITCH_STATUS_FALSE
;
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
;
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
);
4003 switch_channel_clear_flag(channel
, CF_CHANNEL_SWAP
);
4006 uuid
= pickup_pop_uuid(tech_pvt
->key
, switch_core_session_get_uuid(session
));
4007 switch_safe_free(uuid
);
4015 return SWITCH_STATUS_SUCCESS
;
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
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
)
4040 switch_call_cause_t cause
= SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
;
4041 switch_core_session_t
*nsession
;
4042 switch_channel_t
*nchannel
;
4044 pickup_pvt_t
*tech_pvt
;
4045 switch_caller_profile_t
*caller_profile
;
4047 if (zstr(outbound_profile
->destination_number
)) {
4051 pickup
= outbound_profile
->destination_number
;
4053 flags
|= SOF_NO_LIMITS
;
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")))) {
4058 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_CRIT
, "Error Creating Session\n");
4062 tech_pvt
= switch_core_session_alloc(nsession
, sizeof(*tech_pvt
));
4063 tech_pvt
->key
= switch_core_session_strdup(nsession
, pickup
);
4066 switch_core_session_set_private(nsession
, tech_pvt
);
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
);
4072 caller_profile
= switch_caller_profile_clone(nsession
, outbound_profile
);
4073 switch_channel_set_caller_profile(nchannel
, caller_profile
);
4075 switch_channel_set_state(nchannel
, CS_ROUTING
);
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
);
4086 switch_event_del_header(var_event
, "presence_id");
4088 pickup_add_session(nsession
, pickup
);
4089 switch_channel_set_flag(nchannel
, CF_PICKUP
);
4090 switch_channel_set_flag(nchannel
, CF_NO_PRESENCE
);
4092 switch_event_dup(&tech_pvt
->vars
, var_event
);
4108 #define PICKUP_SYNTAX "[<key>]"
4109 SWITCH_STANDARD_APP(pickup_function
)
4112 switch_core_session_t
*pickup_session
;
4113 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
4116 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_WARNING
, "Missing data. Usage: pickup %s\n", PICKUP_SYNTAX
);
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
);
4130 for(hp
= tech_pvt
->vars
->headers
; hp
; hp
= hp
->next
) {
4131 switch_channel_set_variable(channel
, hp
->name
, hp
->value
);
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
));
4138 name
= caller_profile
->caller_id_name
;
4139 num
= caller_profile
->caller_id_number
;
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
);
4144 caller_profile
->callee_id_name
= name
;
4145 caller_profile
->callee_id_number
= num
;
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");
4152 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, "Bridged-To", partner_uuid
);
4154 switch_channel_event_set_data(channel
, event
);
4155 switch_event_fire(&event
);
4159 switch_channel_set_state(channel
, CS_HIBERNATE
);
4161 switch_channel_mark_answered(pickup_channel
);
4162 switch_core_session_rwunlock(pickup_session
);
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
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
)
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
;
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
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
)
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
;
4226 group
= strdup(outbound_profile
->destination_number
);
4231 if ((domain
= strchr(group
, '@'))) {
4234 domain
= switch_core_get_domain(SWITCH_TRUE
);
4235 dup_domain
= domain
;
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
);
4249 template = switch_mprintf("${group_call(%s@%s)}", group
, domain
);
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
);
4257 } else if (var_event
) {
4258 dest
= switch_event_expand_headers(var_event
, template);
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
);
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
);
4278 if ((flags
& SOF_FORKED_DIAL
)) {
4279 myflags
|= SOF_NOBLOCK
;
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
;
4288 new_channel
= switch_core_session_get_channel(*new_session
);
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
);
4295 switch_core_session_rwunlock(*new_session
);
4301 if (dest
&& dest
!= template) {
4302 switch_safe_free(dest
);
4305 switch_safe_free(template);
4306 switch_safe_free(group
);
4307 switch_safe_free(dup_domain
);
4309 if (cause
== SWITCH_CAUSE_NONE
) {
4310 cause
= SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER
;
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
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
)
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
;
4345 if (zstr(outbound_profile
->destination_number
)) {
4349 user
= strdup(outbound_profile
->destination_number
);
4354 if ((domain
= strchr(user
, '@'))) {
4357 domain
= switch_core_get_domain(SWITCH_TRUE
);
4358 dup_domain
= domain
;
4366 switch_event_create(¶ms
, 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");
4372 switch_event_merge(params
, var_event
);
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
);
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
;
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");
4393 if (!strcasecmp(pvar
, "dial-string")) {
4395 } else if (!strncasecmp(pvar
, "dial-var-", 9)) {
4397 switch_event_create(&var_event
, SWITCH_EVENT_GENERAL
);
4399 switch_event_del_header(var_event
, pvar
+ 9);
4401 switch_event_add_header_string(var_event
, SWITCH_STACK_BOTTOM
, pvar
+ 9, val
);
4406 dialed_user
= (char *)switch_xml_attr(x_user
, "id");
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
);
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
;
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
;
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");
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
);
4439 switch_channel_set_variable(channel
, "dialed_user", dialed_user
);
4440 switch_channel_set_variable(channel
, "dialed_domain", domain
);
4442 d_dest
= switch_channel_expand_variables(channel
, dest
);
4445 switch_event_t
*event
= NULL
;
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
);
4456 switch_event_create(&event
, SWITCH_EVENT_REQUEST_PARAMS
);
4457 switch_assert(event
);
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
);
4466 if ((flags
& SOF_NO_LIMITS
)) {
4467 myflags
|= SOF_NO_LIMITS
;
4470 if ((flags
& SOF_FORKED_DIAL
)) {
4471 myflags
|= SOF_NOBLOCK
;
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",
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
;
4487 switch_event_del_header(var_event
, "origination_uuid");
4491 new_channel
= switch_core_session_get_channel(*new_session
);
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
);
4498 switch_core_session_rwunlock(*new_session
);
4501 if (d_dest
!= dest
) {
4502 switch_safe_free(d_dest
);
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
);
4519 switch_xml_free(x_user
);
4523 switch_event_destroy(¶ms
);
4526 if (var_event
&& var_event_orig
!= var_event
) {
4527 switch_event_destroy(&var_event
);
4530 switch_safe_free(user
);
4531 switch_safe_free(dup_domain
);
4536 #define HOLD_SYNTAX "[<display message>]"
4537 SWITCH_STANDARD_APP(hold_function
)
4539 switch_ivr_hold_uuid(switch_core_session_get_uuid(session
), data
, 1);
4542 #define UNHOLD_SYNTAX ""
4543 SWITCH_STANDARD_APP(unhold_function
)
4545 switch_ivr_unhold_uuid(switch_core_session_get_uuid(session
));
4548 SWITCH_STANDARD_APP(novideo_function
)
4550 switch_channel_set_flag(switch_core_session_get_channel(session
), CF_NOVIDEO
);
4553 SWITCH_STANDARD_APP(verbose_events_function
)
4555 switch_channel_set_flag(switch_core_session_get_channel(session
), CF_VERBOSE_EVENTS
);
4558 SWITCH_STANDARD_APP(cng_plc_function
)
4560 switch_channel_set_flag(switch_core_session_get_channel(session
), CF_CNG_PLC
);
4563 SWITCH_STANDARD_APP(early_hangup_function
)
4565 switch_channel_set_flag(switch_core_session_get_channel(session
), CF_EARLY_HANGUP
);
4568 #define WAIT_FOR_SILENCE_SYNTAX "<silence_thresh> <silence_hits> <listen_hits> <timeout_ms> [<file>]"
4569 SWITCH_STANDARD_APP(wait_for_silence_function
)
4571 char *argv
[5] = { 0 };
4572 uint32_t thresh
, silence_hits
, listen_hits
, timeout_ms
= 0;
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]);
4582 timeout_ms
= switch_atoui(argv
[3]);
4585 if (thresh
> 0 && silence_hits
> 0) {
4586 switch_ivr_wait_for_silence(session
, thresh
, silence_hits
, listen_hits
, timeout_ms
, argv
[4]);
4592 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Usage: %s\n", WAIT_FOR_SILENCE_SYNTAX
);
4595 #define DETECT_AUDIO_SYNTAX "<threshold> <audio_hits> <timeout_ms> [<file>]"
4596 SWITCH_STANDARD_APP(detect_audio_function
)
4598 char *argv
[4] = { 0 };
4599 uint32_t thresh
, audio_hits
, timeout_ms
= 0;
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]);
4608 if (thresh
> 0 && audio_hits
> 0) {
4609 switch_ivr_detect_audio(session
, thresh
, audio_hits
, timeout_ms
, argv
[3]);
4615 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Usage: %s\n", DETECT_AUDIO_SYNTAX
);
4618 #define DETECT_SILENCE_SYNTAX "<threshold> <silence_hits> <timeout_ms> [<file>]"
4619 SWITCH_STANDARD_APP(detect_silence_function
)
4621 char *argv
[4] = { 0 };
4622 uint32_t thresh
, silence_hits
, timeout_ms
= 0;
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]);
4631 if (thresh
> 0 && silence_hits
> 0) {
4632 switch_ivr_detect_silence(session
, thresh
, silence_hits
, timeout_ms
, argv
[3]);
4638 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Usage: %s\n", DETECT_SILENCE_SYNTAX
);
4641 static switch_status_t
event_chat_send(switch_event_t
*message_event
)
4644 switch_event_t
*event
;
4647 switch_event_dup(&event
, message_event
);
4648 event
->event_id
= SWITCH_EVENT_RECV_MESSAGE
;
4650 if ((to
= switch_event_get_header(event
, "to"))) {
4652 if ((v
= switch_core_get_variable_dup(to
))) {
4653 switch_event_add_header_string(event
, SWITCH_STACK_BOTTOM
, "Command", v
);
4658 if (switch_event_fire(&event
) == SWITCH_STATUS_SUCCESS
) {
4659 return SWITCH_STATUS_SUCCESS
;
4662 switch_event_destroy(&event
);
4664 return SWITCH_STATUS_MEMERR
;
4667 static switch_status_t
api_chat_send(switch_event_t
*message_event
)
4672 //const char *subject;
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");
4688 switch_stream_handle_t stream
= { 0 };
4689 char *cmd
= NULL
, *arg
;
4691 if (!(v
= switch_core_get_variable_dup(to
))) {
4698 switch_url_decode(cmd
);
4700 if ((arg
= strchr(cmd
, ' '))) {
4704 SWITCH_STANDARD_STREAM(stream
);
4705 switch_api_execute(cmd
, arg
, NULL
, &stream
);
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
);
4711 switch_safe_free(stream
.data
);
4717 return SWITCH_STATUS_SUCCESS
;
4721 #define SESSION_LOGLEVEL_SYNTAX "<level>"
4722 SWITCH_STANDARD_APP(session_loglevel_function
)
4725 switch_log_level_t level
= switch_log_str2level(data
);
4727 if (level
== SWITCH_LOG_INVALID
) {
4728 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Invalid log level: %s\n", data
);
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
);
4734 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No log level specified\n");
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
)
4744 char *argv
[7] = { 0 };
4745 char *mydata
= NULL
;
4746 char *backend
= NULL
;
4749 char *xfer_exten
= NULL
;
4752 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
4754 /* Parse application data */
4756 mydata
= switch_core_session_strdup(session
, data
);
4757 argc
= switch_separate_string(mydata
, ' ', argv
, (sizeof(argv
) / sizeof(argv
[0])));
4762 /* must have at least one item */
4764 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "USAGE: limit %s\n", LIMIT_USAGE
);
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])));
4779 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "USAGE: limit %s\n", LIMIT_USAGE
);
4786 /* If max is omitted or negative, only act as a counter and skip maximum checks */
4788 if (argv
[3][0] == '-') {
4791 char *szinterval
= NULL
;
4792 if ((szinterval
= strchr(argv
[3], '/'))) {
4793 *szinterval
++ = '\0';
4794 interval
= atoi(szinterval
);
4797 max
= atoi(argv
[3]);
4806 xfer_exten
= argv
[4];
4808 xfer_exten
= LIMIT_DEF_XFER_EXTEN
;
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));
4816 switch_ivr_session_transfer(session
, xfer_exten
, argv
[5], argv
[6]);
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
)
4825 char *mydata
= NULL
;
4826 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
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
);
4833 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "'limit_hash' (deprecated) is only available after loading mod_limit.\n");
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
)
4842 char *argv
[6] = { 0 };
4843 char *mydata
= NULL
;
4844 char *backend
= NULL
;
4848 char *app_arg
= NULL
;
4851 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
4853 /* Parse application data */
4855 mydata
= switch_core_session_strdup(session
, data
);
4856 argc
= switch_separate_string(mydata
, ' ', argv
, (sizeof(argv
) / sizeof(argv
[0])));
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")) &&
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");
4868 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "USAGE: limit_execute %s\n", LIMITEXECUTE_USAGE
);
4876 /* Accept '-' as unlimited (act as counter) */
4877 if (argv
[3][0] == '-') {
4880 char *szinterval
= NULL
;
4882 if ((szinterval
= strchr(argv
[3], '/'))) {
4883 *szinterval
++ = '\0';
4884 interval
= atoi(szinterval
);
4887 max
= atoi(argv
[3]);
4898 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Missing application\n");
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
);
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
)
4916 char *mydata
= NULL
;
4917 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
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
);
4924 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "'limit_hash_execute' (deprecated) is only available after loading mod_limit.\n");
4930 /* FILE STRING INTERFACE */
4932 /* for apr_pstrcat */
4933 #define DEFAULT_PREBUFFER_SIZE 1024 * 64
4935 struct file_string_audio_col
{
4936 switch_audio_col_t col
;
4938 struct file_string_audio_col
*next
;
4941 typedef struct file_string_audio_col file_string_audio_col_t
;
4943 struct file_string_context
{
4949 switch_file_handle_t fh
;
4950 file_string_audio_col_t
*audio_cols
;
4953 typedef struct file_string_context file_string_context_t
;
4955 #define FILE_STRING_OPEN "filestring::open"
4956 #define FILE_STRING_CLOSE "filestring::close"
4957 #define FILE_STRING_FAIL "filestring::fail"
4959 static switch_status_t
next_file(switch_file_handle_t
*handle
)
4961 file_string_context_t
*context
= handle
->private_info
;
4963 const char *prefix
= handle
->prefix
;
4964 switch_status_t status
= SWITCH_STATUS_SUCCESS
;
4965 switch_event_t
*event
= NULL
;
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
);
4977 switch_core_file_close(&context
->fh
);
4980 if (context
->index
>= context
->argc
) {
4981 return SWITCH_STATUS_FALSE
;
4986 if (!(prefix
= switch_core_get_variable_pdup("sound_prefix", handle
->memory_pool
))) {
4987 prefix
= SWITCH_GLOBAL_dirs
.sounds_dir
;
4991 if (!prefix
|| switch_is_file_path(context
->argv
[context
->index
])) {
4992 file
= context
->argv
[context
->index
];
4994 file
= switch_core_sprintf(handle
->memory_pool
, "%s%s%s", prefix
, SWITCH_PATH_SEPARATOR
, context
->argv
[context
->index
]);
4997 if (switch_test_flag(handle
, SWITCH_FILE_FLAG_WRITE
)) {
4998 char *path
= switch_core_strdup(handle
->memory_pool
, file
);
5001 if ((p
= strrchr(path
, *SWITCH_PATH_SEPARATOR
))) {
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
);
5009 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Error creating %s\n", path
);
5010 return SWITCH_STATUS_FALSE
;
5014 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Error finding the folder path section in '%s'\n", path
);
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
);
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
);
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
);
5036 if (handle
->dbuflen
) {
5038 handle
->dbuflen
= 0;
5039 handle
->dbuf
= NULL
;
5042 if (switch_test_flag(handle
, SWITCH_FILE_FLAG_WRITE
)) {
5043 file_string_audio_col_t
*col_ptr
= context
->audio_cols
;
5046 switch_core_file_set_string(&context
->fh
, col_ptr
->col
, col_ptr
->value
);
5047 col_ptr
= col_ptr
->next
;
5050 if (context
->file
&& switch_test_flag(handle
, SWITCH_FILE_DATA_SHORT
)) { /* TODO handle other data type flags */
5052 uint16_t buf
[SWITCH_RECOMMENDED_BUFFER_SIZE
] = { 0 };
5053 switch_file_handle_t fh
= { 0 };
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
;
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
);
5064 } while (stat
== SWITCH_STATUS_SUCCESS
);
5066 switch_core_file_close(&fh
);
5067 switch_file_remove(context
->file
, handle
->memory_pool
);
5070 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Can't open %s\n", context
->file
);
5074 context
->file
= file
;
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;
5087 if (switch_test_flag((&context
->fh
), SWITCH_FILE_NATIVE
)) {
5088 switch_set_flag_locked(handle
, SWITCH_FILE_NATIVE
);
5090 switch_clear_flag_locked(handle
, SWITCH_FILE_NATIVE
);
5094 if (!switch_test_flag(handle
, SWITCH_FILE_NATIVE
)) {
5095 if (context
->index
== 0) {
5096 context
->samples
= (handle
->samplerate
/ 1000) * 250;
5104 static switch_status_t
file_string_file_seek(switch_file_handle_t
*handle
, unsigned int *cur_sample
, int64_t samples
, int whence
)
5106 file_string_context_t
*context
= handle
->private_info
;
5108 if (samples
== 0 && whence
== SEEK_SET
) {
5109 context
->index
= -1;
5110 return next_file(handle
);
5113 if (!handle
->seekable
) {
5114 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_WARNING
, "File is not seekable\n");
5115 return SWITCH_STATUS_NOTIMPL
;
5118 return switch_core_file_seek(&context
->fh
, cur_sample
, samples
, whence
);
5121 static switch_status_t
file_string_file_open(switch_file_handle_t
*handle
, const char *path
)
5123 file_string_context_t
*context
;
5126 context
= switch_core_alloc(handle
->memory_pool
, sizeof(*context
));
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;
5132 handle
->private_info
= context
;
5133 handle
->pre_buffer_datalen
= 0;
5135 return next_file(handle
);
5138 static switch_status_t
file_string_file_close(switch_file_handle_t
*handle
)
5140 file_string_context_t
*context
= handle
->private_info
;
5142 if (switch_test_flag((&context
->fh
), SWITCH_FILE_OPEN
)) {
5143 switch_core_file_close(&context
->fh
);
5146 return SWITCH_STATUS_SUCCESS
;
5149 static switch_status_t
file_string_file_set_string(switch_file_handle_t
*handle
, switch_audio_col_t col
, const char *string
)
5151 file_string_context_t
*context
= handle
->private_info
;
5152 file_string_audio_col_t
*col_ptr
= context
->audio_cols
;
5154 while (col_ptr
&& col
!= col_ptr
->col
) {
5155 col_ptr
= col_ptr
->next
;
5159 col_ptr
->value
= switch_core_strdup(handle
->memory_pool
, string
);
5161 col_ptr
= switch_core_alloc(handle
->memory_pool
, sizeof(*col_ptr
));
5162 col_ptr
->value
= switch_core_strdup(handle
->memory_pool
, string
);
5164 col_ptr
->next
= context
->audio_cols
;
5165 context
->audio_cols
= col_ptr
;
5168 return switch_core_file_set_string(&context
->fh
, col
, string
);
5171 static switch_status_t
file_string_file_get_string(switch_file_handle_t
*handle
, switch_audio_col_t col
, const char **string
)
5173 file_string_context_t
*context
= handle
->private_info
;
5175 return switch_core_file_get_string(&context
->fh
, col
, string
);
5179 static switch_status_t
file_string_file_read(switch_file_handle_t
*handle
, void *data
, size_t *len
)
5181 file_string_context_t
*context
= handle
->private_info
;
5182 switch_status_t status
;
5185 if (context
->samples
> 0) {
5186 if (*len
> (size_t) context
->samples
) {
5187 *len
= context
->samples
;
5190 context
->samples
-= (int) *len
;
5191 memset(data
, 255, *len
*2);
5192 status
= SWITCH_STATUS_SUCCESS
;
5194 status
= switch_core_file_read(&context
->fh
, data
, len
);
5197 if (status
!= SWITCH_STATUS_SUCCESS
) {
5198 if ((status
= next_file(handle
)) != SWITCH_STATUS_SUCCESS
) {
5201 if (switch_test_flag(handle
, SWITCH_FILE_BREAK_ON_CHANGE
)) {
5203 status
= SWITCH_STATUS_BREAK
;
5206 status
= switch_core_file_read(&context
->fh
, data
, len
);
5214 static switch_status_t
file_string_file_write(switch_file_handle_t
*handle
, void *data
, size_t *len
)
5216 file_string_context_t
*context
= handle
->private_info
;
5217 switch_status_t status
;
5220 status
= switch_core_file_write(&context
->fh
, data
, len
);
5222 if (status
!= SWITCH_STATUS_SUCCESS
) {
5223 if ((status
= next_file(handle
)) != SWITCH_STATUS_SUCCESS
) {
5227 status
= switch_core_file_write(&context
->fh
, data
, len
);
5232 static switch_status_t
file_url_file_seek(switch_file_handle_t
*handle
, unsigned int *cur_sample
, int64_t samples
, int whence
)
5234 switch_file_handle_t
*fh
= handle
->private_info
;
5235 return switch_core_file_seek(fh
, cur_sample
, samples
, whence
);
5238 static switch_status_t
file_url_file_close(switch_file_handle_t
*handle
)
5240 switch_file_handle_t
*fh
= handle
->private_info
;
5241 if (switch_test_flag(fh
, SWITCH_FILE_OPEN
)) {
5242 switch_core_file_close(fh
);
5245 return SWITCH_STATUS_SUCCESS
;
5248 static switch_status_t
file_url_file_read(switch_file_handle_t
*handle
, void *data
, size_t *len
)
5250 switch_file_handle_t
*fh
= handle
->private_info
;
5251 return switch_core_file_read(fh
, data
, len
);
5254 static switch_status_t
file_url_file_open(switch_file_handle_t
*handle
, const char *path
)
5256 switch_file_handle_t
*fh
= switch_core_alloc(handle
->memory_pool
, sizeof(*fh
));
5257 switch_status_t status
;
5262 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "NULL path\n");
5263 return SWITCH_STATUS_FALSE
;
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
;
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
;
5279 /* decode and check path */
5281 if (zstr(url_path
)) {
5282 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "empty path\n");
5283 return SWITCH_STATUS_FALSE
;
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
;
5290 url_path
= switch_core_sprintf(handle
->memory_pool
, "/%s", url_path
);
5291 switch_url_decode(url_path
);
5293 /* TODO convert to native file separators? */
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;
5308 if (switch_test_flag(fh
, SWITCH_FILE_NATIVE
)) {
5309 switch_set_flag_locked(handle
, SWITCH_FILE_NATIVE
);
5311 switch_clear_flag_locked(handle
, SWITCH_FILE_NATIVE
);
5317 static switch_status_t
file_url_file_write(switch_file_handle_t
*handle
, void *data
, size_t *len
)
5319 switch_file_handle_t
*fh
= handle
->private_info
;
5320 return switch_core_file_write(fh
, data
, len
);
5325 static char *file_string_supported_formats
[SWITCH_MAX_CODECS
] = { 0 };
5326 static char *file_url_supported_formats
[SWITCH_MAX_CODECS
] = { 0 };
5329 /* /FILE STRING INTERFACE */
5332 SWITCH_STANDARD_APP(blind_transfer_ack_function
)
5334 switch_bool_t val
= 0;
5337 val
= (switch_bool_t
)switch_true((char *) data
);
5340 switch_ivr_blind_transfer_ack(session
, val
);
5345 typedef struct mutex_node_s
{
5347 struct mutex_node_s
*next
;
5351 MUTEX_FLAG_WAIT
= (1 << 0),
5352 MUTEX_FLAG_SET
= (1 << 1)
5355 struct read_frame_data
{
5358 const char *context
;
5363 typedef struct master_mutex_s
{
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
);
5371 static switch_status_t
read_frame_callback(switch_core_session_t
*session
, switch_frame_t
*frame
, void *user_data
)
5373 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
5374 struct read_frame_data
*rf
= (struct read_frame_data
*) user_data
;
5376 if (rf
->to
&& --rf
->to
<= 0) {
5378 return SWITCH_STATUS_FALSE
;
5381 return switch_channel_test_app_flag_key(rf
->key
, channel
, MUTEX_FLAG_WAIT
) ? SWITCH_STATUS_SUCCESS
: SWITCH_STATUS_FALSE
;
5385 static void free_node(mutex_node_t
**npp
)
5392 switch_safe_free(np
->uuid
);
5397 static void cancel(switch_core_session_t
*session
, master_mutex_t
*master
)
5399 mutex_node_t
*np
, *lp
= NULL
;
5400 const char *uuid
= switch_core_session_get_uuid(session
);
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
);
5411 lp
->next
= np
->next
;
5413 if ((master
->list
= np
->next
)) {
5414 advance(master
, SWITCH_FALSE
);
5426 switch_mutex_unlock(globals
.mutex_mutex
);
5430 static void advance(master_mutex_t
*master
, switch_bool_t pop_current
)
5433 switch_mutex_lock(globals
.mutex_mutex
);
5435 if (!master
|| !master
->list
) {
5439 while (master
->list
) {
5447 master
->list
= master
->list
->next
;
5449 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_DEBUG
, "ADVANCE POP %p\n", (void *)np
);
5455 switch_core_session_t
*session
;
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
);
5467 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "uuid %s already gone\n", master
->list
->uuid
);
5475 switch_mutex_unlock(globals
.mutex_mutex
);
5480 static void confirm(switch_core_session_t
*session
, master_mutex_t
*master
)
5482 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
5485 if (!(master
= switch_channel_get_private(channel
, "_mutex_master"))) {
5490 switch_mutex_lock(globals
.mutex_mutex
);
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
);
5501 cancel(session
, master
);
5505 switch_mutex_unlock(globals
.mutex_mutex
);
5510 static switch_status_t
mutex_hanguphook(switch_core_session_t
*session
)
5512 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
5513 switch_channel_state_t state
= switch_channel_get_state(channel
);
5515 if (state
!= CS_HANGUP
) {
5516 return SWITCH_STATUS_SUCCESS
;
5519 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "%s mutex hangup hook\n", switch_channel_get_name(channel
));
5521 confirm(session
, NULL
);
5522 switch_core_event_hook_remove_state_change(session
, mutex_hanguphook
);
5524 return SWITCH_STATUS_SUCCESS
;
5527 static switch_bool_t
do_mutex(switch_core_session_t
*session
, const char *key
, switch_bool_t on
)
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
;
5535 struct read_frame_data rf
= { 0 };
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
);
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
;
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
);
5554 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "EXIST MASTER %s %p\n", key
, (void *) master
);
5559 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "HIT ON\n");
5561 switch_zmalloc(node
, sizeof(*node
));
5562 node
->uuid
= strdup(switch_core_session_get_uuid(session
));
5565 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "CHECK MASTER LIST %p\n", (void *) master
->list
);
5567 for (np
= master
->list
; np
&& np
->next
; np
= np
->next
);
5569 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "HIT ON np %p\n", (void *) np
);
5573 switch_channel_set_app_flag_key(key
, channel
, MUTEX_FLAG_WAIT
);
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
);
5587 confirm(session
, master
);
5589 switch_mutex_unlock(globals
.mutex_mutex
);
5593 switch_mutex_unlock(globals
.mutex_mutex
);
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
);
5597 if ((feedback
= switch_channel_get_variable(channel
, "mutex_feedback"))) {
5598 if (!strcasecmp(feedback
, "silence")) {
5599 feedback
= "silence_stream://-1";
5603 if ((rf
.exten
= switch_channel_get_variable(channel
, "mutex_orbit_exten"))) {
5607 if ((var
= switch_channel_get_variable(channel
, "mutex_timeout"))) {
5608 long tmp
= atol(var
);
5616 switch_codec_implementation_t read_impl
;
5617 switch_core_session_get_read_impl(session
, &read_impl
);
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");
5626 args
.read_frame_callback
= read_frame_callback
;
5627 args
.user_data
= &rf
;
5629 while(switch_channel_ready(channel
) && switch_channel_test_app_flag_key(key
, channel
, MUTEX_FLAG_WAIT
)) {
5633 switch_channel_pre_answer(channel
);
5634 st
= switch_ivr_play_file(session
, NULL
, feedback
, &args
);
5636 if ((st
= switch_ivr_sleep(session
, 20, SWITCH_FALSE
, NULL
)) == SWITCH_STATUS_SUCCESS
) {
5637 st
= read_frame_callback(session
, NULL
, &rf
);
5641 if (st
!= SWITCH_STATUS_SUCCESS
) {
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
);
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
);
5656 switch_mutex_unlock(globals
.mutex_mutex
);
5661 #define MUTEX_SYNTAX "<keyname>[ on|off]"
5662 SWITCH_STANDARD_APP(mutex_function
)
5666 switch_bool_t on
= SWITCH_TRUE
;
5669 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "Missing keyname\n");
5673 key
= switch_core_session_sprintf(session
, "_mutex_key_%s", (char *)data
);
5675 if ((arg
= strchr(key
, ' '))) {
5678 if (!strcasecmp(arg
, "off")) {
5683 do_mutex(session
, key
, on
);
5690 typedef struct page_data_s
{
5692 const char *dial_str
;
5694 const char *context
;
5697 switch_event_t
*var_event
;
5698 switch_memory_pool_t
*pool
;
5699 switch_mutex_t
*mutex
;
5702 static switch_status_t
page_hanguphook(switch_core_session_t
*session
)
5704 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
5705 switch_channel_state_t state
= switch_channel_get_state(channel
);
5707 if (state
== CS_HANGUP
) {
5710 if ((pd
= (page_data_t
*) switch_channel_get_private(channel
, "__PAGE_DATA"))) {
5711 uint32_t *counter
= pd
->counter
;
5713 switch_mutex_lock(pd
->mutex
);
5715 switch_mutex_unlock(pd
->mutex
);
5720 switch_core_event_hook_remove_state_change(session
, page_hanguphook
);
5723 return SWITCH_STATUS_SUCCESS
;
5726 void *SWITCH_THREAD_FUNC
page_thread(switch_thread_t
*thread
, void *obj
)
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
;
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
);
5738 switch_channel_set_variable(channel
, "page_file", pd
->path
);
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
);
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
);
5751 switch_mutex_unlock(pd
->mutex
);
5754 switch_event_safe_destroy(pd
->var_event
);
5757 switch_core_destroy_memory_pool(&pool
);
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
)
5767 switch_thread_data_t
*td
;
5768 switch_memory_pool_t
*pool
;
5771 switch_core_new_memory_pool(&pool
);
5773 pd
= switch_core_alloc(pool
, sizeof(*pd
));
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
);
5782 if (var_event
&& *var_event
) {
5783 switch_event_dup(&pd
->var_event
, *var_event
);
5784 switch_event_destroy(var_event
);
5787 switch_mutex_lock(pd
->mutex
);
5789 switch_mutex_unlock(pd
->mutex
);
5791 pd
->counter
= counter
;
5793 td
= switch_core_alloc(pool
, sizeof(*td
));
5794 td
->func
= page_thread
;
5797 switch_thread_pool_launch_thread(&td
);
5801 typedef struct call_monitor_s
{
5802 switch_memory_pool_t
*pool
;
5805 const char *context
;
5808 uint32_t chunk_size
;
5814 void *SWITCH_THREAD_FUNC
call_monitor_thread(switch_thread_t
*thread
, void *obj
)
5816 call_monitor_t
*cm
= (call_monitor_t
*) obj
;
5818 switch_mutex_t
*mutex
;
5819 uint32_t counter
= 0;
5820 switch_memory_pool_t
*pool
= cm
->pool
;
5822 char *argv
[512] = { 0 };
5824 switch_event_t
*var_event
= NULL
;
5827 switch_mutex_init(&mutex
, SWITCH_MUTEX_NESTED
, cm
->pool
);
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
);
5836 while (data
&& *data
&& *data
== ' ') {
5840 while (data
&& *data
== '<') {
5841 char *parsed
= NULL
;
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");
5851 while (data
&& *data
&& *data
== ' ') {
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");
5861 if (cm
->chunk_size
> size
) {
5862 cm
->chunk_size
= size
;
5865 while (sent
< size
) {
5867 switch_mutex_lock(mutex
);
5868 busy
= (counter
>= cm
->chunk_size
);
5869 switch_mutex_unlock(mutex
);
5872 switch_yield(100000);
5877 launch_call(argv
[sent
++], cm
->path
, cm
->exten
, cm
->context
, cm
->dp
, mutex
, &counter
, &var_event
);
5884 switch_mutex_lock(mutex
);
5885 switch_mutex_unlock(mutex
);
5886 switch_yield(100000);
5889 if (cm
->nuke
&& !zstr(cm
->path
)) {
5894 switch_core_destroy_memory_pool(&pool
);
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
)
5902 switch_thread_data_t
*td
;
5903 switch_memory_pool_t
*pool
;
5906 switch_core_new_memory_pool(&pool
);
5908 cm
= switch_core_alloc(pool
, sizeof(*cm
));
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
;
5922 td
= switch_core_alloc(pool
, sizeof(*td
));
5923 td
->func
= call_monitor_thread
;
5926 switch_thread_pool_launch_thread(&td
);
5931 #define PAGE_SYNTAX "<var1=val1,var2=val2><chan1>[:_:<chanN>]"
5932 SWITCH_STANDARD_APP(page_function
)
5934 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
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
;
5944 const char *context
= NULL
;
5945 const char *dp
= "inline";
5946 const char *pdata
= data
;
5949 pdata
= switch_channel_get_variable(channel
, "page_data");
5953 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "No channels specified.\n");
5958 exten
= switch_channel_get_variable(channel
, "page_exten");
5959 context
= switch_channel_get_variable(channel
, "page_context");
5961 if ((l
= switch_channel_get_variable(channel
, "page_dp"))) {
5966 l
= switch_channel_get_variable(channel
, "page_record_limit");
5973 limit
= switch_atoui(l
);
5977 if ((l
= switch_channel_get_variable(channel
, "page_record_thresh"))) {
5978 fh
.thresh
= switch_atoui(l
);
5981 if ((l
= switch_channel_get_variable(channel
, "page_chunk_size"))) {
5982 uint32_t chunk
= switch_atoui(l
);
5989 if ((l
= switch_channel_get_variable(channel
, "page_record_silence_hits"))) {
5990 fh
.silence_hits
= switch_atoui(l
);
5993 if ((tmp
= switch_channel_get_variable(channel
, "record_rate"))) {
5996 fh
.samplerate
= rate
;
6000 args
.input_callback
= on_dtmf
;
6002 switch_channel_set_variable(channel
, SWITCH_PLAYBACK_TERMINATOR_USED
, "");
6005 if (!(path
= switch_channel_get_variable(channel
, "page_path"))) {
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
));
6011 if (!(beep
= switch_channel_get_variable(channel
, "page_beep"))) {
6012 beep
= "tone_stream://%(500,0, 620)";
6015 switch_ivr_play_file(session
, NULL
, beep
, NULL
);
6018 switch_ivr_record_file(session
, &fh
, path
, &args
, limit
);
6022 exten
= switch_core_session_sprintf(session
, "playback:%s", path
);
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
);
6028 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_ERROR
, "File %s does not exist\n", path
);
6034 SWITCH_STANDARD_API(page_api_function
)
6036 char *odata
= NULL
, *data
= NULL
;
6037 switch_event_t
*var_event
= NULL
;
6039 char *oexten
= NULL
;
6040 const char *context
= NULL
;
6041 const char *dp
= "inline";
6042 const char *pdata
= NULL
;
6044 uint32_t chunk_size
= 10;
6049 stream
->write_function(stream
, "-ERR no data");
6053 odata
= strdup(cmd
);
6056 while (data
&& *data
&& *data
== ' ') {
6060 while (data
&& *data
== '(') {
6061 char *parsed
= NULL
;
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");
6071 while (data
&& *data
&& *data
== ' ') {
6076 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Parse Error!\n");
6083 pdata
= switch_event_get_header(var_event
, "page_data");
6087 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "No channels specified.\n");
6092 exten
= switch_event_get_header(var_event
, "page_exten");
6093 context
= switch_event_get_header(var_event
, "page_context");
6095 if ((l
= switch_event_get_header(var_event
, "page_dp"))) {
6100 if ((l
= switch_event_get_header(var_event
, "page_chunk_size"))) {
6101 uint32_t tmp
= switch_atoui(l
);
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");
6114 oexten
= switch_mprintf("playback:%s", path
);
6118 if (switch_file_exists(path
, NULL
) == SWITCH_STATUS_SUCCESS
) {
6119 launch_call_monitor(path
, 0, pdata
, chunk_size
, exten
, context
, dp
);
6121 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "File %s does not exist\n", path
);
6128 switch_safe_free(odata
);
6129 switch_safe_free(oexten
);
6131 return SWITCH_STATUS_SUCCESS
;
6135 * Convert DTMF source to human readable string
6137 static const char *to_dtmf_source_string(switch_dtmf_source_t 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";
6149 struct deduplicate_dtmf_filter
{
6152 switch_dtmf_source_t last_dtmf_source
;
6156 * Filter incoming DTMF and ignore any duplicates
6158 static switch_status_t
deduplicate_recv_dtmf_hook(switch_core_session_t
*session
, const switch_dtmf_t
*dtmf
, switch_dtmf_direction_t direction
)
6160 switch_status_t status
= SWITCH_STATUS_FALSE
;
6162 struct deduplicate_dtmf_filter
*filter
= switch_channel_get_private(switch_core_session_get_channel(session
), "deduplicate_dtmf_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
;
6169 /* remember current state as it might change */
6170 only_rtp
= filter
->only_rtp
;
6172 /* RTP DTMF is preferred over all others- and if it's demonstrated to be available, inband / info detection is disabled */
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");
6178 case SWITCH_DTMF_INBAND_AUDIO
:
6179 switch_channel_set_variable(switch_core_session_get_channel(session
), "deduplicate_dtmf_seen_inband", "true");
6181 case SWITCH_DTMF_RTP
:
6182 switch_channel_set_variable(switch_core_session_get_channel(session
), "deduplicate_dtmf_seen_rtp", "true");
6184 case SWITCH_DTMF_UNKNOWN
:
6185 case SWITCH_DTMF_APP
:
6187 status
= SWITCH_STATUS_SUCCESS
;
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");
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;
6201 /* stop inband detector */
6202 switch_ivr_broadcast(switch_core_session_get_uuid(session
), "spandsp_stop_dtmf::", SMF_ECHO_ALEG
);
6204 case SWITCH_DTMF_ENDPOINT
:
6205 switch_channel_set_variable(switch_core_session_get_channel(session
), "deduplicate_dtmf_seen_endpoint", "true");
6207 case SWITCH_DTMF_UNKNOWN
:
6208 case SWITCH_DTMF_APP
:
6210 status
= SWITCH_STATUS_SUCCESS
;
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
;
6218 filter
->last_dtmf
= dtmf
->digit
;
6219 filter
->last_dtmf_source
= dtmf
->source
;
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
);
6229 SWITCH_STANDARD_APP(deduplicate_dtmf_app_function
)
6231 struct deduplicate_dtmf_filter
*filter
= switch_channel_get_private(switch_core_session_get_channel(session
), "deduplicate_dtmf_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
);
6241 SWITCH_STANDARD_APP(vad_test_function
)
6243 switch_channel_t
*channel
= switch_core_session_get_channel(session
);
6244 switch_codec_implementation_t imp
= { 0 };
6246 switch_frame_t
*frame
= { 0 };
6247 switch_vad_state_t vad_state
;
6249 const char *var
= NULL
;
6255 if (mode
> 3) mode
= 3;
6258 switch_core_session_raw_read(session
);
6259 switch_core_session_get_read_impl(session
, &imp
);
6261 vad
= switch_vad_init(imp
.samples_per_second
, imp
.number_of_channels
);
6264 if ((var
= switch_channel_get_variable(channel
, "vad_debug"))) {
6267 if (tmp
< 0) tmp
= 0;
6268 if (tmp
> 1) tmp
= 1;
6270 switch_vad_set_param(vad
, "debug", tmp
);
6273 switch_vad_set_mode(vad
, mode
);
6275 if ((var
= switch_channel_get_variable(channel
, "vad_silence_ms"))) {
6278 if (tmp
> 0) switch_vad_set_param(vad
, "silence_ms", tmp
);
6281 if ((var
= switch_channel_get_variable(channel
, "vad_thresh"))) {
6284 if (tmp
> 0) switch_vad_set_param(vad
, "thresh", tmp
);
6287 if ((var
= switch_channel_get_variable(channel
, "vad_voice_ms"))) {
6290 if (tmp
> 0) switch_vad_set_param(vad
, "voice_ms", tmp
);
6293 while (switch_channel_ready(channel
)) {
6294 switch_status_t status
= switch_core_session_read_frame(session
, &frame
, SWITCH_IO_FLAG_NONE
, 0);
6296 if (!SWITCH_READ_ACCEPTABLE(status
)) {
6300 if (switch_test_flag(frame
, SFF_CNG
)) {
6304 vad_state
= switch_vad_process(vad
, frame
->data
, frame
->datalen
/ 2);
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);
6313 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "vad_state: %s\n", switch_vad_state2str(vad_state));
6317 switch_vad_destroy(&vad
);
6318 switch_core_session_reset(session
, SWITCH_TRUE
, SWITCH_TRUE
);
6321 #define DEBUG_MEDIA_SYNTAX "<read|write|both|vread|vwrite|vboth|all> <on|off>"
6322 SWITCH_STANDARD_APP(debug_media_function
)
6324 char *mycmd
= NULL
, *argv
[2] = { 0 };
6326 switch_status_t status
= SWITCH_STATUS_FALSE
;
6328 if (!zstr(data
) && (mycmd
= strdup(data
))) {
6329 argc
= switch_separate_string(mycmd
, ' ', argv
, (sizeof(argv
) / sizeof(argv
[0])));
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
);
6336 switch_core_session_message_t msg
= { 0 };
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__
;
6343 if (!strcasecmp(argv
[0], "all")) {
6344 msg
.string_array_arg
[0] = "both";
6348 status
= switch_core_session_receive_message(session
, &msg
);
6350 if (status
== SWITCH_STATUS_SUCCESS
&& !strcasecmp(argv
[0], "all") && !strcmp(msg
.string_array_arg
[0], "both")) {
6351 msg
.string_array_arg
[0] = "vboth";
6356 if (status
== SWITCH_STATUS_SUCCESS
) {
6357 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "media debug on\n");
6359 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session
), SWITCH_LOG_DEBUG
, "error to turn on media debug status=%d\n", status
);
6364 switch_safe_free(mycmd
);
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"
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"
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."
6387 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_dptools_shutdown
)
6390 switch_event_free_subclass(FILE_STRING_CLOSE
);
6391 switch_event_free_subclass(FILE_STRING_FAIL
);
6392 switch_event_free_subclass(FILE_STRING_OPEN
);
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
);
6400 return SWITCH_STATUS_SUCCESS
;
6403 SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load
)
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;
6412 if (switch_true(switch_core_get_variable("disable_system_app_commands"))) {
6413 use_system_commands
= 0;
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
;
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
;
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
;
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
);
6437 /* connect my internal structure to the blank pointer passed to me */
6438 *module_interface
= switch_loadable_module_create_module_interface(pool
, modname
);
6440 switch_event_bind(modname
, SWITCH_EVENT_PRESENCE_PROBE
, SWITCH_EVENT_SUBCLASS_ANY
, pickup_pres_event_handler
, NULL
);
6443 file_string_supported_formats
[0] = "file_string";
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
;
6456 file_url_supported_formats
[0] = "file";
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
;
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
;
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
;
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
;
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
;
6485 SWITCH_ADD_CHAT(chat_interface
, "event", event_chat_send
);
6486 SWITCH_ADD_CHAT(chat_interface
, "api", api_chat_send
);
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
);
6496 SWITCH_ADD_APP(app_interface
, "blind_transfer_ack", "", "", blind_transfer_ack_function
, "[true|false]", SAF_NONE
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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]",
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
);
6621 SWITCH_ADD_APP(app_interface
, "filter_codecs", "Filter Codecs", "Filter Codecs", filter_codecs_function
, FILTER_CODECS_SYNTAX
, SAF_SUPPORT_NOMEDIA
);
6623 SWITCH_ADD_APP(app_interface
, "enable_keepalive", "Enable Keepalive", "Enable Keepalive",
6624 keepalive_function
, KEEPALIVE_SYNTAX
, SAF_SUPPORT_NOMEDIA
);
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
,
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
,
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
, "",
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
);
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
);
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>",
6685 SWITCH_ADD_APP(app_interface
, "displace_session", "Displace File", DISPLACE_DESC
, displace_session_function
, "<path> [<flags>] [+time_limit_ms]",
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
, "",
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
);
6698 SWITCH_ADD_APP(app_interface
, "say", "say", "say", say_function
, SAY_SYNTAX
, SAF_NONE
);
6700 SWITCH_ADD_APP(app_interface
, "detect_audio", "detect_audio", "detect_audio", detect_audio_function
, DETECT_AUDIO_SYNTAX
,
6702 SWITCH_ADD_APP(app_interface
, "detect_silence", "detect_silence", "detect_silence", detect_silence_function
, DETECT_SILENCE_SYNTAX
,
6704 SWITCH_ADD_APP(app_interface
, "wait_for_silence", "wait_for_silence", "wait_for_silence", wait_for_silence_function
, WAIT_FOR_SILENCE_SYNTAX
,
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
);
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
);
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
);
6719 SWITCH_ADD_DIALPLAN(dp_interface
, "inline", inline_dialplan_hunt
);
6721 /* indicate that the module should continue to be loaded */
6722 return SWITCH_STATUS_SUCCESS
;
6728 * indent-tabs-mode:t
6733 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: