diff --git a/conf/lang/en/ivr/sounds.xml b/conf/lang/en/ivr/sounds.xml index 58db0a6c15..e436e294a3 100644 --- a/conf/lang/en/ivr/sounds.xml +++ b/conf/lang/en/ivr/sounds.xml @@ -8,4 +8,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/configure.gnu b/libs/sofia-sip/configure.gnu index e9cd89ac7c..4b64a47b7b 100644 --- a/libs/sofia-sip/configure.gnu +++ b/libs/sofia-sip/configure.gnu @@ -1,4 +1,4 @@ #! /bin/sh srcpath=$(dirname $0 2>/dev/null ) || srcpath="." -$srcpath/configure "$@" --with-pic --with-glib=no --disable-shared --without-doxygen +$srcpath/configure "$@" --with-pic --with-glib=no --disable-shared --without-doxygen --disable-stun diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index 176b841147..8fa0439b47 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -625,7 +625,7 @@ SWITCH_DECLARE(void) switch_channel_mark_hold(switch_channel_t *channel, switch_ /** @} */ SWITCH_DECLARE(switch_status_t) switch_channel_execute_on(switch_channel_t *channel, const char *variable_prefix); - +SWITCH_DECLARE(switch_status_t) switch_channel_api_on(switch_channel_t *channel, const char *variable_prefix); SWITCH_END_EXTERN_C #endif diff --git a/src/include/switch_types.h b/src/include/switch_types.h index f6183e6018..dd36b7f680 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -131,12 +131,21 @@ SWITCH_BEGIN_EXTERN_C #define SWITCH_COPY_XML_CDR_VARIABLE "copy_xml_cdr" #define SWITCH_CURRENT_APPLICATION_VARIABLE "current_application" #define SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE "proto_specific_hangup_cause" + #define SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE "execute_on_answer" #define SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE "execute_on_pre_answer" #define SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE "execute_on_media" -#define SWITCH_CHANNEL_API_ON_ANSWER_VARIABLE "api_on_answer" #define SWITCH_CHANNEL_EXECUTE_ON_RING_VARIABLE "execute_on_ring" #define SWITCH_CHANNEL_EXECUTE_ON_TONE_DETECT_VARIABLE "execute_on_tone_detect" +#define SWITCH_CHANNEL_EXECUTE_ON_ORIGINATE_VARIABLE "execute_on_originate" + +#define SWITCH_CHANNEL_API_ON_ANSWER_VARIABLE "api_on_answer" +#define SWITCH_CHANNEL_API_ON_PRE_ANSWER_VARIABLE "api_on_pre_answer" +#define SWITCH_CHANNEL_API_ON_MEDIA_VARIABLE "api_on_media" +#define SWITCH_CHANNEL_API_ON_RING_VARIABLE "api_on_ring" +#define SWITCH_CHANNEL_API_ON_TONE_DETECT_VARIABLE "api_on_tone_detect" +#define SWITCH_CHANNEL_API_ON_ORIGINATE_VARIABLE "api_on_originate" + #define SWITCH_CALL_TIMEOUT_VARIABLE "call_timeout" #define SWITCH_HOLDING_UUID_VARIABLE "holding_uuid" #define SWITCH_SOFT_HOLDING_UUID_VARIABLE "soft_holding_uuid" diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c index 2a5a2aa2d1..aa95b1e28c 100644 --- a/src/mod/applications/mod_callcenter/mod_callcenter.c +++ b/src/mod/applications/mod_callcenter/mod_callcenter.c @@ -850,7 +850,7 @@ cc_status_t cc_agent_get(const char *key, const char *agent, char *ret_result, s switch_event_t *event; char res[256]; - /* Check to see if agent already exist */ + /* Check to see if agent already exists */ sql = switch_mprintf("SELECT count(*) FROM agents WHERE name = '%q'", agent); cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res)); switch_safe_free(sql); @@ -860,8 +860,8 @@ cc_status_t cc_agent_get(const char *key, const char *agent, char *ret_result, s goto done; } - if (!strcasecmp(key, "status") ) { - /* Check to see if agent already exist */ + if (!strcasecmp(key, "status") || !strcasecmp(key, "state") || !strcasecmp(key, "uuid") ) { + /* Check to see if agent already exists */ sql = switch_mprintf("SELECT %q FROM agents WHERE name = '%q'", key, agent); cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res)); switch_safe_free(sql); @@ -869,9 +869,15 @@ cc_status_t cc_agent_get(const char *key, const char *agent, char *ret_result, s result = CC_STATUS_SUCCESS; if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { + char tmpname[256]; + if (!strcasecmp(key, "uuid")) { + switch_snprintf(tmpname, sizeof(tmpname), "CC-Agent-UUID"); + } else { + switch_snprintf(tmpname, sizeof(tmpname), "CC-Agent-%c%s", (char) switch_toupper(key[0]), key+1); + } switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", agent); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-status-get"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Status", res); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-%s-get", key); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, tmpname, res); switch_event_fire(&event); } @@ -1400,6 +1406,10 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa /* Proceed contact the agent to offer the member */ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { + switch_channel_t *member_channel = switch_core_session_get_channel(member_session); + switch_caller_profile_t *member_profile = switch_channel_get_caller_profile(member_channel); + const char *member_dnis = member_profile->rdnis; + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-offering"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name); @@ -1409,6 +1419,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-Session-UUID", h->member_session_uuid); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Name", h->member_cid_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Number", h->member_cid_number); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-DNIS", member_dnis); switch_event_fire(&event); } @@ -1548,6 +1559,9 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa t_agent_answered = local_epoch_time_now(NULL); if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { + switch_caller_profile_t *member_profile = switch_channel_get_caller_profile(member_channel); + const char *member_dnis = member_profile->rdnis; + switch_channel_event_set_data(agent_channel, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "bridge-agent-start"); @@ -1561,6 +1575,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-Session-UUID", h->member_session_uuid); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Name", h->member_cid_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Number", h->member_cid_number); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-DNIS", member_dnis); switch_event_fire(&event); } /* for xml_cdr needs */ @@ -2676,7 +2691,9 @@ static int list_result_callback(void *pArg, int argc, char **argv, char **column "\tcallcenter_config agent set busy_delay_time [agent_name] [wait second] | \n"\ "\tcallcenter_config agent set no_answer_delay_time [agent_name] [wait second] | \n"\ "\tcallcenter_config agent get status [agent_name] | \n" \ -"\tcallcenter_config agent list | \n" \ +"\tcallcenter_config agent get state [agent_name] | \n" \ +"\tcallcenter_config agent get uuid [agent_name] | \n" \ +"\tcallcenter_config agent list [[agent_name]] | \n" \ "\tcallcenter_config tier add [queue_name] [agent_name] [level] [position] | \n" \ "\tcallcenter_config tier set state [queue_name] [agent_name] [state] | \n" \ "\tcallcenter_config tier set level [queue_name] [agent_name] [level] | \n" \ @@ -2832,7 +2849,14 @@ SWITCH_STANDARD_API(cc_config_api_function) struct list_result cbt; cbt.row_process = 0; cbt.stream = stream; - sql = switch_mprintf("SELECT * FROM agents"); + if ( argc-initial_argc > 1 ) { + stream->write_function(stream, "%s", "-ERR Invalid!\n"); + goto done; + } else if ( argc-initial_argc == 1 ) { + sql = switch_mprintf("SELECT * FROM agents WHERE name='%q'", argv[0 + initial_argc]); + } else { + sql = switch_mprintf("SELECT * FROM agents"); + } cc_execute_sql_callback(NULL /* queue */, NULL /* mutex */, sql, list_result_callback, &cbt /* Call back variables */); switch_safe_free(sql); stream->write_function(stream, "%s", "+OK\n"); diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 39e6380399..8c260ddf7f 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -3669,7 +3669,9 @@ static switch_status_t file_string_file_close(switch_file_handle_t *handle) { file_string_context_t *context = handle->private_info; - switch_core_file_close(&context->fh); + if (switch_test_flag((&context->fh), SWITCH_FILE_OPEN)) { + switch_core_file_close(&context->fh); + } return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/applications/mod_protovm/Makefile b/src/mod/applications/mod_protovm/Makefile deleted file mode 100644 index 92f8441104..0000000000 --- a/src/mod/applications/mod_protovm/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -BASE=../../../.. -LOCAL_OBJS=ivr.o util.o config.o menu.o -include $(BASE)/build/modmake.rules diff --git a/src/mod/applications/mod_protovm/config.c b/src/mod/applications/mod_protovm/config.c deleted file mode 100644 index 6a2573b83a..0000000000 --- a/src/mod/applications/mod_protovm/config.c +++ /dev/null @@ -1,135 +0,0 @@ -/* Copy paste from FS mod_voicemail */ -#include - -#include "config.h" - -const char *global_cf = "protovm.conf"; - -void populate_profile_menu_event(vmivr_profile_t *profile, vmivr_menu_profile_t *menu) { - switch_xml_t cfg, xml, x_profiles, x_profile, x_keys, x_phrases, x_menus, x_menu; - - free_profile_menu_event(menu); - - if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf); - goto end; - } - if (!(x_profiles = switch_xml_child(cfg, "profiles"))) { - goto end; - } - - if ((x_profile = switch_xml_find_child(x_profiles, "profile", "name", profile->name))) { - if ((x_menus = switch_xml_child(x_profile, "menus"))) { - if ((x_menu = switch_xml_find_child(x_menus, "menu", "name", menu->name))) { - if ((x_keys = switch_xml_child(x_menu, "keys"))) { - switch_event_import_xml(switch_xml_child(x_keys, "key"), "dtmf", "action", &menu->event_keys_dtmf); - switch_event_import_xml(switch_xml_child(x_keys, "key"), "action", "dtmf", &menu->event_keys_action); - switch_event_import_xml(switch_xml_child(x_keys, "key"), "action", "variable", &menu->event_keys_varname); - } - if ((x_phrases = switch_xml_child(x_menu, "phrases"))) { - switch_event_import_xml(switch_xml_child(x_phrases, "phrase"), "name", "value", &menu->event_phrases); - } - } - } - } -end: - if (xml) - switch_xml_free(xml); - return; - -} - -void free_profile_menu_event(vmivr_menu_profile_t *menu) { - if (menu->event_keys_dtmf) { - switch_event_destroy(&menu->event_keys_dtmf); - } - if (menu->event_keys_action) { - switch_event_destroy(&menu->event_keys_action); - } - if (menu->event_keys_varname) { - switch_event_destroy(&menu->event_keys_varname); - } - - if (menu->event_phrases) { - switch_event_destroy(&menu->event_phrases); - } -} - -vmivr_profile_t *get_profile(switch_core_session_t *session, const char *profile_name) -{ - vmivr_profile_t *profile = NULL; - switch_xml_t cfg, xml, x_profiles, x_profile, x_apis, param; - - if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf); - return profile; - } - if (!(x_profiles = switch_xml_child(cfg, "profiles"))) { - goto end; - } - - if ((x_profile = switch_xml_find_child(x_profiles, "profile", "name", profile_name))) { - if (!(profile = switch_core_session_alloc(session, sizeof(vmivr_profile_t)))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Alloc Failure\n"); - goto end; - } - - profile->name = profile_name; - - profile->current_msg = 0; - profile->current_msg_uuid = NULL; - - /* TODO Make the following configurable */ - profile->api_profile = profile->name; - profile->menu_check_auth = "std_authenticate"; - profile->menu_check_main = "std_navigator"; - profile->menu_check_terminate = "std_purge"; - - if ((x_apis = switch_xml_child(x_profile, "apis"))) { - int total_options = 0; - int total_invalid_options = 0; - for (param = switch_xml_child(x_apis, "api"); param; param = param->next) { - char *var, *val; - if ((var = (char *) switch_xml_attr_soft(param, "name")) && (val = (char *) switch_xml_attr_soft(param, "value"))) { - if (!strcasecmp(var, "msg_undelete") && !profile->api_msg_undelete) - profile->api_msg_undelete = switch_core_session_strdup(session, val); - else if (!strcasecmp(var, "msg_delete") && !profile->api_msg_delete) - profile->api_msg_delete = switch_core_session_strdup(session, val); - else if (!strcasecmp(var, "msg_list") && !profile->api_msg_list) - profile->api_msg_list = switch_core_session_strdup(session, val); - else if (!strcasecmp(var, "msg_count") && !profile->api_msg_count) - profile->api_msg_count = switch_core_session_strdup(session, val); - else if (!strcasecmp(var, "msg_save") && !profile->api_msg_save) - profile->api_msg_save = switch_core_session_strdup(session, val); - else if (!strcasecmp(var, "msg_purge") && !profile->api_msg_purge) - profile->api_msg_purge = switch_core_session_strdup(session, val); - else if (!strcasecmp(var, "msg_get") && !profile->api_msg_get) - profile->api_msg_get = switch_core_session_strdup(session, val); - else if (!strcasecmp(var, "msg_forward") && !profile->api_msg_forward) - 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_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) - profile->api_pref_password_set = switch_core_session_strdup(session, val); - else if (!strcasecmp(var, "auth_login") && !profile->api_auth_login) - profile->api_auth_login = switch_core_session_strdup(session, val); - else - total_invalid_options++; - total_options++; - } - } - if (total_options - total_invalid_options != 12) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing api definition for profile '%s'\n", profile_name); - profile = NULL; - } - } - - } - -end: - switch_xml_free(xml); - return profile; -} - diff --git a/src/mod/applications/mod_protovm/config.h b/src/mod/applications/mod_protovm/config.h deleted file mode 100644 index 2429f2cb36..0000000000 --- a/src/mod/applications/mod_protovm/config.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _CONFIG_H_ -#define _CONFIG_H_ - -extern const char *global_cf; - -struct vmivr_profile { - const char *name; - - const char *domain; - const char *id; - - int current_msg; - const char *current_msg_uuid; - - const char *menu_check_auth; - const char *menu_check_main; - const char *menu_check_terminate; - - switch_bool_t authorized; - - const char *api_profile; - const char *api_auth_login; - const char *api_msg_delete; - const char *api_msg_undelete; - const char *api_msg_list; - const char *api_msg_count; - const char *api_msg_save; - const char *api_msg_purge; - const char *api_msg_get; - const char *api_msg_forward; - const char *api_pref_greeting_set; - const char *api_pref_recname_set; - const char *api_pref_password_set; - -}; -typedef struct vmivr_profile vmivr_profile_t; - -struct vmivr_menu_profile { - const char *name; - - switch_event_t *event_keys_action; - switch_event_t *event_keys_dtmf; - switch_event_t *event_keys_varname; - switch_event_t *event_phrases; -}; -typedef struct vmivr_menu_profile vmivr_menu_profile_t; - -vmivr_profile_t *get_profile(switch_core_session_t *session, const char *profile_name); - -void free_profile_menu_event(vmivr_menu_profile_t *menu); -void populate_profile_menu_event(vmivr_profile_t *profile, vmivr_menu_profile_t *menu); - -#endif /* _CONFIG_H_ */ diff --git a/src/mod/applications/mod_protovm/ivr.c b/src/mod/applications/mod_protovm/ivr.c deleted file mode 100644 index a48132b1a2..0000000000 --- a/src/mod/applications/mod_protovm/ivr.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2011, Anthony Minessale II - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * - * The Initial Developer of the Original Code is - * Anthony Minessale II - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Marc Olivier Chouinard - * - * - * ivr.c -- MT IVR System Interface - * - */ - -#include - -#include "ivr.h" - -int match_dtmf(switch_core_session_t *session, dtmf_ss_t *loc) { - switch_bool_t is_invalid[128] = { SWITCH_FALSE }; - int i; - loc->potentialMatch = NULL; - loc->completeMatch = NULL; - loc->potentialMatchCount = 0; - - for (i = 0; i < loc->dtmf_received; i++) { - int j; - loc->potentialMatchCount = 0; - for (j = 0; !zstr(loc->dtmf_accepted[j]) && j < 128; j++) { - switch_bool_t cMatch = SWITCH_FALSE; - char test[2] = { 0 }; - - if (is_invalid[j]) - continue; - - test[0] = loc->dtmf_stored[i]; - if (loc->dtmf_accepted[j][i] == 'N' && atoi(test) >= 2 && atoi(test) <= 9) - cMatch = SWITCH_TRUE; - if (loc->dtmf_accepted[j][i] == 'X' && atoi(test) >= 0 && atoi(test) <= 9) { - cMatch = SWITCH_TRUE; - } - if (i >= strlen(loc->dtmf_accepted[j]) - 1 && loc->dtmf_accepted[j][strlen(loc->dtmf_accepted[j])-1] == '.') - cMatch = SWITCH_TRUE; - if (loc->dtmf_accepted[j][i] == loc->dtmf_stored[i]) - cMatch = SWITCH_TRUE; - - if (cMatch == SWITCH_FALSE) { - is_invalid[j] = SWITCH_TRUE; - continue; - } - - if (i == strlen(loc->dtmf_accepted[j]) - 1 && loc->dtmf_accepted[j][strlen(loc->dtmf_accepted[j])-1] == '.') { - loc->completeMatch = loc->dtmf_accepted[j]; - } - if (i == loc->dtmf_received - 1 && loc->dtmf_received == strlen(loc->dtmf_accepted[j]) && loc->dtmf_accepted[j][strlen(loc->dtmf_accepted[j])-1] != '.') { - loc->completeMatch = loc->dtmf_accepted[j]; - continue; - } - loc->potentialMatchCount++; - } - } - - return 1; -} - -static switch_status_t cb_on_dtmf_ignore(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen) -{ - switch (itype) { - case SWITCH_INPUT_TYPE_DTMF: - { - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_dtmf_t *dtmf = (switch_dtmf_t *) input; - switch_channel_queue_dtmf(channel, dtmf); - return SWITCH_STATUS_BREAK; - } - default: - break; - } - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t cb_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen) -{ - dtmf_ss_t *loc = (dtmf_ss_t*) buf; - - switch (itype) { - case SWITCH_INPUT_TYPE_DTMF: - { - switch_dtmf_t *dtmf = (switch_dtmf_t *) input; - switch_bool_t audio_was_stopped = loc->audio_stopped; - loc->audio_stopped = SWITCH_TRUE; - - if (loc->dtmf_received >= sizeof(loc->dtmf_stored)) { - loc->result = RES_BUFFER_OVERFLOW; - break; - } - if (!loc->terminate_key || dtmf->digit != loc->terminate_key) - loc->dtmf_stored[loc->dtmf_received++] = dtmf->digit; - - match_dtmf(session, loc); - - if (loc->terminate_key && dtmf->digit == loc->terminate_key && loc->result == RES_WAITFORMORE) { - if (loc->potentialMatchCount == 1 && loc->completeMatch != NULL) { - loc->result = RES_FOUND; - } else { - loc->result = RES_INVALID; - } - return SWITCH_STATUS_BREAK; - } else { - if (loc->potentialMatchCount == 0 && loc->completeMatch != NULL) { - loc->result = RES_FOUND; - return SWITCH_STATUS_BREAK; - } else if (loc->potentialMatchCount > 0) { - loc->result = RES_WAITFORMORE; - if (!audio_was_stopped) - return SWITCH_STATUS_BREAK; - } else { - loc->result = RES_INVALID; - return SWITCH_STATUS_BREAK; - } - } - } - break; - default: - break; - } - - return SWITCH_STATUS_SUCCESS; -} - -switch_status_t captureMenuInitialize(dtmf_ss_t *loc, char **dtmf_accepted) { - int i; - - memset(loc, 0, sizeof(*loc)); - - for (i = 0; dtmf_accepted[i] && i < 16; i++) { - strncpy(loc->dtmf_accepted[i], dtmf_accepted[i], 128); - } - - return SWITCH_STATUS_SUCCESS; -} - -switch_status_t playbackBufferDTMF(switch_core_session_t *session, const char *macro_name, const char *data, switch_event_t *event, const char *lang, int timeout) { - switch_status_t status = SWITCH_STATUS_SUCCESS; - switch_channel_t *channel = switch_core_session_get_channel(session); - - if (switch_channel_ready(channel)) { - switch_input_args_t args = { 0 }; - - args.input_callback = cb_on_dtmf_ignore; - - if (macro_name) { - status = switch_ivr_phrase_macro_event(session, macro_name, data, event, lang, &args); - } - } else { - status = SWITCH_STATUS_BREAK; - } - - return status; -} - - -switch_status_t captureMenu(switch_core_session_t *session, dtmf_ss_t *loc, const char *macro_name, const char *data, switch_event_t *event, const char *lang, int timeout) { - switch_status_t status = SWITCH_STATUS_SUCCESS; - switch_channel_t *channel = switch_core_session_get_channel(session); - - if (switch_channel_ready(channel)) { - switch_input_args_t args = { 0 }; - - args.input_callback = cb_on_dtmf; - args.buf = loc; - - if (macro_name && loc->audio_stopped == SWITCH_FALSE && loc->result == RES_WAITFORMORE) { - status = switch_ivr_phrase_macro_event(session, macro_name, data, event, lang, &args); - } - - if (switch_channel_ready(channel) && (status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK) && timeout && loc->result == RES_WAITFORMORE) { - loc->audio_stopped = SWITCH_TRUE; - switch_ivr_collect_digits_callback(session, &args, timeout, 0); - if (loc->result == RES_WAITFORMORE) { - if (loc->potentialMatchCount == 1 && loc->completeMatch != NULL) { - loc->result = RES_FOUND; - } else { - loc->result = RES_TIMEOUT; - } - } - } - } else { - status = SWITCH_STATUS_BREAK; - } - - return status; -} - -switch_status_t captureMenuRecord(switch_core_session_t *session, dtmf_ss_t *loc, switch_event_t *event, const char *file_path, switch_file_handle_t *fh, int max_record_len) { - switch_status_t status = SWITCH_STATUS_SUCCESS; - switch_channel_t *channel = switch_core_session_get_channel(session); - - if (switch_channel_ready(channel)) { - switch_input_args_t args = { 0 }; - - args.input_callback = cb_on_dtmf; - args.buf = loc; - - if (loc->audio_stopped == SWITCH_FALSE && loc->result == RES_WAITFORMORE) { - loc->recorded_audio = SWITCH_TRUE; - switch_ivr_gentones(session, "%(1000, 0, 640)", 0, NULL); /* TODO Make this optional and configurable */ - status = switch_ivr_record_file(session, fh, file_path, &args, max_record_len); - - } - if (loc->result == RES_WAITFORMORE) { - loc->result = RES_TIMEOUT; - } - - } else { - status = SWITCH_STATUS_BREAK; - } - - return status; -} - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 - */ diff --git a/src/mod/applications/mod_protovm/ivr.h b/src/mod/applications/mod_protovm/ivr.h deleted file mode 100644 index 99136475fd..0000000000 --- a/src/mod/applications/mod_protovm/ivr.h +++ /dev/null @@ -1,30 +0,0 @@ -struct dtmf_ss { - char dtmf_stored[128]; - int dtmf_received; - char dtmf_accepted[16][128]; - int result; - switch_bool_t audio_stopped; - switch_bool_t recorded_audio; - const char *potentialMatch; - int potentialMatchCount; - const char *completeMatch; - char terminate_key; -}; -typedef struct dtmf_ss dtmf_ss_t; - -#define RES_WAITFORMORE 0 -#define RES_FOUND 1 -#define RES_INVALID 3 -#define RES_TIMEOUT 4 -#define RES_BREAK 5 -#define RES_RECORD 6 -#define RES_BUFFER_OVERFLOW 99 - -#define MAX_DTMF_SIZE_OPTION 32 - -switch_status_t captureMenu(switch_core_session_t *session, dtmf_ss_t *loc, const char *macro_name, const char *data, switch_event_t *event, const char *lang, int timeout); -switch_status_t captureMenuRecord(switch_core_session_t *session, dtmf_ss_t *loc, switch_event_t *event, const char *file_path, switch_file_handle_t *fh, int max_record_len); -switch_status_t captureMenuInitialize(dtmf_ss_t *loc, char **dtmf_accepted); - -switch_status_t playbackBufferDTMF(switch_core_session_t *session, const char *macro_name, const char *data, switch_event_t *event, const char *lang, int timeout); - diff --git a/src/mod/applications/mod_protovm/menu.c b/src/mod/applications/mod_protovm/menu.c deleted file mode 100644 index ba4229d43d..0000000000 --- a/src/mod/applications/mod_protovm/menu.c +++ /dev/null @@ -1,743 +0,0 @@ -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2011, Anthony Minessale II - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * - * The Initial Developer of the Original Code is - * Anthony Minessale II - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Marc Olivier Chouinard - * - * - * menu.c -- VoiceMail Menu - * - */ -#include - -#include "ivr.h" -#include "menu.h" -#include "util.h" -#include "config.h" - -/* List of available menu */ -vmivr_menu_function_t menu_list[] = { - {"std_authenticate", mtvm_menu_authenticate}, - {"std_navigator", mtvm_menu_main}, - {"std_record_name", mtvm_menu_record_name}, - {"std_set_password", mtvm_menu_set_password}, - {"std_select_greeting_slot", mtvm_menu_select_greeting_slot}, - {"std_record_greeting_with_slot", mtvm_menu_record_greeting_with_slot}, - {"std_preference", mtvm_menu_preference}, - {"std_purge", mtvm_menu_purge}, - {"std_forward", mtvm_menu_forward}, - { NULL, NULL } -}; - -#define MAX_ATTEMPT 3 /* TODO Make these fields configurable */ -#define DEFAULT_IVR_TIMEOUT 3000 - -void mtvm_menu_purge(switch_core_session_t *session, vmivr_profile_t *profile) { - if (profile->id && profile->authorized) { - if (1==1 /* TODO make Purge email on exit optional ??? */) { - const char *cmd = switch_core_session_sprintf(session, "%s %s %s", profile->api_profile, profile->domain, profile->id); - mt_api_execute(session, profile->api_msg_purge, cmd); - } - } -} -void mtvm_menu_main(switch_core_session_t *session, vmivr_profile_t *profile) { - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_event_t *msg_list_params = NULL; - size_t msg_count = 0; - size_t current_msg = 1; - size_t next_msg = current_msg; - size_t previous_msg = current_msg; - char *cmd = NULL; - int retry; - - /* Different switch to control playback of phrases */ - switch_bool_t initial_count_played = SWITCH_FALSE; - switch_bool_t skip_header = SWITCH_FALSE; - switch_bool_t msg_deleted = SWITCH_FALSE; - switch_bool_t msg_undeleted = SWITCH_FALSE; - switch_bool_t msg_saved = SWITCH_FALSE; - - vmivr_menu_profile_t menu = { "std_navigator" }; - - /* Initialize Menu Configs */ - populate_profile_menu_event(profile, &menu); - - if (!menu.event_keys_dtmf || !menu.event_phrases) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases or Keys\n"); - return; - } - - /* Get VoiceMail List And update msg count */ - cmd = switch_core_session_sprintf(session, "json %s %s %s", profile->api_profile, profile->domain, profile->id); - msg_list_params = jsonapi2event(session, NULL, profile->api_msg_list, cmd); - msg_count = atol(switch_event_get_header(msg_list_params,"VM-List-Count")); - - /* TODO Add Detection of new message and notify the user */ - - for (retry = MAX_ATTEMPT; switch_channel_ready(channel) && retry > 0; retry--) { - switch_core_session_message_t msg = { 0 }; - char cid_buf[1024] = ""; - dtmf_ss_t loc; - char *dtmfa[16] = { 0 }; - switch_event_t *phrase_params = NULL; - - switch_event_create(&phrase_params, SWITCH_EVENT_REQUEST_PARAMS); - - append_event_profile(phrase_params, profile, menu); - - populate_dtmfa_from_event(phrase_params, profile, menu, dtmfa); - - previous_msg = current_msg; - - /* Simple Protection to not go out of msg list scope */ - /* TODO: Add Prompt to notify they reached the begining or the end */ - if (next_msg == 0) { - next_msg = 1; - } else if (next_msg > msg_count) { - next_msg = msg_count; - } - - current_msg = next_msg; - - captureMenuInitialize(&loc, dtmfa); - - /* Prompt related to previous Message here */ - append_event_message(session, profile, phrase_params, msg_list_params, previous_msg); - if (msg_deleted) { - msg_deleted = SWITCH_FALSE; - captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "ack"), "deleted", phrase_params, NULL, 0); - } - if (msg_undeleted) { - msg_undeleted = SWITCH_FALSE; - captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "ack"), "undeleted", phrase_params, NULL, 0); - } - if (msg_saved) { - msg_saved = SWITCH_FALSE; - captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "ack"), "saved", phrase_params, NULL, 0); - } - - /* Prompt related the current message */ - append_event_message(session, profile, phrase_params, msg_list_params, current_msg); - - /* Save in profile the current msg info for other menu processing AND restoration of our current position */ - switch_snprintf(cid_buf, sizeof(cid_buf), "%s|%s", switch_str_nil(switch_event_get_header(phrase_params, "VM-Message-Caller-Number")), switch_str_nil(switch_event_get_header(phrase_params, "VM-Message-Caller-Name"))); - - /* Display MSG CID/Name to caller */ - msg.from = __FILE__; - msg.string_arg = cid_buf; - msg.message_id = SWITCH_MESSAGE_INDICATE_DISPLAY; - switch_core_session_receive_message(session, &msg); - - profile->current_msg = current_msg; - profile->current_msg_uuid = switch_core_session_strdup(session, switch_event_get_header(phrase_params, "VM-Message-UUID")); - - /* TODO check if msg is gone (purged by another session, notify user and auto jump to next message or something) */ - if (!skip_header) { - if (!initial_count_played) { - cmd = switch_core_session_sprintf(session, "json %s %s %s", profile->api_profile, profile->domain, profile->id); - jsonapi2event(session, phrase_params, profile->api_msg_count, cmd); - initial_count_played = SWITCH_TRUE; - captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "msg_count"), NULL, phrase_params, NULL, 0); - } - if (msg_count > 0) { - captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "say_msg_number"), NULL, phrase_params, NULL, 0); - captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "say_date"), NULL, phrase_params, NULL, 0); - } - } - if (msg_count > 0) { - /* TODO Update the Read date of a message (When msg start, or when it listen compleatly ??? To be determined */ - captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "play_message"), NULL, phrase_params, NULL, 0); - } - skip_header = SWITCH_FALSE; - - captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, phrase_params, NULL, DEFAULT_IVR_TIMEOUT); - - if (loc.result == RES_TIMEOUT) { - /* TODO Ask for the prompt Again IF retry != 0 */ - } else if (loc.result == RES_INVALID) { - /* TODO Say invalid option, and ask for the prompt again IF retry != 0 */ - } else if (loc.result == RES_FOUND) { /* Matching DTMF Key Pressed */ - const char *action = switch_event_get_header(menu.event_keys_dtmf, loc.dtmf_stored); - - /* Reset the try count */ - retry = MAX_ATTEMPT; - - if (action) { - if (!strcasecmp(action, "skip_intro")) { /* Skip Header / Play the recording again */ - skip_header = SWITCH_TRUE; - } else if (!strcasecmp(action, "next_msg")) { /* Next Message */ - next_msg++; - } else if (!strcasecmp(action, "prev_msg")) { /* Previous Message */ - next_msg--; - } else if (!strcasecmp(action, "delete_msg")) { /* Delete / Undelete Message */ - const char *msg_flags = switch_event_get_header(phrase_params, "VM-Message-Flags"); - if (!msg_flags || strncasecmp(msg_flags, "delete", 6)) { - cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(phrase_params, "VM-Message-UUID")); - mt_api_execute(session, profile->api_msg_delete, cmd); - - msg_deleted = SWITCH_TRUE; - /* TODO Option for auto going to next message or just return to the menu (So user used to do 76 to delete and next message wont be confused) */ - next_msg++; - } else { - cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(phrase_params, "VM-Message-UUID")); - mt_api_execute(session, profile->api_msg_undelete, cmd); - - msg_undeleted = SWITCH_TRUE; - } - } else if (!strcasecmp(action, "save_msg")) { /* Save Message */ - cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(phrase_params, "VM-Message-UUID")); - mt_api_execute(session, profile->api_msg_save, cmd); - - msg_saved = SWITCH_TRUE; - } else if (!strcasecmp(action, "callback")) { /* CallBack caller */ - const char *cid_num = switch_event_get_header(phrase_params, "VM-Message-Caller-Number"); - if (cid_num) { - /* TODO add detection for private number */ - switch_core_session_execute_exten(session, cid_num, "XML", profile->domain); - } else { - /* TODO Some error msg that the msg doesn't contain a caller number */ - } - } else if (!strncasecmp(action, "menu:", 5)) { /* Sub Menu */ - void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = mtvm_get_menu_function(action+5); - if (fPtr) { - fPtr(session, profile); - } - } else if (!strcasecmp(action, "return")) { /* Return */ - retry = -1; - } - } - } - - /* IF the API to get the message returned us a COPY of the file locally (temp file create from a DB or from a web server), delete it */ - if (switch_true(switch_event_get_header(phrase_params, "VM-Message-Private-Local-Copy"))) { - const char *file_path = switch_event_get_header(phrase_params, "VM-Message-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(&phrase_params); - } - - switch_event_destroy(&msg_list_params); - - free_profile_menu_event(&menu); - - return; -} - -void mtvm_menu_forward(switch_core_session_t *session, vmivr_profile_t *profile) { - - vmivr_menu_profile_t menu = { "std_forward_ask_prepend" }; - switch_channel_t *channel = switch_core_session_get_channel(session); - const char *prepend_filepath = NULL; - int retry; - switch_bool_t forward_msg = SWITCH_FALSE; - - /* Initialize Menu Configs */ - populate_profile_menu_event(profile, &menu); - - if (!menu.event_keys_dtmf || !menu.event_phrases) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases and Keys\n"); - return; - } - - for (retry = MAX_ATTEMPT; switch_channel_ready(channel) && retry > 0; retry--) { - dtmf_ss_t loc; - char *dtmfa[16] = { 0 }; - switch_event_t *phrase_params = NULL; - - switch_event_create(&phrase_params, SWITCH_EVENT_REQUEST_PARAMS); - append_event_profile(phrase_params, profile, menu); - - populate_dtmfa_from_event(phrase_params, profile, menu, dtmfa); - - captureMenuInitialize(&loc, dtmfa); - - captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, phrase_params, NULL, DEFAULT_IVR_TIMEOUT); - - if (loc.result == RES_TIMEOUT) { - /* TODO Ask for the prompt Again IF retry != 0 */ - } else if (loc.result == RES_INVALID) { - /* TODO Say invalid option, and ask for the prompt again IF retry != 0 */ - } else if (loc.result == RES_FOUND) { /* Matching DTMF Key Pressed */ - const char *action = switch_event_get_header(menu.event_keys_dtmf, loc.dtmf_stored); - - /* Reset the try count */ - retry = MAX_ATTEMPT; - - if (action) { - if (!strcasecmp(action, "return")) { /* Return to the previous menu */ - retry = -1; - forward_msg = SWITCH_FALSE; - } else if (!strcasecmp(action, "prepend")) { /* Prepend record msg */ - vmivr_menu_profile_t sub_menu = { "std_record_message" }; - char *tmp_filepath = generate_random_file_name(session, "protovm", "wav" /* TODO make it configurable */); - switch_status_t status; - - /* Initialize Menu Configs */ - populate_profile_menu_event(profile, &sub_menu); - - status = mtvm_menu_record(session, profile, sub_menu, tmp_filepath); - - if (status == SWITCH_STATUS_SUCCESS) { - //char *cmd = switch_core_session_sprintf(session, "%s %s %s %d %s", profile->api_profile, profile->domain, profile->id, gnum, tmp_filepath); - //char *str_num = switch_core_session_sprintf(session, "%d", gnum); - //mt_api_execute(session, profile->api_pref_greeting_set, cmd); - //playbackBufferDTMF(session, switch_event_get_header(menu.event_phrases, "selected_slot"), str_num, NULL, NULL, 0); - prepend_filepath = tmp_filepath; - retry = -1; - forward_msg = SWITCH_TRUE; - } else { - /* TODO Error Recording msg */ - } - free_profile_menu_event(&sub_menu); - - } else if (!strcasecmp(action, "forward")) { /* Forward without prepend msg */ - retry = -1; - forward_msg = SWITCH_TRUE; - } else if (!strncasecmp(action, "menu:", 5)) { /* Sub Menu */ - void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = mtvm_get_menu_function(action+5); - if (fPtr) { - fPtr(session, profile); - } - } - } - } - switch_event_destroy(&phrase_params); - - - } - /* Ask Extension to Forward */ - if (forward_msg) { - for (retry = MAX_ATTEMPT; switch_channel_ready(channel) && retry > 0; retry--) { - const char *id = NULL; - vmivr_menu_profile_t sub_menu = { "std_forward_ask_extension" }; - - /* Initialize Menu Configs */ - populate_profile_menu_event(profile, &sub_menu); - - id = mtvm_menu_get_input_set(session, profile, sub_menu, "X."); - if (id) { - const char *cmd = switch_core_session_sprintf(session, "%s %s %s %s %s %s %s%s%s", profile->api_profile, profile->domain, profile->id, profile->current_msg_uuid, profile->domain, id, prepend_filepath?" ":"", prepend_filepath?prepend_filepath:"" ); - if (mt_api_execute(session, profile->api_msg_forward, cmd) == SWITCH_STATUS_SUCCESS) { - playbackBufferDTMF(session, switch_event_get_header(sub_menu.event_phrases, "ack"), "saved", NULL, NULL, 0); - retry = -1; - } else { - playbackBufferDTMF(session, switch_event_get_header(sub_menu.event_phrases, "invalid_extension"), NULL, NULL, NULL, 0); - } - } else { - /* TODO Prompt about input not valid */ - } - free_profile_menu_event(&sub_menu); - /* TODO add Confirmation of the transfered number */ - } - /* TODO Ask if we want to transfer the msg to more person */ - - } - - free_profile_menu_event(&menu); -} - - -void mtvm_menu_record_name(switch_core_session_t *session, vmivr_profile_t *profile) { - switch_status_t status; - vmivr_menu_profile_t menu = { "std_record_name" }; - - char *tmp_filepath = generate_random_file_name(session, "protovm", "wav" /* TODO make it configurable */); - - /* Initialize Menu Configs */ - populate_profile_menu_event(profile, &menu); - - status = mtvm_menu_record(session, profile, menu, tmp_filepath); - - if (status == SWITCH_STATUS_SUCCESS) { - char *cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, tmp_filepath); - mt_api_execute(session, profile->api_pref_recname_set, cmd); - } -} - -void mtvm_menu_set_password(switch_core_session_t *session, vmivr_profile_t *profile) { - char *password; - vmivr_menu_profile_t menu = { "std_set_password" }; - - /* Initialize Menu Configs */ - populate_profile_menu_event(profile, &menu); - - password = mtvm_menu_get_input_set(session, profile, menu, "XXX." /* TODO Conf Min 3 Digit */); - - /* TODO Add Prompts to tell if password was set and if it was not */ - if (password) { - char *cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, password); - mt_api_execute(session, profile->api_pref_password_set, cmd); - - } - - free_profile_menu_event(&menu); -} - -void mtvm_menu_authenticate(switch_core_session_t *session, vmivr_profile_t *profile) { - switch_channel_t *channel = switch_core_session_get_channel(session); - vmivr_menu_profile_t menu = { "std_authenticate" }; - int retry; - const char *auth_var = NULL; - /* Initialize Menu Configs */ - populate_profile_menu_event(profile, &menu); - - if (profile->id && (auth_var = switch_channel_get_variable(channel, "voicemail_authorized")) && switch_true(auth_var)) { - profile->authorized = SWITCH_TRUE; - } - - for (retry = MAX_ATTEMPT; switch_channel_ready(channel) && retry > 0 && profile->authorized == SWITCH_FALSE; retry--) { - const char *id = profile->id, *password = NULL; - char *cmd = NULL; - - if (!id) { - vmivr_menu_profile_t sub_menu = { "std_authenticate_ask_user" }; - /* Initialize Menu Configs */ - populate_profile_menu_event(profile, &sub_menu); - - id = mtvm_menu_get_input_set(session, profile, sub_menu, "X." /* TODO Conf Min 3 Digit */); - free_profile_menu_event(&sub_menu); - } - if (!password) { - vmivr_menu_profile_t sub_menu = { "std_authenticate_ask_password" }; - /* Initialize Menu Configs */ - populate_profile_menu_event(profile, &sub_menu); - - password = mtvm_menu_get_input_set(session, profile, sub_menu, "X." /* TODO Conf Min 3 Digit */); - free_profile_menu_event(&sub_menu); - } - cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, id, password); - - if (mt_api_execute(session, profile->api_auth_login, cmd) == SWITCH_STATUS_SUCCESS) { - profile->id = id; - profile->authorized = SWITCH_TRUE; - } else { - playbackBufferDTMF(session, switch_event_get_header(menu.event_phrases, "fail_auth"), NULL, NULL, NULL, 0); - } - } - free_profile_menu_event(&menu); -} - -void mtvm_menu_select_greeting_slot(switch_core_session_t *session, vmivr_profile_t *profile) { - vmivr_menu_profile_t menu = { "std_select_greeting_slot" }; - - const char *result; - int gnum = -1; - - /* Initialize Menu Configs */ - populate_profile_menu_event(profile, &menu); - - result = mtvm_menu_get_input_set(session, profile, menu, "X"); - - if (result) - gnum = atoi(result); - if (gnum != -1) { - char * cmd = switch_core_session_sprintf(session, "%s %s %s %d", profile->api_profile, profile->domain, profile->id, gnum); - if (mt_api_execute(session, profile->api_pref_greeting_set, cmd) == SWITCH_STATUS_SUCCESS) { - char *str_num = switch_core_session_sprintf(session, "%d", gnum); - playbackBufferDTMF(session, switch_event_get_header(menu.event_phrases, "selected_slot"), str_num, NULL, NULL, 0); - } else { - playbackBufferDTMF(session, switch_event_get_header(menu.event_phrases, "invalid_slot"), NULL, NULL, NULL, 0); - } - } - free_profile_menu_event(&menu); -} - -void mtvm_menu_record_greeting_with_slot(switch_core_session_t *session, vmivr_profile_t *profile) { - - vmivr_menu_profile_t menu = { "std_record_greeting_with_slot" }; - - const char *result; - int gnum = -1; - - /* Initialize Menu Configs */ - populate_profile_menu_event(profile, &menu); - - result = mtvm_menu_get_input_set(session, profile, menu, "X"); - - if (result) - gnum = atoi(result); - - /* If user entered 0, we don't accept it */ - if (gnum > 0) { - vmivr_menu_profile_t sub_menu = { "std_record_greeting" }; - char *tmp_filepath = generate_random_file_name(session, "protovm", "wav" /* TODO make it configurable */); - switch_status_t status; - - /* Initialize Menu Configs */ - populate_profile_menu_event(profile, &sub_menu); - - status = mtvm_menu_record(session, profile, sub_menu, tmp_filepath); - - if (status == SWITCH_STATUS_SUCCESS) { - char *cmd = switch_core_session_sprintf(session, "%s %s %s %d %s", profile->api_profile, profile->domain, profile->id, gnum, tmp_filepath); - char *str_num = switch_core_session_sprintf(session, "%d", gnum); - mt_api_execute(session, profile->api_pref_greeting_set, cmd); - playbackBufferDTMF(session, switch_event_get_header(menu.event_phrases, "selected_slot"), str_num, NULL, NULL, 0); - } - free_profile_menu_event(&sub_menu); - - } - - free_profile_menu_event(&menu); - -} - -void mtvm_menu_preference(switch_core_session_t *session, vmivr_profile_t *profile) { - switch_channel_t *channel = switch_core_session_get_channel(session); - - int retry; - - vmivr_menu_profile_t menu = { "std_preference" }; - - /* Initialize Menu Configs */ - populate_profile_menu_event(profile, &menu); - - if (!menu.event_keys_dtmf || !menu.event_phrases) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases and Keys\n"); - return; - } - - for (retry = MAX_ATTEMPT; switch_channel_ready(channel) && retry > 0; retry--) { - dtmf_ss_t loc; - char *dtmfa[16] = { 0 }; - switch_event_t *phrase_params = NULL; - - switch_event_create(&phrase_params, SWITCH_EVENT_REQUEST_PARAMS); - append_event_profile(phrase_params, profile, menu); - - populate_dtmfa_from_event(phrase_params, profile, menu, dtmfa); - - captureMenuInitialize(&loc, dtmfa); - - captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, phrase_params, NULL, DEFAULT_IVR_TIMEOUT); - - if (loc.result == RES_TIMEOUT) { - /* TODO Ask for the prompt Again IF retry != 0 */ - } else if (loc.result == RES_INVALID) { - /* TODO Say invalid option, and ask for the prompt again IF retry != 0 */ - } else if (loc.result == RES_FOUND) { /* Matching DTMF Key Pressed */ - const char *action = switch_event_get_header(menu.event_keys_dtmf, loc.dtmf_stored); - - /* Reset the try count */ - retry = MAX_ATTEMPT; - - if (action) { - if (!strcasecmp(action, "return")) { /* Return to the previous menu */ - retry = -1; - } else if (!strncasecmp(action, "menu:", 5)) { /* Sub Menu */ - void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = mtvm_get_menu_function(action+5); - if (fPtr) { - fPtr(session, profile); - } - } - } - } - switch_event_destroy(&phrase_params); - } - - free_profile_menu_event(&menu); -} - -char *mtvm_menu_get_input_set(switch_core_session_t *session, vmivr_profile_t *profile, vmivr_menu_profile_t menu, const char *input_mask) { - char *result = NULL; - int retry; - const char *terminate_key = NULL; - switch_channel_t *channel = switch_core_session_get_channel(session); - - if (!menu.event_keys_dtmf || !menu.event_phrases) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases and Keys : %s\n", menu.name); - return result; - } - - terminate_key = switch_event_get_header(menu.event_keys_action, "ivrengine:terminate_entry"); - - for (retry = MAX_ATTEMPT; switch_channel_ready(channel) && retry > 0; retry--) { - dtmf_ss_t loc; - char *dtmfa[16] = { 0 }; - int i; - switch_event_t *phrase_params = NULL; - - switch_event_create(&phrase_params, SWITCH_EVENT_REQUEST_PARAMS); - append_event_profile(phrase_params, profile, menu); - - populate_dtmfa_from_event(phrase_params, profile, menu, dtmfa); - - /* Find the last entry and append this one to it */ - for (i=0; dtmfa[i] && i < 16; i++){ - } - dtmfa[i] = (char *) input_mask; - - captureMenuInitialize(&loc, dtmfa); - if (terminate_key) { - loc.terminate_key = terminate_key[0]; - } - captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "instructions"), NULL, phrase_params, NULL, DEFAULT_IVR_TIMEOUT); - - if (loc.result == RES_TIMEOUT) { - /* TODO Ask for the prompt Again IF retry != 0 */ - } else if (loc.result == RES_INVALID) { - /* TODO Say invalid option, and ask for the prompt again IF retry != 0 */ - } else if (loc.result == RES_FOUND) { /* Matching DTMF Key Pressed */ - - /* Reset the try count */ - retry = MAX_ATTEMPT; - - if (!strncasecmp(loc.completeMatch, input_mask, 1)) { - result = switch_core_session_strdup(session, loc.dtmf_stored); - retry = -1; - - } - } - switch_event_destroy(&phrase_params); - } - - return result; -} - -switch_status_t mtvm_menu_record(switch_core_session_t *session, vmivr_profile_t *profile, vmivr_menu_profile_t menu, const char *file_name) { - switch_status_t status = SWITCH_STATUS_FALSE; - switch_channel_t *channel = switch_core_session_get_channel(session); - int retry; - - switch_bool_t record_prompt = SWITCH_TRUE; - switch_bool_t listen_recording = SWITCH_FALSE; - switch_bool_t play_instruction = SWITCH_TRUE; - - if (!menu.event_keys_dtmf || !menu.event_phrases) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases and Keys\n"); - return status; - } - - for (retry = MAX_ATTEMPT; switch_channel_ready(channel) && retry > 0; retry--) { - dtmf_ss_t loc; - - char *dtmfa[16] = { 0 }; - switch_event_t *phrase_params = NULL; - switch_file_handle_t fh = { 0 }; - - /* TODO Make the following configurable */ - fh.thresh = 200; - fh.silence_hits = 4; - //fh.samplerate = 8000; - - - switch_event_create(&phrase_params, SWITCH_EVENT_REQUEST_PARAMS); - append_event_profile(phrase_params, profile, menu); - - populate_dtmfa_from_event(phrase_params, profile, menu, dtmfa); - - captureMenuInitialize(&loc, dtmfa); - if (record_prompt) { - if (play_instruction) { - captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "instructions"), NULL, phrase_params, NULL, 0); - } - play_instruction = SWITCH_TRUE; - - captureMenuRecord(session, &loc, phrase_params, file_name, &fh, 30 /* TODO Make max recording configurable */); - } else { - if (listen_recording) { - switch_event_add_header(phrase_params, SWITCH_STACK_BOTTOM, "VM-Record-File-Path", "%s", file_name); - captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "play_recording"), NULL, phrase_params, NULL, 0); - listen_recording = SWITCH_FALSE; - - } - captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, phrase_params, NULL, DEFAULT_IVR_TIMEOUT); - } - - if (loc.recorded_audio) { - /* Reset the try count */ - retry = MAX_ATTEMPT; - - /* TODO Check if message is too short */ - - record_prompt = SWITCH_FALSE; - - } else if (loc.result == RES_TIMEOUT) { - /* TODO Ask for the prompt Again IF retry != 0 */ - } else if (loc.result == RES_INVALID) { - /* TODO Say invalid option, and ask for the prompt again IF retry != 0 */ - } else if (loc.result == RES_FOUND) { /* Matching DTMF Key Pressed */ - const char *action = switch_event_get_header(menu.event_keys_dtmf, loc.dtmf_stored); - - /* Reset the try count */ - retry = MAX_ATTEMPT; - - if (action) { - if (!strcasecmp(action, "listen")) { /* Listen */ - listen_recording = SWITCH_TRUE; - - } else if (!strcasecmp(action, "save")) { - retry = -1; - /* TODO ALLOW SAVE ONLY IF FILE IS RECORDED AND HIGHER THAN MIN SIZE */ - status = SWITCH_STATUS_SUCCESS; - - } else if (!strcasecmp(action, "rerecord")) { - record_prompt = SWITCH_TRUE; - - } else if (!strcasecmp(action, "skip_instruction")) { /* Skip Recording Greeting */ - play_instruction = SWITCH_FALSE; - - } else if (!strncasecmp(action, "menu:", 5)) { /* Sub Menu */ - void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = mtvm_get_menu_function(action+5); - if (fPtr) { - fPtr(session, profile); - } - } else if (!strcasecmp(action, "return")) { /* Return */ - retry = -1; - } - } - } - switch_event_destroy(&phrase_params); - } - return status; -} - - -void (*mtvm_get_menu_function(const char *menu_name))(switch_core_session_t *session, vmivr_profile_t *profile) { - int i = 0; - - if (menu_name) { - for (i=0; menu_list[i].name ; i++) { - if (!strcasecmp(menu_list[i].name, menu_name)) { - return menu_list[i].pt2Func; - } - } - } - return NULL; -} - - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 - */ diff --git a/src/mod/applications/mod_protovm/menu.h b/src/mod/applications/mod_protovm/menu.h deleted file mode 100644 index 82fd993a8f..0000000000 --- a/src/mod/applications/mod_protovm/menu.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _MENU_H_ -#define _MENU_H_ - -#include "config.h" - -void mtvm_menu_purge(switch_core_session_t *session, vmivr_profile_t *profile); -void mtvm_menu_authenticate(switch_core_session_t *session, vmivr_profile_t *profile); -void mtvm_menu_main(switch_core_session_t *session, vmivr_profile_t *profile); -void mtvm_menu_record_name(switch_core_session_t *session, vmivr_profile_t *profile); -void mtvm_menu_set_password(switch_core_session_t *session, vmivr_profile_t *profile); -void mtvm_menu_select_greeting_slot(switch_core_session_t *session, vmivr_profile_t *profile); -void mtvm_menu_record_greeting_with_slot(switch_core_session_t *session, vmivr_profile_t *profile); -void mtvm_menu_preference(switch_core_session_t *session, vmivr_profile_t *profile); -void mtvm_menu_forward(switch_core_session_t *session, vmivr_profile_t *profile); - -switch_status_t mtvm_menu_record(switch_core_session_t *session, vmivr_profile_t *profile, vmivr_menu_profile_t menu, const char *file_name); -char *mtvm_menu_get_input_set(switch_core_session_t *session, vmivr_profile_t *profile, vmivr_menu_profile_t menu, const char *input_mask); - - -struct vmivr_menu_function { - const char *name; - void (*pt2Func)(switch_core_session_t *session, vmivr_profile_t *profile); - -}; -typedef struct vmivr_menu_function vmivr_menu_function_t; - -extern vmivr_menu_function_t menu_list[]; - -void (*mtvm_get_menu_function(const char *menu_name))(switch_core_session_t *session, vmivr_profile_t *profile); - -#endif /* _MENU_H_ */ - diff --git a/src/mod/applications/mod_protovm/mod_protovm.c b/src/mod/applications/mod_protovm/mod_protovm.c deleted file mode 100644 index 7d826e03c2..0000000000 --- a/src/mod/applications/mod_protovm/mod_protovm.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2011, Anthony Minessale II - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * - * The Initial Developer of the Original Code is - * Anthony Minessale II - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Marc Olivier Chouinard - * - * - * mod_protovm.c -- MT VoiceMail System - * - */ -#include - -#include "config.h" -#include "menu.h" - -/* Prototypes */ -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_protovm_shutdown); -SWITCH_MODULE_RUNTIME_FUNCTION(mod_protovm_runtime); -SWITCH_MODULE_LOAD_FUNCTION(mod_protovm_load); - -/* SWITCH_MODULE_DEFINITION(name, load, shutdown, runtime) - * Defines a switch_loadable_module_function_table_t and a static const char[] modname - */ -SWITCH_MODULE_DEFINITION(mod_protovm, mod_protovm_load, mod_protovm_shutdown, NULL); - - -#define MTVM_DESC "protovm" -#define MTVM_USAGE " profile domain [id]" - -SWITCH_STANDARD_APP(protovm_function) -{ - const char *id = NULL; - const char *domain = NULL; - const char *profile_name = NULL; - vmivr_profile_t *profile = NULL; - int argc = 0; - char *argv[6] = { 0 }; - char *mydata = NULL; - - if (!zstr(data)) { - mydata = switch_core_session_strdup(session, data); - argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); - } - - if (argv[1]) - profile_name = argv[1]; - - if (argv[2]) - domain = argv[2]; - - if (!strcasecmp(argv[0], "check")) { - if (argv[3]) - id = argv[3]; - - if (domain && profile_name) { - profile = get_profile(session, profile_name); - - if (profile) { - void (*fPtrAuth)(switch_core_session_t *session, vmivr_profile_t *profile) = mtvm_get_menu_function(profile->menu_check_auth); - void (*fPtrMain)(switch_core_session_t *session, vmivr_profile_t *profile) = mtvm_get_menu_function(profile->menu_check_main); - void (*fPtrTerminate)(switch_core_session_t *session, vmivr_profile_t *profile) = mtvm_get_menu_function(profile->menu_check_terminate); - - profile->domain = domain; - profile->id = id; - - if (fPtrAuth && !profile->authorized) { - fPtrAuth(session, profile); - } - - if (fPtrMain && profile->authorized) { - fPtrMain(session, profile); - } - if (fPtrTerminate) { - fPtrTerminate(session, profile); - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Profile '%s' not found\n", profile_name); - } - } - } - return; -} - -/* Macro expands to: switch_status_t mod_protovm_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */ -SWITCH_MODULE_LOAD_FUNCTION(mod_protovm_load) -{ - switch_application_interface_t *app_interface; - switch_status_t status = SWITCH_STATUS_SUCCESS; - - /* connect my internal structure to the blank pointer passed to me */ - *module_interface = switch_loadable_module_create_module_interface(pool, modname); - - SWITCH_ADD_APP(app_interface, "protovm", "protovm", MTVM_DESC, protovm_function, MTVM_USAGE, SAF_NONE); - - /* indicate that the module should continue to be loaded */ - return status; -} - -/* - Called when the system shuts down - Macro expands to: switch_status_t mod_protovm_shutdown() */ -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_protovm_shutdown) -{ - - return SWITCH_STATUS_SUCCESS; -} - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 - */ diff --git a/src/mod/applications/mod_protovm/protovm.conf.xml b/src/mod/applications/mod_protovm/protovm.conf.xml deleted file mode 100644 index c57e8f72b6..0000000000 --- a/src/mod/applications/mod_protovm/protovm.conf.xml +++ /dev/null @@ -1,176 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/mod/applications/mod_protovm/sounds.xml b/src/mod/applications/mod_protovm/sounds.xml deleted file mode 100644 index 35dcef169a..0000000000 --- a/src/mod/applications/mod_protovm/sounds.xml +++ /dev/null @@ -1,397 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/mod/applications/mod_protovm/util.c b/src/mod/applications/mod_protovm/util.c deleted file mode 100644 index 476e99bd26..0000000000 --- a/src/mod/applications/mod_protovm/util.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2011, Anthony Minessale II - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * - * The Initial Developer of the Original Code is - * Anthony Minessale II - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Marc Olivier Chouinard - * - * - * utils.c -- MT VoiceMail / Different utility that might need to go into the core (after cleanup) - * - */ -#include - -#include "util.h" - -switch_status_t mt_merge_media_files(const char** inputs, const char *output) { - switch_status_t status = SWITCH_STATUS_SUCCESS; - switch_file_handle_t fh_output = { 0 }; - int channels = 1; - int rate = 8000; /* TODO Make this configurable */ - int j = 0; - - if (switch_core_file_open(&fh_output, output, channels, rate, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't open %s\n", output); - goto end; - } - - for (j = 0; inputs[j] != NULL && j < 128 && status == SWITCH_STATUS_SUCCESS; j++) { - switch_file_handle_t fh_input = { 0 }; - char buf[2048]; - switch_size_t len = sizeof(buf) / 2; - - if (switch_core_file_open(&fh_input, inputs[j], channels, rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't open %s\n", inputs[j]); - status = SWITCH_STATUS_GENERR; - break; - } - - while (switch_core_file_read(&fh_input, buf, &len) == SWITCH_STATUS_SUCCESS) { - if (switch_core_file_write(&fh_output, buf, &len) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Write error\n"); - status = SWITCH_STATUS_GENERR; - break; - } - } - - if (fh_input.file_interface) { - switch_core_file_close(&fh_input); - } - } - - if (fh_output.file_interface) { - switch_core_file_close(&fh_output); - } -end: - return status; -} - -switch_event_t *jsonapi2event(switch_core_session_t *session, switch_event_t *apply_event, const char *api, const char *data) { - switch_event_t *phrases_event = NULL; - switch_stream_handle_t stream = { 0 }; - SWITCH_STANDARD_STREAM(stream); - switch_api_execute(api, data, session, &stream); - switch_event_create_json(&phrases_event, (char *) stream.data); - switch_safe_free(stream.data); - - if (apply_event) { - switch_event_header_t *hp; - for (hp = phrases_event->headers; hp; hp = hp->next) { - if (!strncasecmp(hp->name, "VM-", 3)) { - switch_event_add_header(apply_event, SWITCH_STACK_BOTTOM, hp->name, "%s", hp->value); - } - } - switch_event_destroy(&phrases_event); - phrases_event = apply_event; - - } - - return phrases_event; -} - -char *generate_random_file_name(switch_core_session_t *session, const char *mod_name, char *file_extension) { - char rand_uuid[SWITCH_UUID_FORMATTED_LENGTH + 1] = ""; - switch_uuid_t srand_uuid; - - switch_uuid_get(&srand_uuid); - switch_uuid_format(rand_uuid, &srand_uuid); - - return switch_core_session_sprintf(session, "%s%s%s_%s.%s", SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, mod_name, rand_uuid, file_extension); - -} - -switch_status_t mt_api_execute(switch_core_session_t *session, const char *apiname, const char *arguments) { - switch_status_t status = SWITCH_STATUS_SUCCESS; - - switch_stream_handle_t stream = { 0 }; - - SWITCH_STANDARD_STREAM(stream); - switch_api_execute(apiname, arguments, session, &stream); - if (!strncasecmp(stream.data, "-ERR", 4)) { - status = SWITCH_STATUS_GENERR; - } - switch_safe_free(stream.data); - return status; -} - -void append_event_profile(switch_event_t *phrase_params, vmivr_profile_t *profile, vmivr_menu_profile_t menu) { - /* Used for some appending function */ - if (profile->name && profile->id && profile->domain) { - switch_event_add_header(phrase_params, SWITCH_STACK_BOTTOM, "VM-Profile", "%s", profile->name); - switch_event_add_header(phrase_params, SWITCH_STACK_BOTTOM, "VM-Account-ID", "%s", profile->id); - switch_event_add_header(phrase_params, SWITCH_STACK_BOTTOM, "VM-Account-Domain", "%s", profile->domain); - } -} - -void populate_dtmfa_from_event(switch_event_t *phrase_params, vmivr_profile_t *profile, vmivr_menu_profile_t menu, char **dtmfa) { - int i = 0; - if (menu.event_keys_dtmf) { - switch_event_header_t *hp; - - for (hp = menu.event_keys_dtmf->headers; hp; hp = hp->next) { - if (strlen(hp->name) < 3 && hp->value) { /* TODO This is a hack to discard default FS Events ! */ - const char *varphrasename = switch_event_get_header(menu.event_keys_varname, hp->value); - dtmfa[i++] = hp->name; - - if (varphrasename && !zstr(varphrasename)) { - switch_event_add_header(phrase_params, SWITCH_STACK_BOTTOM, varphrasename, "%s", hp->name); - } - } - } - } - -} - -void append_event_message(switch_core_session_t *session, vmivr_profile_t *profile, switch_event_t *phrase_params, switch_event_t *msg_list_event, size_t current_msg) { - - char *varname; - char *apicmd; - - varname = switch_mprintf("VM-List-Message-%" SWITCH_SIZE_T_FMT "-UUID", current_msg); - apicmd = switch_mprintf("json %s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(msg_list_event, varname)); - - switch_safe_free(varname); - - jsonapi2event(session, phrase_params, profile->api_msg_get, apicmd); - - /* TODO Set these 2 header correctly */ - switch_event_add_header(phrase_params, SWITCH_STACK_BOTTOM, "VM-Message-Type", "%s", "new"); - switch_event_add_header(phrase_params, SWITCH_STACK_BOTTOM, "VM-Message-Number", "%"SWITCH_SIZE_T_FMT, current_msg); - - switch_event_add_header_string(phrase_params, SWITCH_STACK_BOTTOM, "VM-Message-Private-Local-Copy", "False"); - - switch_safe_free(apicmd); -} - diff --git a/src/mod/applications/mod_protovm/util.h b/src/mod/applications/mod_protovm/util.h deleted file mode 100644 index 1c46329e18..0000000000 --- a/src/mod/applications/mod_protovm/util.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _UTIL_H_ -#define _UTIL_H_ - -#include "config.h" - -switch_status_t mt_merge_files(const char** inputs, const char *output); - -void append_event_message(switch_core_session_t *session, vmivr_profile_t *profile, switch_event_t *phrase_params, switch_event_t *msg_list_event, size_t current_msg); -void append_event_profile(switch_event_t *phrase_params, vmivr_profile_t *profile, vmivr_menu_profile_t menu); -char *generate_random_file_name(switch_core_session_t *session, const char *mod_name, char *file_extension); -switch_event_t *jsonapi2event(switch_core_session_t *session, switch_event_t *apply_event, const char *api, const char *data); -switch_status_t mt_merge_media_files(const char** inputs, const char *output); -switch_status_t mt_api_execute(switch_core_session_t *session, const char *apiname, const char *arguments); -void populate_dtmfa_from_event(switch_event_t *phrase_params, vmivr_profile_t *profile, vmivr_menu_profile_t menu, char **dtmfa); -#endif /* _UTIL_H_ */ - diff --git a/src/mod/applications/mod_valet_parking/mod_valet_parking.c b/src/mod/applications/mod_valet_parking/mod_valet_parking.c index 3e8337d857..291d6c86a5 100644 --- a/src/mod/applications/mod_valet_parking/mod_valet_parking.c +++ b/src/mod/applications/mod_valet_parking/mod_valet_parking.c @@ -276,17 +276,19 @@ SWITCH_STANDARD_APP(valet_parking_function) if (token->timeout) { const char *var = switch_channel_get_variable(channel, "valet_ticket"); - if (!strcmp(var, token->uuid)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Valet ticket %s accepted.\n", var); - switch_channel_set_variable(channel, "valet_ticket", NULL); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid token %s\n", token->uuid); - switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); - return; + if (!zstr(var)) { + if (!strcmp(var, token->uuid)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Valet ticket %s accepted.\n", var); + switch_channel_set_variable(channel, "valet_ticket", NULL); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid token %s\n", token->uuid); + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + return; + } } } - if (token && (b_session = switch_core_session_locate(token->uuid))) { + if (!zstr(token->uuid) && (b_session = switch_core_session_locate(token->uuid))) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, VALET_EVENT) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Lot-Name", lot_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Extension", ext); diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 2eb89ebc43..6fc16465d7 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -45,6 +45,7 @@ SWITCH_MODULE_DEFINITION(mod_voicemail, mod_voicemail_load, mod_voicemail_shutdo #define VM_EVENT_MAINT "vm::maintenance" #define VM_MAX_GREETINGS 9 +#define VM_EVENT_QUEUE_SIZE 50000 static switch_status_t voicemail_inject(const char *data, switch_core_session_t *session); @@ -53,6 +54,9 @@ static struct { switch_hash_t *profile_hash; int debug; int message_query_exact_match; + int32_t threads; + int32_t running; + switch_queue_t *event_queue; switch_mutex_t *mutex; switch_memory_pool_t *pool; } globals; @@ -1160,6 +1164,8 @@ static switch_status_t create_file(switch_core_session_t *session, vm_profile_t args.buf = input; args.buflen = sizeof(input); + unlink(file_path); + switch_ivr_record_file(session, &fh, file_path, &args, profile->max_record_len); if (switch_file_exists(file_path, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) { @@ -1819,7 +1825,7 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p uint32_t timeout, attempts = 0, retries = 0; int failed = 0; msg_type_t play_msg_type = MSG_NONE; - char *dir_path = NULL, *file_path = NULL; + char *dir_path = NULL, *file_path = NULL, *tmp_file_path = NULL; int total_new_messages = 0; int total_saved_messages = 0; int total_new_urgent_messages = 0; @@ -2099,13 +2105,19 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p } else { switch_event_t *params; file_path = switch_mprintf("%s%sgreeting_%d.%s", dir_path, SWITCH_PATH_SEPARATOR, num, profile->file_ext); + tmp_file_path = switch_mprintf("%s%sgreeting_%d_TMP.%s", dir_path, SWITCH_PATH_SEPARATOR, num, profile->file_ext); + unlink(tmp_file_path); + TRY_CODE(create_file(session, profile, VM_RECORD_GREETING_MACRO, file_path, &message_len, SWITCH_TRUE, NULL, NULL)); + switch_file_rename(tmp_file_path, file_path, switch_core_session_get_pool(session)); + sql = switch_mprintf("update voicemail_prefs set greeting_path='%s' where username='%s' and domain='%s'", file_path, myid, domain_name); vm_execute_sql(profile, sql, profile->mutex); switch_safe_free(sql); switch_safe_free(file_path); + switch_safe_free(tmp_file_path); switch_event_create_subclass(¶ms, SWITCH_EVENT_CUSTOM, VM_EVENT_MAINT); switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Action", "record-greeting"); @@ -2146,10 +2158,14 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p } else if (!strcmp(input, profile->record_name_key)) { switch_event_t *params; file_path = switch_mprintf("%s%srecorded_name.%s", dir_path, SWITCH_PATH_SEPARATOR, profile->file_ext); + tmp_file_path = switch_mprintf("%s%srecorded_name_TMP.%s", dir_path, SWITCH_PATH_SEPARATOR, profile->file_ext); + unlink(tmp_file_path); TRY_CODE(create_file(session, profile, VM_RECORD_NAME_MACRO, file_path, &message_len, SWITCH_FALSE, NULL, NULL)); + switch_file_rename(tmp_file_path, file_path, switch_core_session_get_pool(session)); sql = switch_mprintf("update voicemail_prefs set name_path='%s' where username='%s' and domain='%s'", file_path, myid, domain_name); vm_execute_sql(profile, sql, profile->mutex); switch_safe_free(file_path); + switch_safe_free(tmp_file_path); switch_safe_free(sql); switch_event_create_subclass(¶ms, SWITCH_EVENT_CUSTOM, VM_EVENT_MAINT); @@ -2431,6 +2447,14 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p end: + switch_safe_free(file_path); + + if (tmp_file_path) { + unlink(tmp_file_path); + free(tmp_file_path); + tmp_file_path = NULL; + } + if (switch_channel_ready(channel)) { if (failed) { status = switch_ivr_phrase_macro(session, VM_ABORT_MACRO, NULL, NULL, NULL); @@ -3629,16 +3653,14 @@ SWITCH_STANDARD_API(prefs_api_function) switch_event_add_header_string(new_event, SWITCH_STACK_BOTTOM, "MWI-Message-Account", account); \ switch_event_add_header(new_event, SWITCH_STACK_BOTTOM, "MWI-Voice-Message", "%d/%d (%d/%d)", \ +total_new_messages, total_saved_messages, total_new_urgent_messages, total_saved_urgent_messages); \ - created++; \ } \ } \ } -static void message_query_handler(switch_event_t *event) +static void actual_message_query_handler(switch_event_t *event) { char *account = switch_event_get_header(event, "message-account"); - int created = 0; switch_event_t *new_event = NULL; char *dup = NULL; int total_new_messages = 0; @@ -3677,6 +3699,10 @@ static void message_query_handler(switch_event_t *event) switch_hash_this(hi, NULL, NULL, &val); profile = (vm_profile_t *) val; parse_profile(); + + if (new_event) { + break; + } } } } @@ -3685,7 +3711,7 @@ static void message_query_handler(switch_event_t *event) } - if (!created) { + if (!new_event) { if (switch_event_create(&new_event, SWITCH_EVENT_MESSAGE_WAITING) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(new_event, SWITCH_STACK_BOTTOM, "MWI-Messages-Waiting", "no"); switch_event_add_header_string(new_event, SWITCH_STACK_BOTTOM, "MWI-Message-Account", account); @@ -3707,6 +3733,101 @@ static void message_query_handler(switch_event_t *event) } +static int EVENT_THREAD_RUNNING = 0; +static int EVENT_THREAD_STARTED = 0; + +void *SWITCH_THREAD_FUNC vm_event_thread_run(switch_thread_t *thread, void *obj) +{ + void *pop; + int done = 0; + + switch_mutex_lock(globals.mutex); + if (!EVENT_THREAD_RUNNING) { + EVENT_THREAD_RUNNING++; + globals.threads++; + } else { + done = 1; + } + switch_mutex_unlock(globals.mutex); + + if (done) { + return NULL; + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Event Thread Started\n"); + + while (globals.running == 1) { + int count = 0; + + if (switch_queue_trypop(globals.event_queue, &pop) == SWITCH_STATUS_SUCCESS) { + switch_event_t *event = (switch_event_t *) pop; + + if (!pop) { + break; + } + actual_message_query_handler(event); + switch_event_destroy(&event); + count++; + } + + if (!count) { + switch_yield(100000); + } + } + + while (switch_queue_trypop(globals.event_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) { + switch_event_t *event = (switch_event_t *) pop; + switch_event_destroy(&event); + } + + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Event Thread Ended\n"); + + switch_mutex_lock(globals.mutex); + globals.threads--; + EVENT_THREAD_RUNNING = EVENT_THREAD_STARTED = 0; + switch_mutex_unlock(globals.mutex); + + return NULL; +} + +void vm_event_thread_start(void) +{ + switch_thread_t *thread; + switch_threadattr_t *thd_attr = NULL; + int done = 0; + + switch_mutex_lock(globals.mutex); + if (!EVENT_THREAD_STARTED) { + EVENT_THREAD_STARTED++; + } else { + done = 1; + } + switch_mutex_unlock(globals.mutex); + + if (done) { + return; + } + + switch_threadattr_create(&thd_attr, globals.pool); + switch_threadattr_detach_set(thd_attr, 1); + switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); + switch_threadattr_priority_increase(thd_attr); + switch_thread_create(&thread, thd_attr, vm_event_thread_run, NULL, globals.pool); +} + +void vm_event_handler(switch_event_t *event) +{ + switch_event_t *cloned_event; + + switch_event_dup(&cloned_event, event); + switch_assert(cloned_event); + switch_queue_push(globals.event_queue, cloned_event); + + if (!EVENT_THREAD_STARTED) { + vm_event_thread_start(); + } +} struct holder { vm_profile_t *profile; @@ -5482,14 +5603,20 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_voicemail_load) switch_core_hash_init(&globals.profile_hash, globals.pool); switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool); + switch_mutex_lock(globals.mutex); + globals.running = 1; + switch_mutex_unlock(globals.mutex); + + switch_queue_create(&globals.event_queue, VM_EVENT_QUEUE_SIZE, globals.pool); if ((status = load_config()) != SWITCH_STATUS_SUCCESS) { + globals.running = 0; return status; } /* connect my internal structure to the blank pointer passed to me */ *module_interface = switch_loadable_module_create_module_interface(pool, modname); - if (switch_event_bind(modname, SWITCH_EVENT_MESSAGE_QUERY, SWITCH_EVENT_SUBCLASS_ANY, message_query_handler, NULL) + if (switch_event_bind(modname, SWITCH_EVENT_MESSAGE_QUERY, SWITCH_EVENT_SUBCLASS_ANY, vm_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_GENERR; @@ -5534,9 +5661,23 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_voicemail_shutdown) void *val = NULL; const void *key; switch_ssize_t keylen; + int sanity = 0; + + switch_mutex_lock(globals.mutex); + if (globals.running == 1) { + globals.running = 0; + } + switch_mutex_unlock(globals.mutex); switch_event_free_subclass(VM_EVENT_MAINT); - switch_event_unbind_callback(message_query_handler); + switch_event_unbind_callback(vm_event_handler); + + while (globals.threads) { + switch_cond_next(); + if (++sanity >= 60000) { + break; + } + } switch_mutex_lock(globals.mutex); while ((hi = switch_hash_first(NULL, globals.profile_hash))) { diff --git a/src/mod/endpoints/mod_rtmp/rtmp_sig.c b/src/mod/endpoints/mod_rtmp/rtmp_sig.c index ece43bc050..7aaf79d6f6 100644 --- a/src/mod/endpoints/mod_rtmp/rtmp_sig.c +++ b/src/mod/endpoints/mod_rtmp/rtmp_sig.c @@ -301,7 +301,7 @@ RTMP_INVOKE_FUNCTION(rtmp_i_makeCall) amf_object_to_event(argv[3], &event); } - if (rtmp_session_create_call(rsession, &newsession, 0, RTMP_DEFAULT_STREAM_AUDIO, number, user, domain, event) != SWITCH_CAUSE_NONE) { + if (rtmp_session_create_call(rsession, &newsession, 0, RTMP_DEFAULT_STREAM_AUDIO, number, user, domain, event) != SWITCH_CAUSE_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_ERROR, "Couldn't create call.\n"); } diff --git a/src/mod/endpoints/mod_skypopen/oss/main.c b/src/mod/endpoints/mod_skypopen/oss/main.c index 72d82cb10c..10ebfc9899 100644 --- a/src/mod/endpoints/mod_skypopen/oss/main.c +++ b/src/mod/endpoints/mod_skypopen/oss/main.c @@ -283,6 +283,7 @@ static ssize_t skypopen_write(struct file *filp, const char __user *buf, size_t * The ioctl() implementation */ +#ifndef HAVE_UNLOCKED_IOCTL static int skypopen_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -302,13 +303,38 @@ static int skypopen_ioctl(struct inode *inode, struct file *filp, } } +#else// HAVE_UNLOCKED_IOCTL +static long skypopen_unlocked_ioctl(struct file *filp, + unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + + switch (cmd) { + case OSS_GETVERSION: + return put_user(SOUND_VERSION, p); + case SNDCTL_DSP_GETBLKSIZE: + return put_user(SKYPOPEN_BLK, p); + case SNDCTL_DSP_GETFMTS: + return put_user(28731, p); + + default: + return 0; + } + +} +#endif// HAVE_UNLOCKED_IOCTL struct file_operations skypopen_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .read = skypopen_read, .write = skypopen_write, +#ifndef HAVE_UNLOCKED_IOCTL .ioctl = skypopen_ioctl, +#else// HAVE_UNLOCKED_IOCTL + .unlocked_ioctl = skypopen_unlocked_ioctl, +#endif// HAVE_UNLOCKED_IOCTL .open = skypopen_c_open, .release = skypopen_c_release, }; diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 87817c3c7f..2774e7135a 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -792,6 +792,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session) SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info")), SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str), SOATAG_REUSE_REJECTED(1), SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), + TAG_IF(is_proxy, SOATAG_RTP_SELECT(1)), TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)), TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote), SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)), TAG_END()); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 190212a22b..5566854208 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -354,6 +354,7 @@ struct mod_sofia_globals { int debug_presence; int debug_sla; int auto_restart; + int reg_deny_binding_fetch_and_no_lookup; /* backwards compatibility */ int auto_nat; int tracelevel; char *capture_server; @@ -1116,6 +1117,7 @@ switch_t38_options_t *sofia_glue_extract_t38_options(switch_core_session_t *sess char *sofia_glue_get_multipart(switch_core_session_t *session, const char *prefix, const char *sdp, char **mp_type); void sofia_glue_tech_simplify(private_object_t *tech_pvt); switch_console_callback_match_t *sofia_reg_find_reg_url_multi(sofia_profile_t *profile, const char *user, const char *host); +switch_console_callback_match_t *sofia_reg_find_reg_url_with_positive_expires_multi(sofia_profile_t *profile, const char *user, const char *host); switch_bool_t sofia_glue_profile_exists(const char *key); void sofia_glue_global_siptrace(switch_bool_t on); void sofia_glue_global_capture(switch_bool_t on); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index c225b2bf35..2e2aacf9d0 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -48,7 +48,9 @@ extern su_log_t nth_server_log[]; extern su_log_t nua_log[]; extern su_log_t soa_log[]; extern su_log_t sresolv_log[]; +#ifdef HAVE_SOFIA_STUN extern su_log_t stun_log[]; +#endif extern su_log_t su_log_default[]; static void config_sofia_profile_urls(sofia_profile_t * profile); @@ -1255,8 +1257,9 @@ void sofia_event_callback(nua_event_t event, if (!zstr(sofia_private->uuid)) { if ((session = switch_core_session_locate(sofia_private->uuid))) { - - if (switch_core_session_running(session)) { + switch_channel_t *channel = switch_core_session_get_channel(session); + + if (switch_core_session_running(session) && !switch_channel_test_flag(channel, CF_PROXY_MODE)) { switch_core_session_queue_signal_data(session, de); } else { switch_core_session_message_t msg = { 0 }; @@ -2077,8 +2080,10 @@ static su_log_t *sofia_get_logger(const char *name) return soa_log; } else if (!strcasecmp(name, "sresolv")) { return sresolv_log; +#ifdef HAVE_SOFIA_STUN } else if (!strcasecmp(name, "stun")) { return stun_log; +#endif } else if (!strcasecmp(name, "default")) { return su_log_default; } else { @@ -2105,7 +2110,9 @@ switch_status_t sofia_set_loglevel(const char *name, int level) su_log_set_level(nua_log, level); su_log_set_level(soa_log, level); su_log_set_level(sresolv_log, level); +#ifdef HAVE_SOFIA_STUN su_log_set_level(stun_log, level); +#endif return SWITCH_STATUS_SUCCESS; } @@ -2702,6 +2709,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) mod_sofia_globals.debug_sla = atoi(val); } else if (!strcasecmp(var, "auto-restart")) { mod_sofia_globals.auto_restart = switch_true(val); + } else if (!strcasecmp(var, "reg-deny-binding-fetch-and-no-lookup")) { /* backwards compatibility */ + mod_sofia_globals.reg_deny_binding_fetch_and_no_lookup = switch_true(val); /* remove when noone complains about the extra lookup */ + if (switch_true(val)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Enabling reg-deny-binding-fetch-and-no-lookup - this functionality is " + "deprecated and will be removed - let FS devs know if you think it should stay\n"); + } } else if (!strcasecmp(var, "rewrite-multicasted-fs-path")) { if( (!strcasecmp(val, "to_host")) || (!strcasecmp(val, "1")) ) { /* old behaviour */ @@ -3356,7 +3369,9 @@ switch_status_t config_sofia(int reload, char *profile_name) su_log_redirect(nua_log, logger, NULL); su_log_redirect(soa_log, logger, NULL); su_log_redirect(sresolv_log, logger, NULL); +#ifdef HAVE_SOFIA_STUN su_log_redirect(stun_log, logger, NULL); +#endif } if (!zstr(profile_name) && (profile = sofia_glue_find_profile(profile_name))) { @@ -3377,6 +3392,7 @@ switch_status_t config_sofia(int reload, char *profile_name) } mod_sofia_globals.auto_restart = SWITCH_TRUE; + mod_sofia_globals.reg_deny_binding_fetch_and_no_lookup = SWITCH_FALSE; /* handle backwards compatilibity - by default use new behavior */ mod_sofia_globals.rewrite_multicasted_fs_path = SWITCH_FALSE; if ((settings = switch_xml_child(cfg, "global_settings"))) { @@ -3393,6 +3409,12 @@ switch_status_t config_sofia(int reload, char *profile_name) mod_sofia_globals.debug_sla = atoi(val); } else if (!strcasecmp(var, "auto-restart")) { mod_sofia_globals.auto_restart = switch_true(val); + } else if (!strcasecmp(var, "reg-deny-binding-fetch-and-no-lookup")) { /* backwards compatibility */ + mod_sofia_globals.reg_deny_binding_fetch_and_no_lookup = switch_true(val); /* remove when noone complains about the extra lookup */ + if (switch_true(val)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Enabling reg-deny-binding-fetch-and-no-lookup - this functionality is " + "deprecated and will be removed - let FS devs know if you think it should stay\n"); + } } else if (!strcasecmp(var, "rewrite-multicasted-fs-path")) { if( (!strcasecmp(val, "to_host")) || (!strcasecmp(val, "1")) ) { /* old behaviour */ @@ -6737,35 +6759,37 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t goto end; } - if (dtmf.digit && (tech_pvt->dtmf_type == DTMF_INFO || - sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) || sofia_test_flag(tech_pvt, TFLAG_LIBERAL_DTMF))) { - /* queue it up */ - switch_channel_queue_dtmf(channel, &dtmf); + if (dtmf.digit) { + if (tech_pvt->dtmf_type == DTMF_INFO || + sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) || sofia_test_flag(tech_pvt, TFLAG_LIBERAL_DTMF)) { + /* queue it up */ + switch_channel_queue_dtmf(channel, &dtmf); - /* print debug info */ - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "INFO DTMF(%c)\n", dtmf.digit); + /* print debug info */ + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "INFO DTMF(%c)\n", dtmf.digit); - if (switch_channel_test_flag(channel, CF_PROXY_MODE)) { - const char *uuid; - switch_core_session_t *session_b; + if (switch_channel_test_flag(channel, CF_PROXY_MODE)) { + const char *uuid; + switch_core_session_t *session_b; - if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) && (session_b = switch_core_session_locate(uuid))) { - while (switch_channel_has_dtmf(channel)) { - switch_dtmf_t idtmf = { 0, 0 }; - if (switch_channel_dequeue_dtmf(channel, &idtmf) == SWITCH_STATUS_SUCCESS) { - switch_core_session_send_dtmf(session_b, &idtmf); + if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) && (session_b = switch_core_session_locate(uuid))) { + while (switch_channel_has_dtmf(channel)) { + switch_dtmf_t idtmf = { 0, 0 }; + if (switch_channel_dequeue_dtmf(channel, &idtmf) == SWITCH_STATUS_SUCCESS) { + switch_core_session_send_dtmf(session_b, &idtmf); + } } + + switch_core_session_rwunlock(session_b); } - - switch_core_session_rwunlock(session_b); } - } - /* Send 200 OK response */ - nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END()); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, - "IGNORE INFO DTMF(%c) (This channel was not configured to use INFO DTMF!)\n", dtmf.digit); + /* Send 200 OK response */ + nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END()); + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, + "IGNORE INFO DTMF(%c) (This channel was not configured to use INFO DTMF!)\n", dtmf.digit); + } } goto end; } diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 006f002334..b7b139e52d 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -3989,7 +3989,6 @@ static switch_t38_options_t *tech_process_udptl(private_object_t *tech_pvt, sdp_ { switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options"); sdp_attribute_t *attr; - const char *var; if (!t38_options) { t38_options = switch_core_session_alloc(tech_pvt->session, sizeof(switch_t38_options_t)); @@ -4069,20 +4068,8 @@ static switch_t38_options_t *tech_process_udptl(private_object_t *tech_pvt, sdp_ switch_channel_set_private(tech_pvt->channel, "t38_options", t38_options); switch_channel_set_app_flag_key("T38", tech_pvt->channel, CF_APP_T38); - if ((var = switch_channel_get_variable(tech_pvt->channel, "sip_execute_on_image"))) { - char *app, *arg = NULL; - app = switch_core_session_strdup(tech_pvt->session, var); - - if (strstr(app, "::")) { - switch_core_session_execute_application_async(tech_pvt->session, app, arg); - } else { - if ((arg = strchr(app, ' '))) { - *arg++ = '\0'; - } - - switch_core_session_execute_application(tech_pvt->session, app, arg); - } - } + switch_channel_execute_on(tech_pvt->channel, "sip_execute_on_image"); + switch_channel_api_on(tech_pvt->channel, "sip_api_on_image"); return t38_options; } diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 1d014aff80..e281903dd6 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -30,9 +30,10 @@ * Marcel Barbulescu * David Knell <> * Eliot Gable + * Leon de Rooij * * - * sofia_ref.c -- SOFIA SIP Endpoint (registration code) + * sofia_reg.c -- SOFIA SIP Endpoint (registration code) * */ #include "mod_sofia.h" @@ -466,6 +467,39 @@ int sofia_reg_find_callback(void *pArg, int argc, char **argv, char **columnName return cbt->matches == 1 ? 0 : 1; } + +int sofia_reg_find_reg_with_positive_expires_callback(void *pArg, int argc, char **argv, char **columnNames) +{ + struct callback_t *cbt = (struct callback_t *) pArg; + sofia_destination_t *dst = NULL; + long int expires; + char *contact = NULL; + + expires = atol(argv[1]) - 60 - (long) switch_epoch_time_now(NULL); + + if (expires > 0) { + dst = sofia_glue_get_destination(argv[0]); + contact = switch_mprintf("<%s>;expires=%ld", dst->contact, expires); + + if (!cbt->len) { + switch_console_push_match(&cbt->list, contact); + switch_safe_free(contact); + sofia_glue_free_destination(dst); + cbt->matches++; + return 0; + } + + switch_copy_string(cbt->val, contact, cbt->len); + switch_safe_free(contact); + sofia_glue_free_destination(dst); + cbt->matches++; + return cbt->matches == 1 ? 0 : 1; + } + + return 0; +} + + int sofia_reg_nat_callback(void *pArg, int argc, char **argv, char **columnNames) { sofia_profile_t *profile = (sofia_profile_t *) pArg; @@ -875,6 +909,29 @@ switch_console_callback_match_t *sofia_reg_find_reg_url_multi(sofia_profile_t *p } +switch_console_callback_match_t *sofia_reg_find_reg_url_with_positive_expires_multi(sofia_profile_t *profile, const char *user, const char *host) +{ + struct callback_t cbt = { 0 }; + char sql[512] = ""; + + if (!user) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Called with null user!\n"); + return NULL; + } + + if (host) { + switch_snprintf(sql, sizeof(sql), "select contact,expires from sip_registrations where sip_user='%s' and (sip_host='%s' or presence_hosts like '%%%s%%')", + user, host, host); + } else { + switch_snprintf(sql, sizeof(sql), "select contact,expires from sip_registrations where sip_user='%s'", user); + } + + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_reg_find_reg_with_positive_expires_callback, &cbt); + + return cbt.list; +} + + void sofia_reg_auth_challenge(sofia_profile_t *profile, nua_handle_t *nh, sofia_dispatch_event_t *de, sofia_regtype_t regtype, const char *realm, int stale) { @@ -983,8 +1040,8 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand } } - /* all callers must confirm that sip, sip->sip_request and sip->sip_contact are not NULL */ - switch_assert(sip != NULL && sip->sip_contact != NULL && sip->sip_request != NULL); + /* all callers must confirm that sip and sip->sip_request are not NULL */ + switch_assert(sip != NULL && sip->sip_request != NULL); sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port); @@ -1032,7 +1089,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand sub_host = to_host; } - if (contact->m_url) { + if (contact && contact->m_url) { const char *port = contact->m_url->url_port; char new_port[25] = ""; const char *contact_host = contact->m_url->url_host; @@ -1130,7 +1187,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand if (expires) { exptime = expires->ex_delta; - } else if (contact->m_expires) { + } else if (contact && contact->m_expires) { exptime = atol(contact->m_expires); } @@ -1163,11 +1220,13 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", to_user); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", reg_host); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str); + if (contact) + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", rpid); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", reg_desc); - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long) exptime); + if (contact) + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long) exptime); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-user", from_user); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-host", from_host); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-ip", network_ip); @@ -1178,7 +1237,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand switch_event_fire(&s_event); } - if (exptime && v_event && *v_event) { + if (contact && exptime && v_event && *v_event) { char *exp_var; char *allow_multireg = NULL; int auto_connectile = 0; @@ -1310,11 +1369,13 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", to_user); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", reg_host); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str); + if (contact) + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", rpid); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", reg_desc); - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long) exptime); + if (contact) + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long) exptime); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-user", from_user); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-host", from_host); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-ip", network_ip); @@ -1343,6 +1404,10 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand switch_goto_int(r, 1, end); } + + if (!contact) + goto respond_200_ok; + reg: @@ -1589,69 +1654,107 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand } } + respond_200_ok: if (regtype == REG_REGISTER) { char exp_param[128] = ""; char date[80] = ""; switch_event_t *s_mwi_event = NULL; + switch_console_callback_match_t *contact_list = NULL; + tagi_t *contact_tags; + switch_console_callback_match_node_t *m; + int i; + s_event = NULL; - if (exptime) { - switch_snprintf(exp_param, sizeof(exp_param), "expires=%ld", exptime); - sip_contact_add_param(nua_handle_home(nh), sip->sip_contact, exp_param); + if (contact) { + if (exptime) { + switch_snprintf(exp_param, sizeof(exp_param), "expires=%ld", exptime); + sip_contact_add_param(nua_handle_home(nh), sip->sip_contact, exp_param); - if (sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER) || - (reg_count == 1 && sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER))) { - if (switch_event_create(&s_mwi_event, SWITCH_EVENT_MESSAGE_QUERY) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(s_mwi_event, SWITCH_STACK_BOTTOM, "Message-Account", "sip:%s@%s", mwi_user, mwi_host); - switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Sofia-Profile", profile->name); - switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Call-ID", call_id); - } - } - - if (sofia_test_pflag(profile, PFLAG_PRESENCE_ON_REGISTER) || - (reg_count == 1 && sofia_test_pflag(profile, PFLAG_PRESENCE_ON_FIRST_REGISTER)) - || send_pres == 1 || (reg_count == 1 && send_pres == 2)) { - - if (sofia_test_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER)) { - if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host); - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, sub_host); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence"); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); - switch_event_fire(&s_event); + if (sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER) || + (reg_count == 1 && sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER))) { + if (switch_event_create(&s_mwi_event, SWITCH_EVENT_MESSAGE_QUERY) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(s_mwi_event, SWITCH_STACK_BOTTOM, "Message-Account", "sip:%s@%s", mwi_user, mwi_host); + switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Sofia-Profile", profile->name); + switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Call-ID", call_id); } - } else { - if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "unknown"); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Registered"); - switch_event_fire(&s_event); - } } - } - } else { - switch_core_del_registration(to_user, reg_host, call_id); - if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_UNREGISTER) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", to_user); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", reg_host); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", rpid); - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long) exptime); + if (sofia_test_pflag(profile, PFLAG_PRESENCE_ON_REGISTER) || + (reg_count == 1 && sofia_test_pflag(profile, PFLAG_PRESENCE_ON_FIRST_REGISTER)) + || send_pres == 1 || (reg_count == 1 && send_pres == 2)) { + + if (sofia_test_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER)) { + if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, sub_host); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence"); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); + switch_event_fire(&s_event); + } + } else { + if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "unknown"); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Registered"); + switch_event_fire(&s_event); + } + } + } + } else { + switch_core_del_registration(to_user, reg_host, call_id); + + if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_UNREGISTER) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", to_user); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", reg_host); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", rpid); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long) exptime); + } } } switch_rfc822_date(date, switch_micro_time_now()); - nua_respond(nh, SIP_200_OK, SIPTAG_CONTACT(sip->sip_contact), - TAG_IF(path_val, SIPTAG_PATH_STR(path_val)), NUTAG_WITH_THIS_MSG(de->data->e_msg), SIPTAG_DATE_STR(date), TAG_END()); + + /* generate and respond a 200 OK */ + + if (mod_sofia_globals.reg_deny_binding_fetch_and_no_lookup) { + /* handle backwards compatibility - contacts will not be looked up but only copied from the request into the response + remove this condition later if nobody complains about the extra select of the below new behavior + also remove the parts in mod_sofia.h, sofia.c and sofia_reg.c that refer to reg_deny_binding_fetch_and_no_lookup */ + nua_respond(nh, SIP_200_OK, TAG_IF(contact, SIPTAG_CONTACT(sip->sip_contact)), TAG_IF(path_val, SIPTAG_PATH_STR(path_val)), + NUTAG_WITH_THIS_MSG(de->data->e_msg), SIPTAG_DATE_STR(date), TAG_END()); + + } else if ((contact_list = sofia_reg_find_reg_url_with_positive_expires_multi(profile, from_user, reg_host))) { + /* all + 1 tag_i elements initialized as NULL - last one implies TAG_END() */ + switch_zmalloc(contact_tags, sizeof(*contact_tags) * (contact_list->count + 1)); + i = 0; + for (m = contact_list->head; m; m = m->next) { + contact_tags[i].t_tag = siptag_contact_str; + contact_tags[i].t_value = (tag_value_t) m->val; + ++i; + } + + nua_respond(nh, SIP_200_OK, TAG_IF(path_val, SIPTAG_PATH_STR(path_val)), + NUTAG_WITH_THIS_MSG(de->data->e_msg), SIPTAG_DATE_STR(date), TAG_NEXT(contact_tags)); + + switch_safe_free(contact_tags); + switch_console_free_matches(&contact_list); + + } else { + /* respond without any contacts */ + nua_respond(nh, SIP_200_OK, TAG_IF(path_val, SIPTAG_PATH_STR(path_val)), + NUTAG_WITH_THIS_MSG(de->data->e_msg), SIPTAG_DATE_STR(date), TAG_END()); + } + if (s_event) { switch_event_fire(&s_event); @@ -1661,7 +1764,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand switch_event_fire(&s_mwi_event); } - if (*contact_str && sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE_SYLANTRO)) { + if (contact && *contact_str && sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE_SYLANTRO)) { sofia_sla_handle_register(nua, profile, sip, de, exptime, contact_str); } @@ -1707,7 +1810,8 @@ void sofia_reg_handle_sip_i_register(nua_t *nua, sofia_profile_t *profile, nua_h sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port); - if (!(sip->sip_contact && sip->sip_contact->m_url)) { + /* backwards compatibility */ + if (mod_sofia_globals.reg_deny_binding_fetch_and_no_lookup && !(sip->sip_contact && sip->sip_contact->m_url)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NO CONTACT! ip: %s, port: %i\n", network_ip, network_port); nua_respond(nh, 400, "Missing Contact Header", TAG_END()); goto end; diff --git a/src/switch_channel.c b/src/switch_channel.c index 4f272db7e2..0a6071105f 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -362,7 +362,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *chan { switch_status_t status; void *pop; - switch_dtmf_t new_dtmf; + switch_dtmf_t new_dtmf = { 0 }; switch_assert(dtmf); @@ -376,14 +376,17 @@ SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *chan if (is_dtmf(new_dtmf.digit)) { switch_dtmf_t *dt; int x = 0; + char str[2] = ""; + str[0] = new_dtmf.digit; + if (new_dtmf.duration > switch_core_max_dtmf_duration(0)) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "%s EXCESSIVE DTMF DIGIT [%c] LEN [%d]\n", - switch_channel_get_name(channel), new_dtmf.digit, new_dtmf.duration); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "%s EXCESSIVE DTMF DIGIT [%s] LEN [%d]\n", + switch_channel_get_name(channel), str, new_dtmf.duration); new_dtmf.duration = switch_core_max_dtmf_duration(0); } else if (new_dtmf.duration < switch_core_min_dtmf_duration(0)) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "%s SHORT DTMF DIGIT [%c] LEN [%d]\n", - switch_channel_get_name(channel), new_dtmf.digit, new_dtmf.duration); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "%s SHORT DTMF DIGIT [%s] LEN [%d]\n", + switch_channel_get_name(channel), str, new_dtmf.duration); new_dtmf.duration = switch_core_min_dtmf_duration(0); } else if (!new_dtmf.duration) { new_dtmf.duration = switch_core_default_dtmf_duration(0); @@ -1014,8 +1017,10 @@ SWITCH_DECLARE(void) switch_channel_process_export(switch_channel_t *channel, sw const char *vval; if ((vval = switch_channel_get_variable(channel, argv[x]))) { char *vvar = argv[x]; - if (!strncasecmp(vvar, "nolocal:", 8)) { + if (!strncasecmp(vvar, "nolocal:", 8)) { /* remove this later ? */ vvar += 8; + } else if (!strncasecmp(vvar, "_nolocal_", 9)) { + vvar += 9; } if (var_event) { switch_event_del_header(var_event, vvar); @@ -1055,9 +1060,12 @@ SWITCH_DECLARE(switch_status_t) switch_channel_export_variable_var_check(switch_ var = switch_core_session_strdup(channel->session, varname); if (var) { - if (!strncasecmp(var, "nolocal:", 8)) { + if (!strncasecmp(var, "nolocal:", 8)) { /* remove this later ? */ var_name = var + 8; local = 0; + } else if (!strncasecmp(var, "_nolocal_", 9)) { + var_name = var + 9; + local = 0; } else { var_name = var; } @@ -2822,6 +2830,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_ring_ready_value(swi } switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_RING_VARIABLE); + switch_channel_api_on(channel, SWITCH_CHANNEL_API_ON_RING_VARIABLE); return SWITCH_STATUS_SUCCESS; } @@ -2869,7 +2878,8 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_pre_answered(switch_ switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE); switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE); - + switch_channel_api_on(channel, SWITCH_CHANNEL_API_ON_PRE_ANSWER_VARIABLE); + switch_channel_api_on(channel, SWITCH_CHANNEL_API_ON_MEDIA_VARIABLE); if ((var = switch_channel_get_variable(channel, SWITCH_PASSTHRU_PTIME_MISMATCH_VARIABLE))) { switch_channel_set_flag(channel, CF_PASSTHRU_PTIME_MISMATCH); @@ -2961,43 +2971,108 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_ring_ready_value(switch_c return status; } +static void do_api_on(switch_channel_t *channel, const char *variable) +{ + char *app; + char *arg = NULL; + switch_stream_handle_t stream = { 0 }; + + app = switch_core_session_strdup(channel->session, variable); + + if ((arg = strchr(app, ' '))) { + *arg++ = '\0'; + } + + SWITCH_STANDARD_STREAM(stream); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "%s process %s: %s(%s)\n%s\n", + channel->name, variable, app, switch_str_nil(arg), (char *) stream.data); + switch_api_execute(app, arg, NULL, &stream); + free(stream.data); +} + + +SWITCH_DECLARE(switch_status_t) switch_channel_api_on(switch_channel_t *channel, const char *variable_prefix) +{ + switch_event_header_t *hp; + switch_event_t *event; + int x = 0; + + + switch_channel_get_variables(channel, &event); + + for (hp = event->headers; hp; hp = hp->next) { + char *var = hp->name; + char *val = hp->value; + + if (!strncasecmp(var, variable_prefix, strlen(variable_prefix))) { + if (hp->idx) { + int i; + for (i = 0; i < hp->idx; i++) { + x++; + do_api_on(channel, hp->array[i]); + } + } else { + x++; + do_api_on(channel, val); + } + } + } + + switch_event_destroy(&event); + + return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; +} + +static void do_execute_on(switch_channel_t *channel, const char *variable) +{ + char *arg = NULL; + char *p; + int bg = 0; + char *app; + + app = switch_core_session_strdup(channel->session, variable); + + for(p = app; p && *p; p++) { + if (*p == ' ') { + *p++ = '\0'; + arg = p; + break; + } else if (*p == ':' && (*(p+1) == ':')) { + bg++; + break; + } + } + + + if (bg) { + switch_core_session_execute_application_async(channel->session, app, arg); + } else { + switch_core_session_execute_application(channel->session, app, arg); + } +} + SWITCH_DECLARE(switch_status_t) switch_channel_execute_on(switch_channel_t *channel, const char *variable_prefix) { - switch_event_header_t *hi; + switch_event_header_t *hp; switch_event_t *event; int x = 0; switch_channel_get_variables(channel, &event); - for (hi = event->headers; hi; hi = hi->next) { - char *var = hi->name; - char *val = hi->value; - char *app; - + for (hp = event->headers; hp; hp = hp->next) { + char *var = hp->name; + char *val = hp->value; + if (!strncasecmp(var, variable_prefix, strlen(variable_prefix))) { - char *arg = NULL; - char *p; - int bg = 0; - x++; - - app = switch_core_session_strdup(channel->session, val); - - for(p = app; p && *p; p++) { - if (*p == ' ') { - *p++ = '\0'; - arg = p; - break; - } else if (*p == ':' && (*(p+1) == ':')) { - bg++; - break; + if (hp->idx) { + int i; + for (i = 0; i < hp->idx; i++) { + x++; + do_execute_on(channel, hp->array[i]); } - } - - - if (bg) { - switch_core_session_execute_application_async(channel->session, app, arg); } else { - switch_core_session_execute_application(channel->session, app, arg); + x++; + do_execute_on(channel, val); } } } @@ -3013,7 +3088,6 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_answered(switch_chan const char *uuid; switch_core_session_t *other_session; const char *var; - char *app; switch_assert(channel != NULL); @@ -3079,24 +3153,10 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_answered(switch_chan if (!switch_channel_test_flag(channel, CF_EARLY_MEDIA)) { switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE); + switch_channel_api_on(channel, SWITCH_CHANNEL_API_ON_MEDIA_VARIABLE); } - if ((var = switch_channel_get_variable(channel, SWITCH_CHANNEL_API_ON_ANSWER_VARIABLE)) && !zstr(var)) { - switch_stream_handle_t stream = { 0 }; - char *arg = NULL; - - app = switch_core_session_strdup(channel->session, var); - if ((arg = strchr(app, ' '))) { - *arg++ = '\0'; - } - - SWITCH_STANDARD_STREAM(stream); - switch_api_execute(app, arg, NULL, &stream); - - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "%s api on answer: %s(%s)\n%s\n", - channel->name, app, switch_str_nil(arg), (char *) stream.data); - free(stream.data); - } + switch_channel_api_on(channel, SWITCH_CHANNEL_API_ON_ANSWER_VARIABLE); switch_channel_presence(channel, "unknown", "answered", NULL); diff --git a/src/switch_core_file.c b/src/switch_core_file.c index 58b63bdc4b..28f1172ff8 100644 --- a/src/switch_core_file.c +++ b/src/switch_core_file.c @@ -135,10 +135,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, switch_uuid_format(uuid_str, &uuid); fh->spool_path = switch_core_sprintf(fh->memory_pool, "%s%s%s.%s", spool_path, SWITCH_PATH_SEPARATOR, uuid_str, ext); + } else { + fh->spool_path = NULL; } if (rhs) { fh->handler = switch_core_strdup(fh->memory_pool, rhs); + } else { + fh->handler = NULL; } if (channels) { diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index b23d082bdf..798e7c288f 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -996,7 +996,7 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, trans = 1; } - if (len + newlen > sql_len) { + if (len + newlen + 1 > sql_len) { int new_mlen = len + newlen + 10240; if (new_mlen < runtime.max_sql_buffer_len) { @@ -1935,7 +1935,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ case SCDB_TYPE_ODBC: { char *err; - switch_cache_db_test_reactive(dbh, "select call_uuid, read_bit_rate from channels", "DROP TABLE channels", create_channels_sql); + switch_cache_db_test_reactive(dbh, "select call_uuid, read_bit_rate, sent_callee_name from channels", "DROP TABLE channels", create_channels_sql); switch_cache_db_test_reactive(dbh, "select * from detailed_calls where sent_callee_name=''", "DROP VIEW detailed_calls", detailed_calls_sql); switch_cache_db_test_reactive(dbh, "select * from basic_calls where sent_callee_name=''", "DROP VIEW basic_calls", basic_calls_sql); if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { diff --git a/src/switch_event.c b/src/switch_event.c index b469b9f7b7..8265a18207 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -333,17 +333,11 @@ static void *SWITCH_THREAD_FUNC switch_event_thread(switch_thread_t *thread, voi if (++loops > 2) { - uint32_t last_sps = 0, sess_count = switch_core_session_count(); if (auto_pause) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Event system *still* overloading.\n"); } else { - switch_core_session_ctl(SCSC_LAST_SPS, &last_sps); - last_sps = (uint32_t) (float) (last_sps * 0.75f); - sess_count = (uint32_t) (float) (sess_count * 0.75f); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, - "Event system overloading. Taking a 10 second break, Reducing max_sessions to %d %dsps\n", sess_count, last_sps); - switch_core_session_limit(sess_count); - switch_core_session_ctl(SCSC_SPS, &last_sps); + "Event system overloading. Taking a 10 second break\n"); auto_pause = 10; switch_core_session_ctl(SCSC_PAUSE_INBOUND, &auto_pause); } diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index a47cfbd0c0..b55413f007 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -2458,6 +2458,8 @@ static switch_status_t tone_on_dtmf(switch_core_session_t *session, const switch cont->list[i].callback(cont->session, cont->list[i].app, cont->list[i].data); } else { switch_channel_execute_on(switch_core_session_get_channel(cont->session), SWITCH_CHANNEL_EXECUTE_ON_TONE_DETECT_VARIABLE); + switch_channel_api_on(switch_core_session_get_channel(cont->session), SWITCH_CHANNEL_API_ON_TONE_DETECT_VARIABLE); + if (cont->list[i].app) { switch_core_session_execute_application_async(cont->session, cont->list[i].app, cont->list[i].data); } diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index 262d6d7a91..9ab1c1b1da 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -2561,7 +2561,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess switch_channel_set_variable(originate_status[i].peer_channel, "originating_leg_uuid", switch_core_session_get_uuid(session)); } - switch_channel_execute_on(originate_status[i].peer_channel, "execute_on_originate"); + switch_channel_execute_on(originate_status[i].peer_channel, SWITCH_CHANNEL_EXECUTE_ON_ORIGINATE_VARIABLE); + switch_channel_api_on(originate_status[i].peer_channel, SWITCH_CHANNEL_API_ON_ORIGINATE_VARIABLE); } if (table) { diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index bc6ba62120..c5200d0e0e 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -377,7 +377,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se int divisor = 0; int file_flags = SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT; int restart_limit_on_dtmf = 0; - const char *prefix; + const char *prefix, *var; prefix = switch_channel_get_variable(channel, "sound_prefix"); @@ -756,6 +756,29 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se switch_core_file_close(fh); + + if ((var = switch_channel_get_variable(channel, "record_post_process_exec_api"))) { + char *cmd = switch_core_session_strdup(session, var); + char *data, *expanded = NULL; + switch_stream_handle_t stream = { 0 }; + + SWITCH_STANDARD_STREAM(stream); + + if ((data = strchr(cmd, ':'))) { + *data++ = '\0'; + expanded = switch_channel_expand_variables(channel, data); + } + + switch_api_execute(cmd, expanded, session, &stream); + + if (expanded && expanded != data) { + free(expanded); + } + + switch_safe_free(stream.data); + + } + if (read_impl.samples_per_second) { switch_channel_set_variable_printf(channel, "record_seconds", "%d", fh->samples_out / read_impl.samples_per_second); switch_channel_set_variable_printf(channel, "record_ms", "%d", fh->samples_out / (read_impl.samples_per_second / 1000)); diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c index 8fca52eb58..007309781e 100644 --- a/src/switch_loadable_module.c +++ b/src/switch_loadable_module.c @@ -994,8 +994,8 @@ static switch_status_t switch_loadable_module_load_module_ex(char *dir, char *fn switch_snprintf(path, len, "%s%s%s%s", dir, SWITCH_PATH_SEPARATOR, file, ext); } - switch_mutex_lock(loadable_modules.mutex); - if (switch_core_hash_find(loadable_modules.module_hash, file)) { + + if (switch_core_hash_find_locked(loadable_modules.module_hash, file, loadable_modules.mutex)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Module %s Already Loaded!\n", file); *err = "Module already loaded"; status = SWITCH_STATUS_FALSE; @@ -1010,7 +1010,7 @@ static switch_status_t switch_loadable_module_load_module_ex(char *dir, char *fn } else { *err = "module load file routine returned an error"; } - switch_mutex_unlock(loadable_modules.mutex); + return status;