diff --git a/Makefile.am b/Makefile.am index 84a01260ce..3a99b52824 100644 --- a/Makefile.am +++ b/Makefile.am @@ -34,7 +34,6 @@ DEFAULT_SOUNDS=en-us-callie-8000 fi; \ fi - sounds: sounds-en-us-callie-8000 sounds-install: sounds-en-us-callie-8000-install sounds-ru: sounds-ru-RU-elena-8000 @@ -72,6 +71,35 @@ cd-moh-install: uhd-moh-install sounds-music-48000-install all-recursive: libfreeswitch.la clean-recusive: clean_core install-recursive: install-libLTLIBRARIES install-binPROGRAMS +$(RECURSIVE_TARGETS): freeswitch + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; \ + if test -z "$$fail" ; then \ + cd $(top_builddir)/build && $(MAKE) $(AM_MAKEFLAGS) $$target || exit 1; \ + else \ + exit 1; \ + fi ; CORE_CFLAGS = `$(switch_builddir)/libs/apr/apr-1-config --cflags --cppflags --includes` CORE_CFLAGS += `$(switch_builddir)/libs/apr-util/apu-1-config --includes` @@ -86,7 +114,7 @@ CORE_CFLAGS += -I$(switch_srcdir)/libs/spandsp/src -I$(switch_srcdir)/libs/tiff- CORE_LIBS = libs/apr-util/libaprutil-1.la libs/apr/libapr-1.la CORE_LIBS += libs/sqlite/libsqlite3.la libs/pcre/libpcre.la libs/speex/libspeex/libspeexdsp.la -CORE_LIBS += libs/sofia-sip/libsofia-sip-ua/sdp/libsdp.la libs/sofia-sip/libsofia-sip-ua/su/libsu.la +CORE_LIBS += libs/sofia-sip/libsofia-sip-ua/sdp/.libs/libsdp.a libs/sofia-sip/libsofia-sip-ua/su/.libs/libsu.a if ENABLE_SRTP CORE_CFLAGS += -DENABLE_SRTP @@ -420,7 +448,7 @@ libs/libzrtp/projects/gnu/build/libzrtp.a: libs/sofia-sip/Makefile: cd libs/sofia-sip && sh ./configure.gnu --prefix=$(prefix) -libs/sofia-sip/libsofia-sip-ua/sdp/libsdp.la libs/sofia-sip/libsofia-sip-ua/su/libsu.la: libs/sofia-sip/.update libs/sofia-sip/Makefile +libs/sofia-sip/libsofia-sip-ua/sdp/.libs/libsdp.a libs/sofia-sip/libsofia-sip-ua/su/.libs/libsu.a: libs/sofia-sip/.update libs/sofia-sip/Makefile @cd libs/sofia-sip && $(MAKE) noop @cd libs/sofia-sip && $(MAKE) SOFIA_CFLAGS="$(SWITCH_AM_CFLAGS)" @$(TOUCH_TARGET) diff --git a/conf/vanilla/autoload_configs/voicemail_ivr.conf.xml b/conf/vanilla/autoload_configs/voicemail_ivr.conf.xml index 529509a495..1cdf3c222e 100644 --- a/conf/vanilla/autoload_configs/voicemail_ivr.conf.xml +++ b/conf/vanilla/autoload_configs/voicemail_ivr.conf.xml @@ -26,6 +26,7 @@ + @@ -57,11 +58,14 @@ + + + - - - - + + + + @@ -89,9 +93,8 @@ - - - + + @@ -105,7 +108,7 @@ - + @@ -117,7 +120,7 @@ - + @@ -132,7 +135,7 @@ - + @@ -146,7 +149,7 @@ - + diff --git a/conf/vanilla/lang/en/vm/voicemail_ivr.xml b/conf/vanilla/lang/en/vm/voicemail_ivr.xml index 590026a29d..1c48299430 100644 --- a/conf/vanilla/lang/en/vm/voicemail_ivr.xml +++ b/conf/vanilla/lang/en/vm/voicemail_ivr.xml @@ -11,8 +11,8 @@ - - + + @@ -89,7 +89,7 @@ - + @@ -97,7 +97,7 @@ - + @@ -105,16 +105,24 @@ - + - - + + + + + + + + + + @@ -264,6 +272,7 @@ + diff --git a/docs/phrase/phrase_en.xml b/docs/phrase/phrase_en.xml index f9add503b7..ed4c0d6a75 100644 --- a/docs/phrase/phrase_en.xml +++ b/docs/phrase/phrase_en.xml @@ -22,6 +22,17 @@ + + + + + + + + + + + @@ -589,20 +600,32 @@ - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + @@ -635,6 +658,16 @@ + + + + + + + + + + diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index 7bdf1e3dd0..e4e8dc7c6f 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -214,8 +214,6 @@ typedef enum { struct switch_runtime { switch_time_t initiated; - switch_time_t mono_initiated; - switch_time_t mono_reference; switch_time_t reference; int64_t offset; switch_event_t *global_vars; diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 68e592b9df..575e4601ae 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -756,7 +756,7 @@ SWITCH_DECLARE(void) switch_core_session_set_dmachine(switch_core_session_t *ses SWITCH_DECLARE(switch_ivr_dmachine_t *) switch_core_session_get_dmachine(switch_core_session_t *session, switch_digit_action_target_t target); SWITCH_DECLARE(switch_digit_action_target_t) switch_ivr_dmachine_get_target(switch_ivr_dmachine_t *dmachine); SWITCH_DECLARE(void) switch_ivr_dmachine_set_target(switch_ivr_dmachine_t *dmachine, switch_digit_action_target_t target); - +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_set_terminators(switch_ivr_dmachine_t *dmachine, const char *terminators); SWITCH_DECLARE(switch_status_t) switch_core_session_set_codec_slin(switch_core_session_t *session, switch_slin_data_t *data); /*! diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index e45f7215bc..d90fb29d6a 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -336,6 +336,7 @@ static void bind_to_session(switch_core_session_t *session, struct action_binding *act; switch_ivr_dmachine_t *dmachine; switch_channel_t *channel = switch_core_session_get_channel(session); + const char *terminators = NULL; if (!(dmachine = switch_core_session_get_dmachine(session, target))) { uint32_t digit_timeout = 1500; @@ -363,6 +364,10 @@ static void bind_to_session(switch_core_session_t *session, act->target = bind_target; act->session = session; switch_ivr_dmachine_bind(dmachine, act->realm, act->input, 0, digit_action_callback, act); + + if ((terminators = switch_channel_get_variable(channel, "bda_terminators"))) { + switch_ivr_dmachine_set_terminators(dmachine, terminators); + } } #define BIND_DIGIT_ACTION_USAGE ",,[,][,][,]" diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index cef4d78be8..75c7006a7d 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -2252,7 +2252,7 @@ static void fifo_caller_add(fifo_node_t *node, switch_core_session_t *session) switch_str_nil(switch_channel_get_variable(channel, "caller_id_number")), switch_epoch_time_now(NULL)); - fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE); + fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE); } static void fifo_caller_del(const char *uuid) @@ -2265,7 +2265,7 @@ static void fifo_caller_del(const char *uuid) sql = switch_mprintf("delete from fifo_callers"); } - fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE); + fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE); } @@ -4303,7 +4303,7 @@ static void fifo_member_add(char *fifo_name, char *originate_string, int simo_co sql = switch_mprintf("delete from fifo_outbound where fifo_name='%q' and uuid = '%q'", fifo_name, digest); switch_assert(sql); - fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE); + fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE); switch_mutex_lock(globals.mutex); @@ -4325,7 +4325,7 @@ static void fifo_member_add(char *fifo_name, char *originate_string, int simo_co digest, fifo_name, originate_string, simo_count, 0, timeout, lag, 0, (long) expires, globals.hostname, taking_calls, (long)switch_epoch_time_now(NULL)); switch_assert(sql); - fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE); + fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE); free(name_dup); cbt.buf = outbound_count; @@ -4360,7 +4360,7 @@ static void fifo_member_del(char *fifo_name, char *originate_string) sql = switch_mprintf("delete from fifo_outbound where fifo_name='%q' and uuid = '%q' and hostname='%q'", fifo_name, digest, globals.hostname); switch_assert(sql); - fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE); + fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE); switch_mutex_lock(globals.mutex); if (!(node = switch_core_hash_find(globals.fifo_hash, fifo_name))) { diff --git a/src/mod/applications/mod_fsv/mod_fsv.c b/src/mod/applications/mod_fsv/mod_fsv.c index 01160f6f7f..8a7e27c09c 100644 --- a/src/mod/applications/mod_fsv/mod_fsv.c +++ b/src/mod/applications/mod_fsv/mod_fsv.c @@ -403,6 +403,15 @@ SWITCH_STANDARD_APP(play_fsv_function) switch_rtp_hdr_t *hdr = vid_frame.packet; bytes &= ~VID_BIT; + /* + * Frame is larger than available buffer space. This error is non-recoverable due to the + * structure of the .fsv format (no frame header signature to re-sync). + */ + if (bytes > ((int) vid_frame.buflen + 12)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Corrupt .fsv video frame header is overflowing read buffer, aborting!\n"); + break; + } + if ((vid_frame.packetlen = read(fd, vid_frame.packet, bytes)) != (uint32_t) bytes) { break; } @@ -425,10 +434,15 @@ SWITCH_STANDARD_APP(play_fsv_function) } last = ts; } else { + /* + * Frame is larger than available buffer space. This error is non-recoverable due to the + * structure of the .fsv format (no frame header signature to re-sync). + */ if (bytes > (int) write_frame.buflen) { - bytes = write_frame.buflen; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Corrupt .fsv audio frame header is overflowing read buffer, aborting!\n"); + break; } - + if ((write_frame.datalen = read(fd, write_frame.data, bytes)) <= 0) { break; } diff --git a/src/mod/applications/mod_httapi/mod_httapi.c b/src/mod/applications/mod_httapi/mod_httapi.c index 34073260de..cc5fea89eb 100644 --- a/src/mod/applications/mod_httapi/mod_httapi.c +++ b/src/mod/applications/mod_httapi/mod_httapi.c @@ -374,6 +374,7 @@ static switch_status_t parse_playback(const char *tag_name, client_t *client, sw const char *action = switch_xml_attr(tag, "action"); const char *digit_timeout_ = switch_xml_attr(tag, "digit-timeout"); const char *input_timeout_ = switch_xml_attr(tag, "input-timeout"); + const char *terminators = switch_xml_attr(tag, "terminators"); const char *tts_engine = NULL; const char *tts_voice = NULL; char *loops_ = (char *) switch_xml_attr(tag, "loops"); @@ -559,6 +560,10 @@ static switch_status_t parse_playback(const char *tag_name, client_t *client, sw } switch_ivr_dmachine_set_realm(dmachine, realm); + if (!zstr(terminators)) { + switch_ivr_dmachine_set_terminators(dmachine, terminators); + } + myargs.dmachine = dmachine; args = &myargs; } @@ -915,6 +920,7 @@ static switch_status_t parse_record(const char *tag_name, client_t *client, swit const char *action = switch_xml_attr(tag, "action"); const char *sub_action = NULL; const char *digit_timeout_ = switch_xml_attr(tag, "digit-timeout"); + const char *terminators = switch_xml_attr(tag, "terminators"); char *loops_ = (char *) switch_xml_attr(tag, "loops"); int loops = 0; switch_status_t status = SWITCH_STATUS_SUCCESS; @@ -1032,6 +1038,10 @@ static switch_status_t parse_record(const char *tag_name, client_t *client, swit } switch_ivr_dmachine_set_realm(dmachine, realm); + if (!zstr(terminators)) { + switch_ivr_dmachine_set_terminators(dmachine, terminators); + } + myargs.dmachine = dmachine; args = &myargs; } diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 195ac3170f..fd1d5856bc 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -3107,6 +3107,7 @@ static switch_status_t voicemail_inject(const char *data, switch_core_session_t switch_xml_t ux; if (switch_xml_locate_user_in_domain(uname, x_domain, &ux, NULL) == SWITCH_STATUS_SUCCESS) { + switch_xml_merge_user(ux, x_domain, group); switch_event_create(&my_params, SWITCH_EVENT_REQUEST_PARAMS); status = deliver_vm(profile, ux, domain, path, 0, read_flags, my_params, pool, cid_name, cid_num, forwarded_by, @@ -3116,6 +3117,7 @@ static switch_status_t voicemail_inject(const char *data, switch_core_session_t continue; } + switch_xml_merge_user(ut, x_domain, group); switch_event_create(&my_params, SWITCH_EVENT_REQUEST_PARAMS); status = deliver_vm(profile, ut, domain, path, 0, read_flags, my_params, pool, cid_name, cid_num, forwarded_by, SWITCH_TRUE, @@ -3139,6 +3141,7 @@ static switch_status_t voicemail_inject(const char *data, switch_core_session_t continue; } + switch_xml_merge_user(ut, x_domain, group); switch_event_create(&my_params, SWITCH_EVENT_REQUEST_PARAMS); status = deliver_vm(profile, ut, domain, path, 0, read_flags, my_params, pool, cid_name, cid_num, forwarded_by, SWITCH_TRUE, @@ -3153,6 +3156,7 @@ static switch_status_t voicemail_inject(const char *data, switch_core_session_t switch_xml_t x_group = NULL; if ((status = switch_xml_locate_user_in_domain(user, x_domain, &ut, &x_group)) == SWITCH_STATUS_SUCCESS) { + switch_xml_merge_user(ut, x_domain, x_group); switch_event_create(&my_params, SWITCH_EVENT_REQUEST_PARAMS); status = deliver_vm(profile, ut, domain, path, 0, read_flags, my_params, pool, cid_name, cid_num, forwarded_by, SWITCH_TRUE, @@ -4975,6 +4979,80 @@ done: return SWITCH_STATUS_SUCCESS; } +#define VM_FSDB_PREF_GREETING_GET_USAGE " [slot]" +SWITCH_STANDARD_API(vm_fsdb_pref_greeting_get_function) +{ + /* int slot = -1; not implemented yet */ + char *sql = NULL; + char res[254] = ""; + + char *id = NULL, *domain = NULL, *profile_name = NULL; + vm_profile_t *profile = NULL; + + char *argv[6] = { 0 }; + char *mycmd = NULL; + + switch_memory_pool_t *pool; + + switch_core_new_memory_pool(&pool); + + if (!zstr(cmd)) { + mycmd = switch_core_strdup(pool, cmd); + switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + } + + if (argv[1]) + profile_name = argv[1]; + if (argv[2]) + domain = argv[2]; + if (argv[3]) + id = argv[3]; +/* if (argv[4]) + slot = atoi(argv[4]); +not implemented yet +*/ + + if (!profile_name || !domain || !id) { + stream->write_function(stream, "-ERR Missing Arguments\n"); + goto done; + } + + if (!(profile = get_profile(profile_name))) { + stream->write_function(stream, "-ERR Profile not found\n"); + goto done; + } + sql = switch_mprintf("select greeting_path from voicemail_prefs WHERE domain = '%q' AND username = '%q'", domain, id); + + vm_execute_sql2str(profile, profile->mutex, sql, res, sizeof(res)); + + switch_safe_free(sql); + + profile_rwunlock(profile); + + /* TODO If no slot requested, returned currently selected and figure out the slot number from the file name. + * IF slot provided, check if file exist, check if it currently selected */ + if (zstr(res)) { + stream->write_function(stream, "-ERR No greeting found\n"); + } else { + switch_event_t *my_params = NULL; + char *ebuf = NULL; + + switch_event_create(&my_params, SWITCH_EVENT_REQUEST_PARAMS); + switch_event_add_header(my_params, SWITCH_STACK_BOTTOM, "VM-Preference-Greeting-File-Path", "%s", res); + switch_event_add_header(my_params, SWITCH_STACK_BOTTOM, "VM-Preference-Greeting-Slot", "%s", "Not Implemented yet"); + switch_event_add_header(my_params, SWITCH_STACK_BOTTOM, "VM-Preference-Greeting-Selected", "%s", "True"); + switch_event_serialize_json(my_params, &ebuf); + switch_event_destroy(&my_params); + + stream->write_function(stream, "%s", ebuf); + switch_safe_free(ebuf); + + } +done: + switch_core_destroy_memory_pool(&pool); + return SWITCH_STATUS_SUCCESS; +} + #define VM_FSDB_PREF_RECNAME_SET_USAGE " " SWITCH_STANDARD_API(vm_fsdb_pref_recname_set_function) { @@ -5961,6 +6039,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_voicemail_load) /* Preferences */ SWITCH_ADD_API(commands_api_interface, "vm_fsdb_pref_greeting_set", "vm_fsdb_pref_greeting_set", vm_fsdb_pref_greeting_set_function, VM_FSDB_PREF_GREETING_SET_USAGE); + SWITCH_ADD_API(commands_api_interface, "vm_fsdb_pref_greeting_get", "vm_fsdb_pref_greeting_get", vm_fsdb_pref_greeting_get_function, VM_FSDB_PREF_GREETING_GET_USAGE); SWITCH_ADD_API(commands_api_interface, "vm_fsdb_pref_recname_set", "vm_fsdb_pref_recname_set", vm_fsdb_pref_recname_set_function, VM_FSDB_PREF_RECNAME_SET_USAGE); SWITCH_ADD_API(commands_api_interface, "vm_fsdb_pref_password_set", "vm_fsdb_pref_password_set", vm_fsdb_pref_password_set_function, VM_FSDB_PREF_PASSWORD_SET_USAGE); diff --git a/src/mod/applications/mod_voicemail_ivr/conf/autoload_configs/voicemail_ivr.conf.xml b/src/mod/applications/mod_voicemail_ivr/conf/autoload_configs/voicemail_ivr.conf.xml index 529509a495..502578ee64 100644 --- a/src/mod/applications/mod_voicemail_ivr/conf/autoload_configs/voicemail_ivr.conf.xml +++ b/src/mod/applications/mod_voicemail_ivr/conf/autoload_configs/voicemail_ivr.conf.xml @@ -58,10 +58,10 @@ - - - - + + + + diff --git a/src/mod/applications/mod_voicemail_ivr/config.c b/src/mod/applications/mod_voicemail_ivr/config.c index 1066a5c6ce..3561c9edc5 100644 --- a/src/mod/applications/mod_voicemail_ivr/config.c +++ b/src/mod/applications/mod_voicemail_ivr/config.c @@ -86,7 +86,7 @@ void menu_init(vmivr_profile_t *profile, vmivr_menu_t *menu) { if ((x_phrases = switch_xml_child(x_menu, "phrases"))) { switch_event_import_xml(switch_xml_child(x_phrases, "phrase"), "name", "value", &menu->event_phrases); } - if ((x_settings = switch_xml_child(x_profile, "settings"))) { + if ((x_settings = switch_xml_child(x_menu, "settings"))) { switch_event_import_xml(switch_xml_child(x_settings, "param"), "name", "value", &menu->event_settings); } @@ -114,6 +114,7 @@ void menu_instance_init(vmivr_menu_t *menu) { void menu_instance_free(vmivr_menu_t *menu) { if (menu->phrase_params) { switch_event_destroy(&menu->phrase_params); + menu->phrase_params = NULL; } memset(&menu->ivre_d, 0, sizeof(menu->ivre_d)); } @@ -244,6 +245,8 @@ vmivr_profile_t *get_profile(switch_core_session_t *session, const char *profile profile->api_msg_forward = switch_core_session_strdup(session, val); else if (!strcasecmp(var, "pref_greeting_set") && !profile->api_pref_greeting_set) profile->api_pref_greeting_set = switch_core_session_strdup(session, val); + else if (!strcasecmp(var, "pref_greeting_get") && !profile->api_pref_greeting_get) + profile->api_pref_greeting_get = switch_core_session_strdup(session, val); else if (!strcasecmp(var, "pref_recname_set") && !profile->api_pref_recname_set) profile->api_pref_recname_set = switch_core_session_strdup(session, val); else if (!strcasecmp(var, "pref_password_set") && !profile->api_pref_password_set) @@ -255,7 +258,7 @@ vmivr_profile_t *get_profile(switch_core_session_t *session, const char *profile total_options++; } } - if (total_options - total_invalid_options != 12) { + if (total_options - total_invalid_options != 13) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing api definition for profile '%s'\n", profile_name); profile = NULL; } diff --git a/src/mod/applications/mod_voicemail_ivr/config.h b/src/mod/applications/mod_voicemail_ivr/config.h index 9d3b63d584..fbd5803b3b 100644 --- a/src/mod/applications/mod_voicemail_ivr/config.h +++ b/src/mod/applications/mod_voicemail_ivr/config.h @@ -70,6 +70,7 @@ struct vmivr_profile { const char *api_msg_get; const char *api_msg_forward; const char *api_pref_greeting_set; + const char *api_pref_greeting_get; const char *api_pref_recname_set; const char *api_pref_password_set; diff --git a/src/mod/applications/mod_voicemail_ivr/menu.c b/src/mod/applications/mod_voicemail_ivr/menu.c index 4442b23e53..f307899b95 100644 --- a/src/mod/applications/mod_voicemail_ivr/menu.c +++ b/src/mod/applications/mod_voicemail_ivr/menu.c @@ -73,6 +73,7 @@ void vmivr_menu_main(switch_core_session_t *session, vmivr_profile_t *profile) { switch_channel_t *channel = switch_core_session_get_channel(session); vmivr_menu_t menu = { "std_main_menu" }; int retry; + switch_bool_t action_on_new_message_occured = SWITCH_FALSE; /* Initialize Menu Configs */ menu_init(profile, &menu); @@ -84,6 +85,8 @@ void vmivr_menu_main(switch_core_session_t *session, vmivr_profile_t *profile) { for (retry = menu.ivr_maximum_attempts; switch_channel_ready(channel) && retry > 0; retry--) { char *cmd = NULL; + const char *action = NULL; + const char *action_on_new_message = switch_event_get_header(menu.event_settings, "Action-On-New-Message"); menu_instance_init(&menu); @@ -93,17 +96,26 @@ void vmivr_menu_main(switch_core_session_t *session, vmivr_profile_t *profile) { cmd = switch_core_session_sprintf(session, "json %s %s %s %s", profile->api_profile, profile->domain, profile->id, profile->folder_name); jsonapi2event(session, menu.phrase_params, profile->api_msg_count, cmd); - //initial_count_played = SWITCH_TRUE; + ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "msg_count"), NULL, menu.phrase_params, NULL, 0); - ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, menu.phrase_params, NULL, menu.ivr_entry_timeout); + if (atoi(switch_event_get_header(menu.phrase_params, "VM-Total-New-Messages")) > 0 && menu.ivre_d.result == RES_WAITFORMORE && !action_on_new_message_occured && action_on_new_message) { + menu.ivre_d.result = RES_FOUND; + action = action_on_new_message; + action_on_new_message_occured = SWITCH_TRUE; + + } else { + ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, menu.phrase_params, NULL, menu.ivr_entry_timeout); + } if (menu.ivre_d.result == RES_TIMEOUT) { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "timeout"), NULL, NULL, NULL, 0); } else if (menu.ivre_d.result == RES_INVALID) { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "invalid"), NULL, NULL, NULL, 0); } else if (menu.ivre_d.result == RES_FOUND) { /* Matching DTMF Key Pressed */ - const char *action = switch_event_get_header(menu.event_keys_dtmf, menu.ivre_d.dtmf_stored); + if (!action) { + action = switch_event_get_header(menu.event_keys_dtmf, menu.ivre_d.dtmf_stored); + } /* Reset the try count */ retry = menu.ivr_maximum_attempts; @@ -577,7 +589,19 @@ void vmivr_menu_select_greeting_slot(switch_core_session_t *session, vmivr_profi char * cmd = switch_core_session_sprintf(session, "%s %s %s %d", profile->api_profile, profile->domain, profile->id, gnum); if (vmivr_api_execute(session, profile->api_pref_greeting_set, cmd) == SWITCH_STATUS_SUCCESS) { char *str_num = switch_core_session_sprintf(session, "%d", gnum); - ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "selected_slot"), str_num, NULL, NULL, 0); + char *cmd = switch_core_session_sprintf(session, "json %s %s %s %d %s", profile->api_profile, profile->domain, profile->id); + switch_event_t *phrases = jsonapi2event(session, NULL, profile->api_pref_greeting_get, cmd); + + ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "selected_slot"), str_num, phrases, NULL, 0); + + if (switch_true(switch_event_get_header(phrases, "VM-Message-Private-Local-Copy"))) { + const char *file_path = switch_event_get_header(phrases, "VM-Preference-Greeting-File-Path"); + if (file_path && unlink(file_path) != 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to delete temp file [%s]\n", file_path); + } + } + + switch_event_destroy(&phrases); } else { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "invalid_slot"), NULL, NULL, NULL, 0); } diff --git a/src/mod/endpoints/mod_skypopen/mod_skypopen.c b/src/mod/endpoints/mod_skypopen/mod_skypopen.c index 455e18b1cd..167357f47d 100644 --- a/src/mod/endpoints/mod_skypopen/mod_skypopen.c +++ b/src/mod/endpoints/mod_skypopen/mod_skypopen.c @@ -450,6 +450,8 @@ static switch_status_t channel_on_init(switch_core_session_t *session) channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); + memset(tech_pvt->skype_voicemail_id, '\0', sizeof(tech_pvt->skype_voicemail_id)); + memset(tech_pvt->skype_voicemail_id_greeting, '\0', sizeof(tech_pvt->skype_voicemail_id_greeting)); switch_channel_set_variable(channel, "skype_user", tech_pvt->skype_user); switch_mutex_lock(tech_pvt->flag_mutex); switch_set_flag(tech_pvt, TFLAG_IO); @@ -621,10 +623,26 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) if (strlen(tech_pvt->skype_call_id)) { DEBUGA_SKYPE("hanging up skype call: %s\n", SKYPOPEN_P_LOG, tech_pvt->skype_call_id); - sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", tech_pvt->skype_call_id); - skypopen_signaling_write(tech_pvt, msg_to_skype); + if(strlen(tech_pvt->skype_voicemail_id_greeting)){ + sprintf(msg_to_skype, "ALTER VOICEMAIL %s STOPPLAYBACK", tech_pvt->skype_voicemail_id_greeting); + skypopen_signaling_write(tech_pvt, msg_to_skype); + switch_sleep(MS_SKYPOPEN * 1000 * 100);//XXX FIXME 2000 millisecs, 2 seconds, so it will record at least 1 second + } + + if(strlen(tech_pvt->skype_voicemail_id_greeting)){ + sprintf(msg_to_skype, "ALTER VOICEMAIL %s DELETE", tech_pvt->skype_voicemail_id_greeting); + skypopen_signaling_write(tech_pvt, msg_to_skype); + switch_sleep(MS_SKYPOPEN * 1000 * 10);//XXX FIXME 200 millisecs + } + if(strlen(tech_pvt->skype_voicemail_id)){ + sprintf(msg_to_skype, "ALTER VOICEMAIL %s STOPRECORDING", tech_pvt->skype_voicemail_id); + skypopen_signaling_write(tech_pvt, msg_to_skype); + switch_sleep(MS_SKYPOPEN * 1000 * 10);//XXX FIXME 200 millisecs + } sprintf(msg_to_skype, "ALTER CALL %s HANGUP", tech_pvt->skype_call_id); skypopen_signaling_write(tech_pvt, msg_to_skype); + sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", tech_pvt->skype_call_id); + skypopen_signaling_write(tech_pvt, msg_to_skype); } DEBUGA_SKYPE("%s CHANNEL HANGUP\n", SKYPOPEN_P_LOG, tech_pvt->name); switch_mutex_lock(globals.mutex); @@ -882,7 +900,10 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch //DEBUGA_SKYPE("skypopen_audio_read going back to read\n", SKYPOPEN_P_LOG); goto read; } - DEBUGA_SKYPE("READ BUFFER EMPTY, skypopen_audio_read Silence\n", SKYPOPEN_P_LOG); + + if (!strlen(tech_pvt->skype_voicemail_id)) { + DEBUGA_SKYPE("READ BUFFER EMPTY, skypopen_audio_read Silence\n", SKYPOPEN_P_LOG); + } memset(tech_pvt->read_frame.data, 255, BYTES_PER_FRAME); tech_pvt->read_frame.datalen = BYTES_PER_FRAME; @@ -1030,7 +1051,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc } switch_buffer_write(tech_pvt->write_buffer, frame->data, frame->datalen); switch_mutex_unlock(tech_pvt->mutex_audio_cli); - if (no_space) { + if (no_space && !strlen(tech_pvt->skype_voicemail_id)) { //switch_sleep(MS_SKYPOPEN * 1000); DEBUGA_SKYPE("NO SPACE in WRITE BUFFER: there was no space for %d\n", SKYPOPEN_P_LOG, frame->datalen); } @@ -1797,7 +1818,7 @@ static switch_status_t load_config(int reload_type) ("Interface_id=%d is now STARTED, the Skype client to which we are connected gave us the correct CURRENTUSERHANDLE (%s)\n", SKYPOPEN_P_LOG, interface_id, globals.SKYPOPEN_INTERFACES[interface_id].skype_user); - skypopen_signaling_write(&globals.SKYPOPEN_INTERFACES[interface_id], "PROTOCOL 7"); + skypopen_signaling_write(&globals.SKYPOPEN_INTERFACES[interface_id], "PROTOCOL 999"); switch_sleep(20000); skypopen_signaling_write(&globals.SKYPOPEN_INTERFACES[interface_id], "SET AUTOAWAY OFF"); switch_sleep(20000); diff --git a/src/mod/endpoints/mod_skypopen/skypopen.h b/src/mod/endpoints/mod_skypopen/skypopen.h index d5f01f85e6..69cda02b9a 100644 --- a/src/mod/endpoints/mod_skypopen/skypopen.h +++ b/src/mod/endpoints/mod_skypopen/skypopen.h @@ -357,6 +357,8 @@ struct private_object { char ring_value[256]; char message[4096]; + char skype_voicemail_id[512]; + char skype_voicemail_id_greeting[512]; }; typedef struct private_object private_t; diff --git a/src/mod/endpoints/mod_skypopen/skypopen_protocol.c b/src/mod/endpoints/mod_skypopen/skypopen_protocol.c index 84d4cb81ef..320c95483b 100644 --- a/src/mod/endpoints/mod_skypopen/skypopen_protocol.c +++ b/src/mod/endpoints/mod_skypopen/skypopen_protocol.c @@ -219,7 +219,7 @@ int skypopen_signaling_read(private_t *tech_pvt) ("If I don't connect immediately, please give the Skype client authorization to be connected by Skypopen (and to not ask you again)\n", SKYPOPEN_P_LOG); skypopen_sleep(1000000); - skypopen_signaling_write(tech_pvt, "PROTOCOL 7"); + skypopen_signaling_write(tech_pvt, "PROTOCOL 999"); skypopen_sleep(20000); return 0; } @@ -245,6 +245,10 @@ int skypopen_signaling_read(private_t *tech_pvt) } else if (!strncasecmp(message, "ERROR 99 CALL", 12)) { DEBUGA_SKYPE("Skype got ERROR: |||%s|||, another call is active on this interface\n\n\n", SKYPOPEN_P_LOG, message); tech_pvt->interface_state = SKYPOPEN_STATE_ERROR_DOUBLE_CALL; + } else if (!strncasecmp(message, "ERROR 531 VOICEMAIL", 18)) { + NOTICA("Skype got ERROR about VOICEMAIL, no problem: |||%s|||\n", SKYPOPEN_P_LOG, message); + } else if (!strncasecmp(message, "ERROR 529 VOICEMAIL", 18)) { + NOTICA("Skype got ERROR about VOICEMAIL, no problem: |||%s|||\n", SKYPOPEN_P_LOG, message); } else if (!strncasecmp(message, "ERROR 592 ALTER CALL", 19)) { NOTICA("Skype got ERROR about TRANSFERRING, no problem: |||%s|||\n", SKYPOPEN_P_LOG, message); } else if (!strncasecmp(message, "ERROR 559 CALL", 13) | !strncasecmp(message, "ERROR 556 CALL", 13)) { @@ -539,6 +543,43 @@ int skypopen_signaling_read(private_t *tech_pvt) } + if (!strcasecmp(message, "VOICEMAIL")) { + char msg_to_skype[1024]; + + skypopen_strncpy(obj, where, sizeof(obj) - 1); + where = strsep(stringp, " "); + skypopen_strncpy(id, where, sizeof(id) - 1); + where = strsep(stringp, " "); + skypopen_strncpy(prop, where, sizeof(prop) - 1); + where = strsep(stringp, " "); + skypopen_strncpy(value, where, sizeof(value) - 1); + where = strsep(stringp, " "); + + //DEBUGA_SKYPE + //("Skype MSG: message: %s, obj: %s, id: %s, prop: %s, value: %s,where: %s!\n", + //SKYPOPEN_P_LOG, message, obj, id, prop, value, where ? where : "NULL"); + + if (!strcasecmp(prop, "STATUS") && !strcasecmp(value, "RECORDING") ) { + DEBUGA_SKYPE("VOICEMAIL %s INPUT\n", SKYPOPEN_P_LOG, id); + sprintf(msg_to_skype, "ALTER VOICEMAIL %s SET_INPUT PORT=\"%d\"", id, tech_pvt->tcp_cli_port); + skypopen_signaling_write(tech_pvt, msg_to_skype); + } else if (!strcasecmp(prop, "STATUS") && !strcasecmp(value, "PLAYING") ) { + DEBUGA_SKYPE("VOICEMAIL %s OUTPUT\n", SKYPOPEN_P_LOG, id); + sprintf(msg_to_skype, "ALTER VOICEMAIL %s SET_OUTPUT PORT=\"%d\"", id, tech_pvt->tcp_srv_port); + skypopen_signaling_write(tech_pvt, msg_to_skype); + sprintf(tech_pvt->skype_voicemail_id_greeting, "%s", id); + + } else if (!strcasecmp(prop, "TYPE") && !strcasecmp(value, "OUTGOING") ) { + DEBUGA_SKYPE("VOICEMAIL OUTGOING id is %s\n", SKYPOPEN_P_LOG, id); + sprintf(tech_pvt->skype_voicemail_id, "%s", id); + } else if (!strcasecmp(prop, "STATUS") && !strcasecmp(value, "PLAYED") ) { + //switch_ivr_broadcast( tech_pvt->session_uuid_str, "gentones::%(500,0,800)",SMF_ECHO_ALEG|SMF_ECHO_BLEG); + switch_ivr_broadcast( tech_pvt->session_uuid_str, "gentones::%(500,0,800)",SMF_ECHO_BLEG); + memset(tech_pvt->skype_voicemail_id_greeting, '\0', sizeof(tech_pvt->skype_voicemail_id_greeting)); + + } + } + if (!strcasecmp(message, "CALL")) { skypopen_strncpy(obj, where, sizeof(obj) - 1); where = strsep(stringp, " "); @@ -665,12 +706,6 @@ int skypopen_signaling_read(private_t *tech_pvt) return CALLFLOW_INCOMING_HANGUP; } } - //skypopen_sleep(1000); - sprintf(msg_to_skype, "ALTER CALL %s SET_INPUT PORT=\"%d\"", id, tech_pvt->tcp_cli_port); - skypopen_signaling_write(tech_pvt, msg_to_skype); - //skypopen_sleep(1000); - sprintf(msg_to_skype, "#output ALTER CALL %s SET_OUTPUT PORT=\"%d\"", id, tech_pvt->tcp_srv_port); - skypopen_signaling_write(tech_pvt, msg_to_skype); } tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS; if (skypopen_answered(tech_pvt) != SWITCH_STATUS_SUCCESS) { @@ -986,15 +1021,15 @@ void *skypopen_do_tcp_srv_thread_func(void *obj) || tech_pvt->skype_callflow == CALLFLOW_STATUS_EARLYMEDIA || tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPOPEN_STATE_UP)) { - //unsigned int fdselect; + unsigned int fdselect; int rt = 1; - //fd_set fs; - //struct timeval to; + fd_set fs; + struct timeval to; int nospace; if (!(running && tech_pvt->running)) break; -#if 0 +#if 1 fdselect = fd; FD_ZERO(&fs); FD_SET(fdselect, &fs); @@ -1008,7 +1043,7 @@ void *skypopen_do_tcp_srv_thread_func(void *obj) skypopen_sleep(20000); } - //rt = select(fdselect + 1, &fs, NULL, NULL, &to); + rt = select(fdselect + 1, &fs, NULL, NULL, &to); if (rt > 0) { if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) { @@ -1868,6 +1903,7 @@ void *skypopen_do_skypeapi_thread_func(void *obj) switch_channel_hangup(channel, SWITCH_CAUSE_CRASH); } else { WARNINGA("NO CHANNEL ?\n", SKYPOPEN_P_LOG); + switch_core_session_rwunlock(session); } } @@ -1945,7 +1981,7 @@ void *skypopen_do_skypeapi_thread_func(void *obj) return NULL; } - snprintf(buf, 512, "PROTOCOL 7"); + snprintf(buf, 512, "PROTOCOL 999"); if (!skypopen_send_message(tech_pvt, buf)) { ERRORA("Sending message failed - probably Skype crashed. Please run/restart Skype manually and launch Skypopen again\n", SKYPOPEN_P_LOG); diff --git a/src/mod/languages/mod_lua/freeswitch_lua.cpp b/src/mod/languages/mod_lua/freeswitch_lua.cpp index c8918aee97..f4d5291db9 100644 --- a/src/mod/languages/mod_lua/freeswitch_lua.cpp +++ b/src/mod/languages/mod_lua/freeswitch_lua.cpp @@ -331,61 +331,64 @@ switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t ityp return SWITCH_STATUS_SUCCESS; } + Dbh::Dbh(char *dsn, char *user, char *pass) { - switch_cache_db_connection_options_t options = { {0} }; - const char *prefix = "core:"; - switch_cache_db_handle_type_t type; - m_connected = false; + dbh = NULL; + char *tmp = NULL; + + if (!zstr(user) || !zstr(pass)) { + tmp = switch_mprintf("%s%s%s%s%s", dsn, + zstr(user) ? "" : ":", + zstr(user) ? "" : user, + zstr(pass) ? "" : ":", + zstr(pass) ? "" : pass + ); + + dsn = tmp; + } - if (strstr(dsn, prefix) == dsn) { - options.core_db_options.db_path = &dsn[strlen(prefix)]; - if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_CORE_DB, &options) == SWITCH_STATUS_SUCCESS) { - m_connected = true; - } - } else if (!strncasecmp(dsn, "pgsql://", 8)) { - type = SCDB_TYPE_PGSQL; - options.pgsql_options.dsn = (char *)(dsn + 8); - if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_PGSQL, &options) == SWITCH_STATUS_SUCCESS) { - m_connected = true; - } - } else { - options.odbc_options.dsn = dsn; - options.odbc_options.user = user; - options.odbc_options.pass = pass; - if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) == SWITCH_STATUS_SUCCESS) { - m_connected = true; - } - } + if (switch_cache_db_get_db_handle_dsn(&dbh, dsn) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DBH handle %p Connected.\n", (void *) dbh); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Connection failed. DBH NOT Connected.\n"); + } + + switch_safe_free(tmp); + } Dbh::~Dbh() { - release(); + if (dbh) release(); } bool Dbh::release() { - if (m_connected) { - switch_cache_db_release_db_handle(&dbh); - m_connected = false; - return true; + if (dbh) { + switch_cache_db_release_db_handle(&dbh); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DBH handle %p released.\n", (void *) dbh); + return true; } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DBH NOT Connected.\n"); return false; } bool Dbh::connected() { - return m_connected; + return dbh ? true : false; } bool Dbh::test_reactive(char *test_sql, char *drop_sql, char *reactive_sql) { - if (m_connected) { + if (dbh) { if (switch_cache_db_test_reactive(dbh, test_sql, drop_sql, reactive_sql) == SWITCH_TRUE) { return true; } } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DBH NOT Connected.\n"); return false; } @@ -417,7 +420,7 @@ int Dbh::query_callback(void *pArg, int argc, char **argv, char **cargv) bool Dbh::query(char *sql, SWIGLUA_FN lua_fun) { - if (m_connected) { + if (dbh) { if (lua_fun.L) { if (switch_cache_db_execute_sql_callback(dbh, sql, query_callback, &lua_fun, NULL) == SWITCH_STATUS_SUCCESS) { return true; @@ -428,21 +431,27 @@ bool Dbh::query(char *sql, SWIGLUA_FN lua_fun) } } } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DBH NOT Connected.\n"); return false; } int Dbh::affected_rows() { - if (m_connected) { + if (dbh) { return switch_cache_db_affected_rows(dbh); } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DBH NOT Connected.\n"); return 0; } int Dbh::load_extension(const char *extension) { - if (m_connected) { + if (dbh) { return switch_cache_db_load_extension(dbh, extension); } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DBH NOT Connected.\n"); return 0; } diff --git a/src/switch_core.c b/src/switch_core.c index e7e3c953ad..4f6a99ed9f 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1664,8 +1664,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc switch_rtp_init(runtime.memory_pool); runtime.running = 1; - runtime.initiated = switch_time_now(); - runtime.mono_initiated = switch_mono_micro_time_now(); + runtime.initiated = switch_mono_micro_time_now(); switch_scheduler_add_task(switch_epoch_time_now(NULL), heartbeat_callback, "heartbeat", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL); @@ -2102,7 +2101,7 @@ SWITCH_DECLARE(void) switch_core_measure_time(switch_time_t total_ms, switch_cor SWITCH_DECLARE(switch_time_t) switch_core_uptime(void) { - return switch_mono_micro_time_now() - runtime.mono_initiated; + return switch_mono_micro_time_now() - runtime.initiated; } diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 6f5f76cbb6..80d945f875 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -40,6 +40,7 @@ struct switch_ivr_dmachine_binding { char *digits; int32_t key; + uint8_t rmatch; switch_ivr_dmachine_callback_t callback; switch_byte_t is_regex; void *user_data; @@ -50,6 +51,8 @@ typedef struct switch_ivr_dmachine_binding switch_ivr_dmachine_binding_t; typedef struct { switch_ivr_dmachine_binding_t *binding_list; switch_ivr_dmachine_binding_t *tail; + char *name; + char *terminators; } dm_binding_head_t; struct switch_ivr_dmachine { @@ -186,6 +189,21 @@ SWITCH_DECLARE(void) switch_ivr_dmachine_destroy(switch_ivr_dmachine_t **dmachin } } +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_set_terminators(switch_ivr_dmachine_t *dmachine, const char *terminators) +{ + if (!dmachine->realm) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No realm selected.\n"); + return SWITCH_STATUS_FALSE; + } + + + dmachine->realm->terminators = switch_core_strdup(dmachine->pool, terminators); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Digit parser %s: Setting terminators for realm '%s' to '%s'\n", + dmachine->name, dmachine->realm->name, terminators); + + return SWITCH_STATUS_SUCCESS; +} + SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_set_realm(switch_ivr_dmachine_t *dmachine, const char *realm) { dm_binding_head_t *headp = switch_core_hash_find(dmachine->binding_hash, realm); @@ -197,7 +215,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_set_realm(switch_ivr_dmachin } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Digit parser %s: Error Setting realm to '%s'\n", dmachine->name, realm); - + return SWITCH_STATUS_FALSE; } @@ -247,6 +265,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_bind(switch_ivr_dmachine_t * if (!(headp = switch_core_hash_find(dmachine->binding_hash, realm))) { headp = switch_core_alloc(dmachine->pool, sizeof(*headp)); + headp->name = switch_core_strdup(dmachine->pool, realm); switch_core_hash_insert(dmachine->binding_hash, realm, headp); } @@ -319,13 +338,23 @@ static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachin { dm_match_t best = DM_MATCH_NONE; switch_ivr_dmachine_binding_t *bp, *exact_bp = NULL, *partial_bp = NULL, *both_bp = NULL, *r_bp = NULL; - int pmatches = 0, ematches = 0; + int pmatches = 0, ematches = 0, rmatches = 0; if (!dmachine->cur_digit_len || !dmachine->realm) goto end; for(bp = dmachine->realm->binding_list; bp; bp = bp->next) { if (bp->is_regex) { + switch_status_t r_status = switch_regex_match(dmachine->digits, bp->digits); + + if (r_status == SWITCH_STATUS_SUCCESS) { + bp->rmatch++; + } else { + bp->rmatch = 0; + } + + rmatches++; pmatches++; + } else { if (!strncmp(dmachine->digits, bp->digits, strlen(dmachine->digits))) { pmatches++; @@ -334,11 +363,23 @@ static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachin } } + if (!zstr(dmachine->realm->terminators)) { + char *p = dmachine->realm->terminators; + char *q; + + while(p && *p) { + if ((q=strrchr(dmachine->digits, *p))) { + *q = '\0'; + is_timeout = 1; + break; + } + p++; + } + } + for(bp = dmachine->realm->binding_list; bp; bp = bp->next) { if (bp->is_regex) { - switch_status_t r_status = switch_regex_match(dmachine->digits, bp->digits); - - if (r_status == SWITCH_STATUS_SUCCESS) { + if (bp->rmatch) { if (is_timeout || (bp == dmachine->realm->binding_list && !bp->next)) { best = DM_MATCH_EXACT; exact_bp = bp; @@ -349,7 +390,7 @@ static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachin } else { int pmatch = !strncmp(dmachine->digits, bp->digits, strlen(dmachine->digits)); - if (!exact_bp && pmatch && (pmatches == 1 || ematches == 1 || is_timeout) && !strcmp(bp->digits, dmachine->digits)) { + if (!exact_bp && pmatch && (((pmatches == 1 || ematches == 1) && !rmatches) || is_timeout) && !strcmp(bp->digits, dmachine->digits)) { best = DM_MATCH_EXACT; exact_bp = bp; if (dmachine->cur_digit_len == dmachine->max_digit_len) break; diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index d86daed217..2b50b4cf55 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -194,6 +194,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro_event(switch_core_sessio field_expanded = field_expanded_alloc; } + if (!pattern) { + pattern = ".*"; + } + if (pattern) { switch_regex_t *re = NULL; int proceed = 0, ovector[100]; diff --git a/src/switch_time.c b/src/switch_time.c index 5a33a208c4..6d5bfabd47 100644 --- a/src/switch_time.c +++ b/src/switch_time.c @@ -180,6 +180,7 @@ static void do_sleep(switch_interval_time_t t) clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL); #elif defined(DARWIN) + t -= OFFSET; ts.tv_sec = t / APR_USEC_PER_SEC; ts.tv_nsec = (t % APR_USEC_PER_SEC) * 1000; nanosleep(&ts, NULL); @@ -447,7 +448,7 @@ SWITCH_DECLARE(switch_time_t) switch_time_ref(void) return time_now(0); } else { /* Return monotonic time reference (when available) */ - return time_now(-1); + return switch_mono_micro_time_now(); } } @@ -461,14 +462,12 @@ SWITCH_DECLARE(void) switch_time_sync(void) if (SYSTEM_TIME) { runtime.reference = time_now(0); - runtime.mono_reference = time_now(-1); runtime.offset = 0; } else { - runtime.offset = runtime.reference - time_now(-1); /* Get the offset between system time and the monotonic clock (when available) */ + runtime.offset = runtime.reference - switch_mono_micro_time_now(); /* Get the offset between system time and the monotonic clock (when available) */ runtime.reference = time_now(runtime.offset); } - if (runtime.reference - last_time > 1000000 || last_time == 0) { if (SYSTEM_TIME) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Clock is already configured to always report system time.\n"); @@ -901,6 +900,8 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) while (((ts = time_now(runtime.offset)) + 100) < runtime.reference) { if (ts < last) { if (MONO) { + runtime.initiated = switch_mono_micro_time_now() - ((last - runtime.offset) - runtime.initiated); + if (time_sync == runtime.time_sync) { /* Only resync if not in the middle of switch_time_sync() already */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Virtual Migration Detected! Syncing Clock\n"); win32_init_timers(); /* Make sure to reinit timers on WIN32 */ @@ -918,8 +919,13 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) } if (!MONO || time_sync == runtime.time_sync) { +#if defined(HAVE_CLOCK_NANOSLEEP) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "If you see this message many times try setting the param enable-clock-nanosleep to true in switch.conf.xml or consider a nicer machine to run me on. I AM *FREE* afterall.\n"); +#else + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, + "If you see this message many times consider a nicer machine to run me on. I AM *FREE* afterall.\n"); +#endif } } else { rev_errs = 0; @@ -955,6 +961,8 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) if (ts > (runtime.reference + too_late)) { if (MONO) { + runtime.initiated = switch_mono_micro_time_now() - (((runtime.reference - runtime.microseconds_per_tick) - runtime.offset) - runtime.initiated); + if (time_sync == runtime.time_sync) { /* Only resync if not in the middle of switch_time_sync() already */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Virtual Migration Detected! Syncing Clock\n"); win32_init_timers(); /* Make sure to reinit timers on WIN32 */ @@ -962,7 +970,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) time_sync = runtime.time_sync; } } else { - switch_time_t diff = ts - runtime.reference - runtime.microseconds_per_tick; + switch_time_t diff = ts - (runtime.reference - runtime.microseconds_per_tick); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Forward Clock Skew Detected!\n"); fwd_errs++; runtime.reference = switch_time_now(); @@ -1296,7 +1304,7 @@ SWITCH_MODULE_LOAD_FUNCTION(softtimer_load) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Enabled Windows monotonic clock, using timeGetTime()\n"); } - runtime.mono_initiated = switch_mono_micro_time_now(); /* Update mono_initiated, since now is the first time the real clock is enabled */ + runtime.initiated = switch_mono_micro_time_now(); /* Update mono_initiated, since now is the first time the real clock is enabled */ } /* No need to calibrate clock in Win32, we will only sleep ms anyway, it's just not accurate enough */