Merge branch 'master' into smgmaster

This commit is contained in:
David Yat Sin committed 2011-04-04 16:04:51 -04:00
commit 2b8d96a301
364 files changed
+122942 -1699

No files matched your search

+5
View File
@@ -150,6 +150,7 @@
*
* - Linux (x86 & x86_64)
* - Windows (MSVC 2008 & VC++ EE 2008)
* - Windows (MSVC 2010 & VC++ EE 2010)
* - Mac OS X (intel & ppc )
* - FreeBSD 6
*
@@ -176,6 +177,10 @@
* mod_pocketsphinx
* - PocketSphinx (http://www.speech.cs.cmu.edu/pocketsphinx/)
*
* mod_unimrcp
* - MRCP (http://www.unimrcp.org/)
*
*
* Codecs
* mod_speex
* - libspeex (http://www.speex.org/)
+2
View File
@@ -145,6 +145,8 @@ SWITCH_DECLARE(int) switch_snprintf(_Out_z_cap_(len)
SWITCH_DECLARE(int) switch_vasprintf(_Out_opt_ char **buf, _In_z_ _Printf_format_string_ const char *format, _In_ va_list ap);
SWITCH_DECLARE(int) switch_vsnprintf(char *buf, switch_size_t len, const char *format, va_list ap);
SWITCH_DECLARE(char *) switch_copy_string(_Out_z_cap_(dst_size)
char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size);
+3
View File
@@ -615,6 +615,9 @@ 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_END_EXTERN_C
#endif
/* For Emacs:
+10 -1
View File
@@ -1183,7 +1183,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(_In_ switch_core_s
///\ingroup core1
///\{
/*!
\brief Initilize a hash table
\brief Initialize a hash table
\param hash a NULL pointer to a hash table to aim at the new hash
\param pool the pool to use for the new hash
\return SWITCH_STATUS_SUCCESS if the hash is created
@@ -2240,6 +2240,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_del_registration(const char *user, c
*/
SWITCH_DECLARE(switch_status_t) switch_core_expire_registration(int force);
SWITCH_DECLARE(char *) switch_say_file_handle_get_variable(switch_say_file_handle_t *sh, const char *var);
SWITCH_DECLARE(char *) switch_say_file_handle_get_path(switch_say_file_handle_t *sh);
SWITCH_DECLARE(char *) switch_say_file_handle_detach_path(switch_say_file_handle_t *sh);
SWITCH_DECLARE(void) switch_say_file_handle_destroy(switch_say_file_handle_t **sh);
SWITCH_DECLARE(switch_status_t) switch_say_file_handle_create(switch_say_file_handle_t **sh, const char *ext, switch_event_t **var_event);
SWITCH_DECLARE(void) switch_say_file(switch_say_file_handle_t *sh, const char *fmt, ...);
SWITCH_END_EXTERN_C
#endif
/* For Emacs:
+10
View File
@@ -859,6 +859,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
const char *say_gender,
switch_input_args_t *args);
SWITCH_DECLARE(switch_status_t) switch_ivr_say_string(switch_core_session_t *session,
const char *lang,
const char *ext,
const char *tosay,
const char *module_name,
const char *say_type,
const char *say_method,
const char *say_gender,
char **rstr);
SWITCH_DECLARE(switch_say_method_t) switch_ivr_get_say_method_by_name(const char *name);
SWITCH_DECLARE(switch_say_gender_t) switch_ivr_get_say_gender_by_name(const char *name);
SWITCH_DECLARE(switch_say_type_t) switch_ivr_get_say_type_by_name(const char *name);
+3 -22
View File
@@ -103,29 +103,9 @@ struct switch_stream_handle {
};
struct switch_io_event_hooks;
struct switch_say_file_handle;
typedef switch_call_cause_t (*switch_io_outgoing_channel_t)
typedef switch_call_cause_t (*switch_io_outgoing_channel_t)
(switch_core_session_t *, switch_event_t *, switch_caller_profile_t *, switch_core_session_t **, switch_memory_pool_t **, switch_originate_flag_t,
switch_call_cause_t *);
typedef switch_status_t (*switch_io_read_frame_t) (switch_core_session_t *, switch_frame_t **, switch_io_flag_t, int);
@@ -490,6 +470,7 @@ struct switch_say_interface {
const char *interface_name;
/*! function to pass down to the module */
switch_say_callback_t say_function;
switch_say_string_callback_t say_string_function;
switch_thread_rwlock_t *rwlock;
int refs;
switch_mutex_t *reflock;
+6 -1
View File
@@ -56,7 +56,7 @@ SWITCH_DECLARE(const char *) switch_nat_get_type(void);
\param pool the memory pool to use for long term allocations
\note Generally called by the core_init
*/
SWITCH_DECLARE(void) switch_nat_init(switch_memory_pool_t *pool);
SWITCH_DECLARE(void) switch_nat_init(switch_memory_pool_t *pool, switch_bool_t mapping);
/*!
\brief Initilize the rest of the NAT Traversal System
@@ -86,6 +86,11 @@ SWITCH_DECLARE(void) switch_nat_republish(void);
*/
SWITCH_DECLARE(void) switch_nat_reinit(void);
/*!
\brief Update the setting if port mapping will be created
*/
SWITCH_DECLARE(void) switch_nat_set_mapping(switch_bool_t mapping);
/*!
\brief Maps a port through the NAT Traversal System
\param port Internal port to map
+21 -5
View File
@@ -36,6 +36,7 @@
#define SWITCH_TYPES_H
#include <switch.h>
SWITCH_BEGIN_EXTERN_C
#define SWITCH_ENT_ORIGINATE_DELIM ":_:"
#define SWITCH_BLANK_STRING ""
@@ -264,7 +265,8 @@ typedef enum {
SCF_VERBOSE_EVENTS = (1 << 11),
SCF_USE_WIN32_MONOTONIC = (1 << 12),
SCF_AUTO_SCHEMAS = (1 << 13),
SCF_MINIMAL = (1 << 14)
SCF_MINIMAL = (1 << 14),
SCF_USE_NAT_MAPPING = (1 << 15)
} switch_core_flag_enum_t;
typedef uint32_t switch_core_flag_t;
@@ -515,7 +517,6 @@ typedef enum {
SWITCH_RTP_FLAG_NOBLOCK - Do not block
SWITCH_RTP_FLAG_IO - IO is ready
SWITCH_RTP_FLAG_USE_TIMER - Timeout Reads and replace with a CNG Frame
SWITCH_RTP_FLAG_TIMER_RECLOCK - Resync the timer to the current clock on slips
SWITCH_RTP_FLAG_SECURE - Secure RTP
SWITCH_RTP_FLAG_AUTOADJ - Auto-Adjust the dest based on the source
SWITCH_RTP_FLAG_RAW_WRITE - Try to forward packets unscathed
@@ -532,7 +533,7 @@ typedef enum {
SWITCH_RTP_FLAG_NOBLOCK = (1 << 0),
SWITCH_RTP_FLAG_IO = (1 << 1),
SWITCH_RTP_FLAG_USE_TIMER = (1 << 2),
SWITCH_RTP_FLAG_TIMER_RECLOCK = (1 << 3),
SWITCH_RTP_FLAG_RTCP_PASSTHRU = (1 << 3),
SWITCH_RTP_FLAG_SECURE_SEND = (1 << 4),
SWITCH_RTP_FLAG_SECURE_RECV = (1 << 5),
SWITCH_RTP_FLAG_AUTOADJ = (1 << 6),
@@ -559,8 +560,7 @@ typedef enum {
SWITCH_RTP_FLAG_DEBUG_RTP_READ = (1 << 27),
SWITCH_RTP_FLAG_DEBUG_RTP_WRITE = (1 << 28),
SWITCH_RTP_FLAG_VIDEO = (1 << 29),
SWITCH_RTP_FLAG_ENABLE_RTCP = (1 << 30),
SWITCH_RTP_FLAG_RTCP_PASSTHRU = (1 << 31)
SWITCH_RTP_FLAG_ENABLE_RTCP = (1 << 30)
/* don't add any more 31 is the limit! gotta chnge to an array to add more */
} switch_rtp_flag_enum_t;
typedef uint32_t switch_rtp_flag_t;
@@ -1737,6 +1737,7 @@ typedef switch_status_t (*switch_stream_handle_raw_write_function_t) (switch_str
typedef switch_status_t (*switch_api_function_t) (_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session,
_In_ switch_stream_handle_t *stream);
#define SWITCH_STANDARD_API(name) static switch_status_t name (_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session, _In_ switch_stream_handle_t *stream)
typedef switch_status_t (*switch_input_callback_function_t) (switch_core_session_t *session, void *input,
@@ -1774,17 +1775,32 @@ typedef struct {
switch_ivr_dmachine_t *dmachine;
} switch_input_args_t;
typedef struct {
switch_say_type_t type;
switch_say_method_t method;
switch_say_gender_t gender;
const char *ext;
} switch_say_args_t;
typedef switch_status_t (*switch_say_callback_t) (switch_core_session_t *session,
char *tosay,
switch_say_args_t *say_args,
switch_input_args_t *args);
typedef switch_status_t (*switch_say_string_callback_t) (switch_core_session_t *session,
char *tosay,
switch_say_args_t *say_args, char **rstr);
struct switch_say_file_handle;
typedef struct switch_say_file_handle switch_say_file_handle_t;
typedef switch_status_t (*switch_new_say_callback_t) (switch_say_file_handle_t *sh,
char *tosay,
switch_say_args_t *say_args);
typedef struct switch_xml *switch_xml_t;
typedef struct switch_core_time_duration switch_core_time_duration_t;
typedef switch_xml_t(*switch_xml_search_function_t) (const char *section,
+8 -4
View File
@@ -151,7 +151,11 @@ static inline char *switch_strchr_strict(const char *in, char find, const char *
#endif
static inline int switch_string_has_escaped_data(const char *in)
{
const char *i = strchr(in, '\\');
const char *i;
switch_assert(in);
i = strchr(in, '\\');
while (i && *i == '\\') {
i++;
@@ -631,7 +635,7 @@ SWITCH_DECLARE(switch_time_t) switch_str_time(const char *in);
#define switch_time_from_sec(sec) ((switch_time_t)(sec) * 1000000)
/*!
\brief Declares a function designed to set a dymaic global string
\brief Declares a function designed to set a dynamic global string
\param fname the function name to declare
\param vname the name of the global pointer to modify with the new function
*/
@@ -639,9 +643,9 @@ SWITCH_DECLARE(switch_time_t) switch_str_time(const char *in);
if (vname) {free(vname); vname = NULL;}vname = strdup(string);} static void fname(const char *string)
/*!
\brief Separate a string into an array based on a character delimeter
\brief Separate a string into an array based on a character delimiter
\param buf the string to parse
\param delim the character delimeter
\param delim the character delimiter
\param array the array to split the values into
\param arraylen the max number of elements in the array
\return the number of elements added to the array
+1
View File
@@ -98,6 +98,7 @@ struct switch_xml {
uint32_t flags;
/*! is_switch_xml_root bool */
switch_bool_t is_switch_xml_root_t;
uint32_t refs;
};
/*!
@@ -177,8 +177,9 @@ static char members_sql[] =
" queue VARCHAR(255),\n"
" system VARCHAR(255),\n"
" uuid VARCHAR(255) NOT NULL DEFAULT '',\n"
" caller_number VARCHAR(255),\n"
" caller_name VARCHAR(255),\n"
" session_uuid VARCHAR(255) NOT NULL DEFAULT '',\n"
" cid_number VARCHAR(255),\n"
" cid_name VARCHAR(255),\n"
" system_epoch INTEGER NOT NULL DEFAULT 0,\n"
" joined_epoch INTEGER NOT NULL DEFAULT 0,\n"
" rejoined_epoch INTEGER NOT NULL DEFAULT 0,\n"
@@ -704,7 +705,7 @@ static cc_queue_t *load_queue(const char *queue_name)
goto end;
}
switch_cache_db_test_reactive(dbh, "select count(rejoined_epoch) from members", "drop table members", members_sql);
switch_cache_db_test_reactive(dbh, "select count(session_uuid) from members", "drop table members", members_sql);
switch_cache_db_test_reactive(dbh, "select count(ready_time) from agents", NULL, "alter table agents add ready_time integer not null default 0;"
"alter table agents add reject_delay_time integer not null default 0;"
"alter table agents add busy_delay_time integer not null default 0;");
@@ -718,7 +719,7 @@ static cc_queue_t *load_queue(const char *queue_name)
/* Reset a unclean shutdown */
sql = switch_mprintf("UPDATE agents SET state = 'Waiting', uuid = '' WHERE system = 'single_box';"
"UPDATE tiers SET state = 'Ready' WHERE agent IN (SELECT name FROM agents WHERE system = 'single_box');"
"UPDATE members SET state = '%q', uuid = '' WHERE system = 'single_box';",
"UPDATE members SET state = '%q', session_uuid = '' WHERE system = 'single_box';",
cc_member_state2str(CC_MEMBER_STATE_ABANDONED));
cc_execute_sql(NULL, sql, NULL);
@@ -756,11 +757,12 @@ static cc_queue_t *get_queue(const char *queue_name)
struct call_helper {
const char *member_uuid;
const char *member_session_uuid;
const char *queue_name;
const char *queue_strategy;
const char *member_joined_epoch;
const char *member_caller_name;
const char *member_caller_number;
const char *member_cid_name;
const char *member_cid_number;
const char *agent_name;
const char *agent_system;
const char *agent_status;
@@ -1356,7 +1358,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
char *sql = NULL;
char *dialstr = NULL;
cc_tier_state_t tiers_state = CC_TIER_STATE_READY;
switch_core_session_t *member_session = switch_core_session_locate(h->member_uuid);
switch_core_session_t *member_session = switch_core_session_locate(h->member_session_uuid);
switch_event_t *ovars;
switch_time_t t_agent_called = 0;
switch_time_t t_agent_answered = 0;
@@ -1369,7 +1371,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
/* member is gone before we could process it */
if (!member_session) {
sql = switch_mprintf("UPDATE members SET state = '%q', uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q' AND state != '%q'",
sql = switch_mprintf("UPDATE members SET state = '%q', session_uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q' AND state != '%q'",
cc_member_state2str(CC_MEMBER_STATE_ABANDONED), (long) switch_epoch_time_now(NULL), h->member_uuid, cc_member_state2str(CC_MEMBER_STATE_ABANDONED));
cc_execute_sql(NULL, sql, NULL);
@@ -1384,9 +1386,10 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Type", h->agent_type);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", h->member_uuid);
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_fire(&event);
}
@@ -1395,14 +1398,16 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_queue", "%s", h->queue_name);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_uuid", "%s", h->member_uuid);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_session_uuid", "%s", h->member_session_uuid);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_pre_answer_uuid", "%s", h->member_uuid);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent", "%s", h->agent_name);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent_type", "%s", h->agent_type);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_side", "%s", "agent");
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "ignore_early_media", "true");
t_agent_called = switch_epoch_time_now(NULL);
dialstr = switch_mprintf("%s", h->originate_string);
status = switch_ivr_originate(NULL, &agent_session, &cause, dialstr, 60, NULL, h->member_caller_name, h->member_caller_number, NULL, ovars, SOF_NONE, NULL);
status = switch_ivr_originate(NULL, &agent_session, &cause, dialstr, 60, NULL, h->member_cid_name, h->member_cid_number, NULL, ovars, SOF_NONE, NULL);
switch_safe_free(dialstr);
switch_event_destroy(&ovars);
@@ -1414,10 +1419,12 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_t *event;
const char *cc_warning_tone = switch_channel_get_variable(agent_channel, "cc_warning_tone");
switch_channel_set_variable(agent_channel, "cc_side", "agent");
switch_channel_set_variable(agent_channel, "cc_queue", h->queue_name);
switch_channel_set_variable(agent_channel, "cc_agent", h->agent_name);
switch_channel_set_variable(agent_channel, "cc_agent_type", h->agent_type);
switch_channel_set_variable(agent_channel, "cc_member_uuid", h->member_uuid);
switch_channel_set_variable(agent_channel, "cc_member_session_uuid", h->member_session_uuid);
/* Playback this to the agent */
if (cc_warning_tone && switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
@@ -1449,8 +1456,10 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
/* Loopback special case */
if (other_loopback_leg_uuid) {
switch_core_session_t *other_loopback_session = switch_core_session_locate(other_loopback_leg_uuid);
if (other_loopback_session) {
switch_core_session_t *other_loopback_session = NULL;
switch_yield(20000); // Wait 20ms for the channel to be ready
if ((other_loopback_session = switch_core_session_locate(other_loopback_leg_uuid))) {
switch_channel_t *other_loopback_channel = switch_core_session_get_channel(other_loopback_session);
const char *real_uuid = switch_channel_get_variable(other_loopback_channel, SWITCH_SIGNAL_BOND_VARIABLE);
@@ -1459,14 +1468,15 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
/* Switch the agent session */
if (real_uuid) {
switch_core_session_rwunlock(agent_session);
agent_uuid = real_uuid;
agent_session = switch_core_session_locate(agent_uuid);
agent_session = switch_core_session_locate(real_uuid);
agent_uuid = switch_core_session_get_uuid(agent_session);
agent_channel = switch_core_session_get_channel(agent_session);
switch_channel_set_variable(agent_channel, "cc_queue", h->queue_name);
switch_channel_set_variable(agent_channel, "cc_agent", h->agent_name);
switch_channel_set_variable(agent_channel, "cc_agent_type", h->agent_type);
switch_channel_set_variable(agent_channel, "cc_member_uuid", h->member_uuid);
switch_channel_set_variable(agent_channel, "cc_member_session_uuid", h->member_session_uuid);
}
switch_core_session_rwunlock(other_loopback_session);
}
@@ -1508,10 +1518,11 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-UUID", agent_uuid);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Called-Time", "%ld", (long) t_agent_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answered-Time", "%ld", (long) t_agent_answered);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Member-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", h->member_uuid);
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_fire(&event);
}
/* for xml_cdr needs */
@@ -1541,8 +1552,8 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Agent %s answered \"%s\" <%s> from queue %s%s\n",
h->agent_name, h->member_caller_name, h->member_caller_number, h->queue_name, (h->record_template?" (Recorded)":""));
switch_ivr_uuid_bridge(h->member_uuid, switch_core_session_get_uuid(agent_session));
h->agent_name, h->member_cid_name, h->member_cid_number, h->queue_name, (h->record_template?" (Recorded)":""));
switch_ivr_uuid_bridge(h->member_session_uuid, switch_core_session_get_uuid(agent_session));
/* This is used for the waiting caller to quit waiting for a agent */
switch_channel_set_variable(member_channel, "cc_agent_uuid", agent_uuid);
@@ -1563,11 +1574,12 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-UUID", agent_uuid);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Called-Time", "%ld", (long) t_agent_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answered-Time", "%ld", (long) t_agent_answered);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Member-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Bridge-Terminated-Time", "%ld", (long) switch_epoch_time_now(NULL));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", h->member_uuid);
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_fire(&event);
}
/* for xml_cdr needs */
@@ -1597,11 +1609,12 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-UUID", agent_uuid);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Called-Time", "%ld", (long) t_agent_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answered-Time", "%ld", (long) t_agent_answered);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Leaving-Time", "%ld", (long) switch_epoch_time_now(NULL));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Member-Leaving-Time", "%ld", (long) switch_epoch_time_now(NULL));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Member-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", h->member_uuid);
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_fire(&event);
}
@@ -1667,9 +1680,10 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Hangup-Cause", switch_channel_cause2str(cause));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", h->member_uuid);
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_fire(&event);
}
@@ -1711,10 +1725,12 @@ done:
struct agent_callback {
const char *queue_name;
const char *system;
const char *uuid;
const char *caller_number;
const char *caller_name;
const char *joined_epoch;
const char *member_uuid;
const char *member_session_uuid;
const char *member_cid_number;
const char *member_cid_name;
const char *member_joined_epoch;
const char *member_score;
const char *strategy;
const char *record_template;
switch_bool_t tier_rules_apply;
@@ -1733,15 +1749,23 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
agent_callback_t *cbt = (agent_callback_t *) pArg;
char *sql = NULL;
char res[256];
char *agent_status = argv[2];
char *agent_tier_state = argv[9];
char *agent_last_bridge_end = argv[10];
char *agent_wrap_up_time = argv[11];
char *agent_state = argv[12];
char *agent_ready_time = argv[13];
char *agent_tier_level = argv[14];
char *agent_type = argv[15];
char *agent_uuid = argv[16];
const char *agent_system = argv[0];
const char *agent_name = argv[1];
const char *agent_status = argv[2];
const char *agent_originate_string = argv[3];
const char *agent_no_answer_count = argv[4];
const char *agent_max_no_answer = argv[5];
const char *agent_reject_delay_time = argv[6];
const char *agent_busy_delay_time = argv[7];
const char *agent_no_answer_delay_time = argv[8];
const char *agent_tier_state = argv[9];
const char *agent_last_bridge_end = argv[10];
const char *agent_wrap_up_time = argv[11];
const char *agent_state = argv[12];
const char *agent_ready_time = argv[13];
const char *agent_tier_level = argv[14];
const char *agent_type = argv[15];
const char *agent_uuid = argv[16];
switch_bool_t contact_agent = SWITCH_TRUE;
@@ -1754,11 +1778,11 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
if (cbt->tier_rule_no_agent_no_wait == SWITCH_TRUE && cbt->tier_agent_available == 0) {
cbt->tier = atoi(agent_tier_level);
/* Multiple the tier level by the tier wait time */
} else if (cbt->tier_rule_wait_multiply_level == SWITCH_TRUE && (long) switch_epoch_time_now(NULL) - atol(cbt->joined_epoch) >= atoi(agent_tier_level) * cbt->tier_rule_wait_second) {
} else if (cbt->tier_rule_wait_multiply_level == SWITCH_TRUE && (long) switch_epoch_time_now(NULL) - atol(cbt->member_joined_epoch) >= atoi(agent_tier_level) * cbt->tier_rule_wait_second) {
cbt->tier = atoi(agent_tier_level);
cbt->tier_agent_available = 0;
/* Just check if joined is bigger than next tier wait time */
} else if (cbt->tier_rule_wait_multiply_level == SWITCH_FALSE && (long) switch_epoch_time_now(NULL) - atol(cbt->joined_epoch) >= cbt->tier_rule_wait_second) {
} else if (cbt->tier_rule_wait_multiply_level == SWITCH_FALSE && (long) switch_epoch_time_now(NULL) - atol(cbt->member_joined_epoch) >= cbt->tier_rule_wait_second) {
cbt->tier = atoi(agent_tier_level);
cbt->tier_agent_available = 0;
} else {
@@ -1790,7 +1814,7 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
}
/* If agent isn't on this box */
if (strcasecmp(argv[0],"single_box" /* SELF */)) {
if (strcasecmp(agent_system,"single_box" /* SELF */)) {
if (!strcasecmp(cbt->strategy, "ring-all")) {
return 1; /* Abort finding agent for member if we found a match but for a different Server */
} else {
@@ -1800,7 +1824,7 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
if (!strcasecmp(cbt->strategy,"ring-all")) {
/* Check if member is a ring-all mode */
sql = switch_mprintf("SELECT count(*) FROM members WHERE serving_agent = 'ring-all' AND uuid = '%q' AND system = 'single_box'", cbt->uuid);
sql = switch_mprintf("SELECT count(*) FROM members WHERE serving_agent = 'ring-all' AND uuid = '%q' AND system = 'single_box'", cbt->member_uuid);
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
switch_safe_free(sql);
@@ -1808,14 +1832,14 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
/* Map the Agent to the member */
sql = switch_mprintf("UPDATE members SET serving_agent = '%q', serving_system = 'single_box', state = '%q'"
" WHERE state = '%q' AND uuid = '%q' AND system = 'single_box'",
argv[1], cc_member_state2str(CC_MEMBER_STATE_TRYING),
cc_member_state2str(CC_MEMBER_STATE_WAITING), cbt->uuid);
agent_name, cc_member_state2str(CC_MEMBER_STATE_TRYING),
cc_member_state2str(CC_MEMBER_STATE_WAITING), cbt->member_uuid);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
/* Check if we won the race to get the member to our selected agent (Used for Multi system purposes) */
sql = switch_mprintf("SELECT count(*) FROM members WHERE serving_agent = '%q' AND serving_system = 'single_box' AND uuid = '%q' AND system = 'single_box'",
argv[1], cbt->uuid);
agent_name, cbt->member_uuid);
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
switch_safe_free(sql);
}
@@ -1834,24 +1858,25 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
switch_core_new_memory_pool(&pool);
h = switch_core_alloc(pool, sizeof(*h));
h->pool = pool;
h->member_uuid = switch_core_strdup(h->pool, cbt->uuid);
h->member_uuid = switch_core_strdup(h->pool, cbt->member_uuid);
h->member_session_uuid = switch_core_strdup(h->pool, cbt->member_session_uuid);
h->queue_strategy = switch_core_strdup(h->pool, cbt->strategy);
h->originate_string = switch_core_strdup(h->pool, argv[3]);
h->agent_name = switch_core_strdup(h->pool, argv[1]);
h->originate_string = switch_core_strdup(h->pool, agent_originate_string);
h->agent_name = switch_core_strdup(h->pool, agent_name);
h->agent_system = switch_core_strdup(h->pool, "single_box");
h->agent_status = switch_core_strdup(h->pool, argv[2]);
h->agent_status = switch_core_strdup(h->pool, agent_status);
h->agent_type = switch_core_strdup(h->pool, agent_type);
h->agent_uuid = switch_core_strdup(h->pool, agent_uuid);
h->member_joined_epoch = switch_core_strdup(h->pool, cbt->joined_epoch);
h->member_caller_name = switch_core_strdup(h->pool, cbt->caller_name);
h->member_caller_number = switch_core_strdup(h->pool, cbt->caller_number);
h->member_joined_epoch = switch_core_strdup(h->pool, cbt->member_joined_epoch);
h->member_cid_name = switch_core_strdup(h->pool, cbt->member_cid_name);
h->member_cid_number = switch_core_strdup(h->pool, cbt->member_cid_number);
h->queue_name = switch_core_strdup(h->pool, cbt->queue_name);
h->record_template = switch_core_strdup(h->pool, cbt->record_template);
h->no_answer_count = atoi(argv[4]);
h->max_no_answer = atoi(argv[5]);
h->reject_delay_time = atoi(argv[6]);
h->busy_delay_time = atoi(argv[7]);
h->no_answer_delay_time = atoi(argv[8]);
h->no_answer_count = atoi(agent_no_answer_count);
h->max_no_answer = atoi(agent_max_no_answer);
h->reject_delay_time = atoi(agent_reject_delay_time);
h->busy_delay_time = atoi(agent_busy_delay_time);
h->no_answer_delay_time = atoi(agent_no_answer_delay_time);
cc_agent_update("state", cc_agent_state2str(CC_AGENT_STATE_RECEIVING), h->agent_name);
@@ -1895,9 +1920,22 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
uint32_t discard_abandoned_after;
switch_bool_t abandoned_resume_allowed;
agent_callback_t cbt;
const char *member_state = NULL;
const char *member_abandoned_epoch = NULL;
memset(&cbt, 0, sizeof(cbt));
if (!argv[0] || !(queue = get_queue(argv[0]))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found locally, skip this member\n", argv[0]);
cbt.queue_name = argv[0];
cbt.member_uuid = argv[1];
cbt.member_session_uuid = argv[2];
cbt.member_cid_number = argv[3];
cbt.member_cid_name = argv[4];
cbt.member_joined_epoch = argv[5];
cbt.member_score = argv[6];
member_state = argv[7];
member_abandoned_epoch = argv[8];
if (!cbt.queue_name || !(queue = get_queue(cbt.queue_name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found locally, skip this member\n", cbt.queue_name);
goto end;
} else {
queue_name = strdup(queue->name);
@@ -1915,21 +1953,27 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
queue_rwunlock(queue);
}
if (!strcasecmp(argv[6], cc_member_state2str(CC_MEMBER_STATE_ABANDONED))) {
long abandoned_epoch = atol(argv[7]);
/* Checking for cleanup Abandonded calls from the db */
if (!strcasecmp(member_state, cc_member_state2str(CC_MEMBER_STATE_ABANDONED))) {
long abandoned_epoch = atol(member_abandoned_epoch);
if (abandoned_epoch == 0) {
abandoned_epoch = atol(argv[4]);
abandoned_epoch = atol(cbt.member_joined_epoch);
}
/* Once we pass a certain point, we want to get rid of the abandoned call */
if (abandoned_epoch + discard_abandoned_after < (long) switch_epoch_time_now(NULL)) {
sql = switch_mprintf("DELETE FROM members WHERE system = 'single_box' AND uuid = '%q' AND (abandoned_epoch = '%ld' OR joined_epoch = '%q')", argv[1], abandoned_epoch, argv[4]);
sql = switch_mprintf("DELETE FROM members WHERE system = 'single_box' AND uuid = '%q' AND (abandoned_epoch = '%ld' OR joined_epoch = '%q')", cbt.member_uuid, abandoned_epoch, cbt.member_joined_epoch);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
}
/* Skip this member */
goto end;
}
memset(&cbt, 0, sizeof(cbt));
/* Check if member is in the queue waiting */
if (zstr(cbt.member_session_uuid)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Member %s <%s> in Queue %s have no session uuid, skip this member\n", cbt.member_cid_name, cbt.member_cid_number, cbt.queue_name);
}
cbt.tier = 0;
cbt.tier_agent_available = 0;
@@ -1938,11 +1982,6 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
cbt.tier_rule_wait_multiply_level = tier_rule_wait_multiply_level;
cbt.tier_rule_no_agent_no_wait = tier_rule_no_agent_no_wait;
cbt.uuid = argv[1];
cbt.caller_number = argv[2];
cbt.caller_name = argv[3];
cbt.joined_epoch = argv[4];
cbt.queue_name = argv[0];
cbt.strategy = queue_strategy;
cbt.record_template = queue_record_template;
cbt.agent_found = SWITCH_FALSE;
@@ -1955,7 +1994,7 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
sql_order_by = switch_mprintf("level, agents.calls_answered, position");
} else if (!strcasecmp(queue_strategy, "ring-all")) {
sql = switch_mprintf("UPDATE members SET state = '%q' WHERE state = '%q' AND uuid = '%q' AND system = 'single_box'",
cc_member_state2str(CC_MEMBER_STATE_TRYING), cc_member_state2str(CC_MEMBER_STATE_WAITING), cbt.uuid);
cc_member_state2str(CC_MEMBER_STATE_TRYING), cc_member_state2str(CC_MEMBER_STATE_WAITING), cbt.member_uuid);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
sql_order_by = switch_mprintf("level, position");
@@ -1980,8 +2019,8 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
switch_safe_free(sql_order_by);
/* We update a field in the queue struct so we can kick caller out if waiting for too long with no agent */
if (!argv[0] || !(queue = get_queue(argv[0]))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found locally, skip this member\n", argv[0]);
if (!cbt.queue_name || !(queue = get_queue(cbt.queue_name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found locally, skip this member\n", cbt.queue_name);
goto end;
} else {
queue->last_agent_exist_check = switch_epoch_time_now(NULL);
@@ -2023,7 +2062,7 @@ void *SWITCH_THREAD_FUNC cc_agent_dispatch_thread_run(switch_thread_t *thread, v
while (globals.running == 1) {
char *sql = NULL;
sql = switch_mprintf("SELECT queue,uuid,caller_number,caller_name,joined_epoch,(%ld-joined_epoch)+base_score+skill_score AS score, state, abandoned_epoch FROM members"
sql = switch_mprintf("SELECT queue,uuid,session_uuid,cid_number,cid_name,joined_epoch,(%ld-joined_epoch)+base_score+skill_score AS score, state, abandoned_epoch FROM members"
" WHERE state = '%q' OR state = '%q' OR (serving_agent = 'ring-all' AND state = '%q') ORDER BY score DESC",
(long) switch_epoch_time_now(NULL),
cc_member_state2str(CC_MEMBER_STATE_WAITING), cc_member_state2str(CC_MEMBER_STATE_ABANDONED), cc_member_state2str(CC_MEMBER_STATE_TRYING));
@@ -2071,8 +2110,9 @@ void cc_agent_dispatch_thread_start(void)
}
struct member_thread_helper {
const char *member_uuid;
const char *queue_name;
const char *member_uuid;
const char *member_session_uuid;
switch_time_t t_member_called;
cc_member_cancel_reason_t member_cancel_reason;
@@ -2083,7 +2123,7 @@ struct member_thread_helper {
void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj)
{
struct member_thread_helper *m = (struct member_thread_helper *) obj;
switch_core_session_t *member_session = switch_core_session_locate(m->member_uuid);
switch_core_session_t *member_session = switch_core_session_locate(m->member_session_uuid);
switch_channel_t *member_channel = NULL;
switch_mutex_lock(globals.mutex);
@@ -2148,8 +2188,8 @@ void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj
}
struct moh_dtmf_helper {
const char *queue_name;
char dtmf;
const char *queue_name;
char dtmf;
};
static switch_status_t moh_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen) {
@@ -2186,7 +2226,7 @@ SWITCH_STANDARD_APP(callcenter_function)
switch_core_session_t *member_session = session;
switch_channel_t *member_channel = switch_core_session_get_channel(member_session);
char *sql = NULL;
char *member_uuid = switch_core_session_get_uuid(member_session);
char *member_session_uuid = switch_core_session_get_uuid(member_session);
struct member_thread_helper *h = NULL;
switch_thread_t *thread;
switch_threadattr_t *thd_attr = NULL;
@@ -2201,6 +2241,8 @@ SWITCH_STANDARD_APP(callcenter_function)
switch_time_t t_member_called = switch_epoch_time_now(NULL);
long abandoned_epoch = 0;
const char *agent_uuid = NULL;
switch_uuid_t smember_uuid;
char member_uuid[SWITCH_UUID_FORMATTED_LENGTH + 1] = "";
if (!zstr(data)) {
mydata = switch_core_session_strdup(member_session, data);
@@ -2231,13 +2273,29 @@ SWITCH_STANDARD_APP(callcenter_function)
char res[256];
/* Check to see if agent already exist */
sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE queue = '%q' AND caller_number = '%q' AND state = '%q' ORDER BY abandoned_epoch DESC",
sql = switch_mprintf("SELECT uuid FROM members WHERE queue = '%q' AND cid_number = '%q' AND state = '%q' ORDER BY abandoned_epoch DESC",
queue_name, switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")), cc_member_state2str(CC_MEMBER_STATE_ABANDONED));
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
switch_safe_free(sql);
abandoned_epoch = atol(res);
strncpy(member_uuid, res, sizeof(member_uuid));
if (!zstr(member_uuid)) {
sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE uuid = '%q'", member_uuid);
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
switch_safe_free(sql);
abandoned_epoch = atol(res);
}
}
/* If no existing uuid is restored, let create a new one */
if (abandoned_epoch == 0) {
switch_uuid_get(&smember_uuid);
switch_uuid_format(member_uuid, &smember_uuid);
}
switch_channel_set_variable(member_channel, "cc_side", "member");
switch_channel_set_variable(member_channel, "cc_member_uuid", member_uuid);
/* Add manually imported score */
if (cc_base_score) {
cc_base_score_int += atoi(cc_base_score);
@@ -2252,9 +2310,10 @@ SWITCH_STANDARD_APP(callcenter_function)
switch_channel_event_set_data(member_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-%s", (abandoned_epoch==0?"start":"resume"));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-Session-UUID", member_session_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
switch_event_fire(&event);
}
/* for xml_cdr needs */
@@ -2264,10 +2323,11 @@ SWITCH_STANDARD_APP(callcenter_function)
if (abandoned_epoch == 0) {
/* Add the caller to the member queue */
sql = switch_mprintf("INSERT INTO members"
" (queue,system,uuid,system_epoch,joined_epoch,base_score,skill_score,caller_number,caller_name,serving_agent,serving_system,state)"
" VALUES('%q','single_box','%q','%q','%ld','%d','%d','%q','%q','%q','','%q')",
" (queue,system,uuid,session_uuid,system_epoch,joined_epoch,base_score,skill_score,cid_number,cid_name,serving_agent,serving_system,state)"
" VALUES('%q','single_box','%q','%q','%q','%ld','%d','%d','%q','%q','%q','','%q')",
queue_name,
member_uuid,
member_session_uuid,
start_epoch,
(long) switch_epoch_time_now(NULL),
cc_base_score_int,
@@ -2281,18 +2341,20 @@ SWITCH_STANDARD_APP(callcenter_function)
} else {
char res[256];
/* Update abandoned member */
sql = switch_mprintf("UPDATE members SET uuid = '%q', state = '%q', rejoined_epoch = '%ld' WHERE caller_number = '%q' AND abandoned_epoch = '%ld' AND state = '%q' AND queue = '%q'",
member_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), (long) switch_epoch_time_now(NULL), switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")), abandoned_epoch, cc_member_state2str(CC_MEMBER_STATE_ABANDONED), queue_name);
sql = switch_mprintf("UPDATE members SET session_uuid = '%q', state = '%q', rejoined_epoch = '%ld' WHERE uuid = '%q' AND state = '%q'",
member_session_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), (long) switch_epoch_time_now(NULL), member_uuid, cc_member_state2str(CC_MEMBER_STATE_ABANDONED));
cc_execute_sql(queue, sql, NULL);
switch_safe_free(sql);
/* Confirm we took that member in */
sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE uuid = '%q' AND state = '%q' AND queue = '%q'", member_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), queue_name);
sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE uuid = '%q' AND session_uuid = '%q' AND state = '%q' AND queue = '%q'", member_session, member_session_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), queue_name);
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
switch_safe_free(sql);
if (atol(res) == 0) {
/* Failed to get the member !!! */
/* TODO Loop back to just create a uuid and add the member as a new member */
/* TODO ERROR MSG */
queue_rwunlock(queue);
goto end;
}
@@ -2308,6 +2370,7 @@ SWITCH_STANDARD_APP(callcenter_function)
h->pool = pool;
h->member_uuid = switch_core_strdup(h->pool, member_uuid);
h->member_session_uuid = switch_core_strdup(h->pool, member_session_uuid);
h->queue_name = switch_core_strdup(h->pool, queue_name);
h->t_member_called = t_member_called;
h->member_cancel_reason = CC_MEMBER_CANCEL_REASON_NONE;
@@ -2374,7 +2437,7 @@ SWITCH_STANDARD_APP(callcenter_function)
/* Canceled for some reason */
if (!switch_channel_up(member_channel) || h->member_cancel_reason != CC_MEMBER_CANCEL_REASON_NONE) {
/* Update member state */
sql = switch_mprintf("UPDATE members SET state = '%q', uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'",
sql = switch_mprintf("UPDATE members SET state = '%q', session_uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'",
cc_member_state2str(CC_MEMBER_STATE_ABANDONED), (long) switch_epoch_time_now(NULL), member_uuid);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
@@ -2387,13 +2450,14 @@ SWITCH_STANDARD_APP(callcenter_function)
switch_channel_event_set_data(member_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-end");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Leaving-Time", "%ld", (long) switch_epoch_time_now(NULL));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Member-Leaving-Time", "%ld", (long) switch_epoch_time_now(NULL));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Member-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", "Cancel");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cancel-Reason", cc_member_cancel_reason2str(h->member_cancel_reason));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-Session-UUID", member_session_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
switch_event_fire(&event);
}
@@ -116,6 +116,59 @@ static switch_status_t select_url(const char *user,
return SWITCH_STATUS_SUCCESS;
}
#define SAY_STRING_SYNTAX "<module_name>[.<ext>] <lang>[.<ext>] <say_type> <say_method> [<say_gender>] <text>"
SWITCH_STANDARD_API(say_string_function)
{
char *argv[6] = { 0 };
int argc;
char *lbuf = NULL, *string = NULL;
int err = 1, par = 0;
char *p, *ext = "wav";
if (cmd) {
lbuf = strdup(cmd);
}
if (lbuf && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) && (argc == 5 || argc == 6)) {
if ((p = strchr(argv[0], '.'))) {
*p++ = '\0';
ext = p;
par++;
}
if (!par && (p = strchr(argv[1], '.'))) {
*p++ = '\0';
ext = p;
}
switch_ivr_say_string(session,
argv[1],
ext,
(argc == 5) ? argv[4] : argv[5],
argv[0],
argv[2],
argv[3],
(argc == 6) ? argv[4] : NULL ,
&string);
if (string) {
stream->write_function(stream, "%s", string);
free(string);
err = 0;
}
}
if (err) {
stream->write_function(stream, "-ERR Usage: %s\n", SAY_STRING_SYNTAX);
}
free(lbuf);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_API(reg_url_function)
{
char *data;
@@ -276,6 +329,7 @@ SWITCH_STANDARD_API(nat_map_function)
switch_port_t external_port = 0;
char *tmp = NULL;
switch_bool_t sticky = SWITCH_FALSE;
switch_bool_t mapping = SWITCH_TRUE;
if (!cmd) {
goto usage;
@@ -310,6 +364,24 @@ SWITCH_STANDARD_API(nat_map_function)
goto ok;
}
if (argc < 2) {
goto usage;
}
if (argv[0] && switch_stristr("mapping", argv[0])) {
if (argv[1] && switch_stristr("enable", argv[1])) {
mapping = SWITCH_TRUE;
} else if (argv[1] && switch_stristr("disable", argv[1])) {
mapping = SWITCH_FALSE;
}
switch_nat_set_mapping(mapping);
tmp = switch_nat_status();
stream->write_function(stream, tmp);
switch_safe_free(tmp);
goto ok;
}
if (argc < 3) {
goto error;
}
@@ -342,7 +414,7 @@ SWITCH_STANDARD_API(nat_map_function)
goto ok;
usage:
stream->write_function(stream, "USAGE: nat_map [status|reinit|republish] | [add|del] <port> [tcp|udp] [sticky]");
stream->write_function(stream, "USAGE: nat_map [status|reinit|republish] | [add|del] <port> [tcp|udp] [sticky] | [mapping] <enable|disable>");
ok:
@@ -4843,6 +4915,87 @@ end:
return SWITCH_STATUS_SUCCESS;
}
#define LIMIT_SYNTAX "<uuid> <backend> <realm> <resource> [<max>[/interval]] [number [dialplan [context]]]"
SWITCH_STANDARD_API(uuid_limit_function)
{
int argc = 0;
char *argv[8] = { 0 };
char *mydata = NULL;
char *realm = NULL;
char *resource = NULL;
char *xfer_exten = NULL;
int max = -1;
int interval = 0;
switch_core_session_t *sess = NULL;
switch_status_t res = SWITCH_STATUS_SUCCESS;
if (!zstr(cmd)) {
mydata = strdup(cmd);
switch_assert(mydata);
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
}
if (argc < 4) {
stream->write_function(stream, "USAGE: uuid_limit %s\n", LIMIT_SYNTAX);
goto end;
}
realm = argv[2];
resource = argv[3];
/* If max is omitted or negative, only act as a counter and skip maximum checks */
if (argc > 4) {
if (argv[4][0] == '-') {
max = -1;
} else {
char *szinterval = NULL;
if ((szinterval = strchr(argv[4], '/'))) {
*szinterval++ = '\0';
interval = atoi(szinterval);
}
max = atoi(argv[4]);
if (max < 0) {
max = 0;
}
}
}
if (argc > 5) {
xfer_exten = argv[5];
} else {
xfer_exten = LIMIT_DEF_XFER_EXTEN;
}
sess = switch_core_session_locate(argv[0]);
if (!sess) {
stream->write_function(stream, "-ERR did not find a session with uuid %s\n", argv[0]);
goto end;
}
res = switch_limit_incr(argv[1], sess, realm, resource, max, interval);
if (res != SWITCH_STATUS_SUCCESS) {
/* Limit exceeded */
if (*xfer_exten == '!') {
switch_channel_t *channel = switch_core_session_get_channel(sess);
switch_channel_hangup(channel, switch_channel_str2cause(xfer_exten + 1));
} else {
switch_ivr_session_transfer(sess, xfer_exten, argv[6], argv[7]);
}
}
switch_core_session_rwunlock(sess);
stream->write_function(stream, "+OK");
end:
switch_safe_free(mydata);
return SWITCH_STATUS_SUCCESS;
}
#define LIMIT_RELEASE_SYNTAX "<uuid> <backend> [realm] [resource]"
SWITCH_STANDARD_API(uuid_limit_release_function)
{
@@ -5024,6 +5177,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "reload", "Reload Module", reload_function, UNLOAD_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "reloadxml", "Reload XML", reload_xml_function, "");
SWITCH_ADD_API(commands_api_interface, "replace", "replace a string", replace_function, "<data>|<string1>|<string2>");
SWITCH_ADD_API(commands_api_interface, "say_string", "", say_string_function, SAY_STRING_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "sched_api", "Schedule an api command", sched_api_function, SCHED_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "sched_broadcast", "Schedule a broadcast event to a running call", sched_broadcast_function,
SCHED_BROADCAST_SYNTAX);
@@ -5063,6 +5217,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "uuid_getvar", "uuid_getvar", uuid_getvar_function, GETVAR_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_hold", "hold", uuid_hold_function, HOLD_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_kill", "Kill Channel", kill_function, KILL_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_limit", "Increase limit resource", uuid_limit_function, LIMIT_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_limit_release", "Release limit resource", uuid_limit_release_function, LIMIT_RELEASE_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_loglevel", "set loglevel on session", uuid_loglevel, UUID_LOGLEVEL_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_media", "media", uuid_media_function, MEDIA_SYNTAX);
@@ -5181,6 +5336,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add uuid_hold ::console::list_uuid");
switch_console_set_complete("add uuid_jitterbuffer ::console::list_uuid");
switch_console_set_complete("add uuid_kill ::console::list_uuid");
switch_console_set_complete("add uuid_limit ::console::list_uuid");
switch_console_set_complete("add uuid_limit_release ::console::list_uuid");
switch_console_set_complete("add uuid_loglevel ::console::list_uuid console");
switch_console_set_complete("add uuid_loglevel ::console::list_uuid alert");
@@ -155,7 +155,8 @@ typedef enum {
CFLAG_WAIT_MOD = (1 << 7),
CFLAG_VID_FLOOR = (1 << 8),
CFLAG_WASTE_BANDWIDTH = (1 << 9),
CFLAG_OUTCALL = (1 << 10)
CFLAG_OUTCALL = (1 << 10),
CFLAG_INHASH = (1 << 11)
} conf_flag_t;
typedef enum {
@@ -667,7 +668,7 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
lock_member(member);
switch_mutex_lock(conference->member_mutex);
switch_clear_flag(conference, CFLAG_DESTRUCT);
member->join_time = switch_epoch_time_now(NULL);
member->conference = conference;
member->next = conference->members;
@@ -1491,29 +1492,30 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
}
}
if (switch_test_flag(conference, CFLAG_DESTRUCT)) {
switch_core_timer_destroy(&timer);
switch_mutex_lock(globals.hash_mutex);
switch_core_timer_destroy(&timer);
switch_mutex_lock(globals.hash_mutex);
if (switch_test_flag(conference, CFLAG_INHASH)) {
switch_core_hash_delete(globals.conference_hash, conference->name);
switch_mutex_unlock(globals.hash_mutex);
}
switch_mutex_unlock(globals.hash_mutex);
/* Wait till everybody is out */
switch_clear_flag_locked(conference, CFLAG_RUNNING);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Lock ON\n");
switch_thread_rwlock_wrlock(conference->rwlock);
switch_thread_rwlock_unlock(conference->rwlock);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Lock OFF\n");
/* Wait till everybody is out */
switch_clear_flag_locked(conference, CFLAG_RUNNING);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Lock ON\n");
switch_thread_rwlock_wrlock(conference->rwlock);
switch_thread_rwlock_unlock(conference->rwlock);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Lock OFF\n");
if (conference->sh) {
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
switch_core_speech_close(&conference->lsh, &flags);
conference->sh = NULL;
}
if (conference->sh) {
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
switch_core_speech_close(&conference->lsh, &flags);
conference->sh = NULL;
}
if (conference->pool) {
switch_memory_pool_t *pool = conference->pool;
switch_core_destroy_memory_pool(&pool);
}
if (conference->pool) {
switch_memory_pool_t *pool = conference->pool;
switch_core_destroy_memory_pool(&pool);
}
switch_mutex_lock(globals.hash_mutex);
@@ -2557,10 +2559,6 @@ static void conference_loop_output(conference_member_t *member)
write_frame.codec = &member->write_codec;
if (!switch_test_flag(member->conference, CFLAG_ANSWERED)) {
switch_channel_answer(channel);
}
if (!restarting) {
/* Start the input thread */
launch_conference_loop_input(member, switch_core_session_get_pool(member->session));
@@ -2607,8 +2605,24 @@ static void conference_loop_output(conference_member_t *member)
}
switch_safe_free(cpstr);
}
do {
switch_ivr_sleep(member->session, 500, SWITCH_TRUE, NULL);
} while(switch_channel_up(channel) && member->conference->originating);
if (!switch_channel_ready(channel)) {
member->conference->cancel_cause = SWITCH_CAUSE_ORIGINATOR_CANCEL;
goto end;
}
conference_member_play_file(member, "tone_stream://%(500,0,640)", 0);
}
}
if (!switch_test_flag(member->conference, CFLAG_ANSWERED)) {
switch_channel_answer(channel);
}
if (restarting) {
switch_channel_clear_app_flag(channel, CF_APP_TAGGED);
@@ -2786,8 +2800,9 @@ static void conference_loop_output(conference_member_t *member)
switch_cond_next();
}
} /* Rinse ... Repeat */
} /* Rinse ... Repeat */
end:
switch_clear_flag_locked(member, MFLAG_RUNNING);
switch_core_timer_destroy(&timer);
@@ -2821,6 +2836,9 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
uint32_t rlen;
switch_size_t data_buf_len;
switch_event_t *event;
int no_data = 0;
int lead_in = 20;
switch_size_t len = 0;
data_buf_len = samples * sizeof(int16_t);
@@ -2908,9 +2926,15 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
switch_event_fire(&event);
}
while (switch_test_flag(member, MFLAG_RUNNING) && switch_test_flag(conference, CFLAG_RUNNING) && conference->count) {
switch_size_t len = 0;
len = 0;
if (lead_in) {
lead_in--;
goto loop;
}
mux_used = (uint32_t) switch_buffer_inuse(member->mux_buffer);
if (switch_test_flag(member, MFLAG_FLUSH_BUFFER)) {
@@ -2923,36 +2947,64 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
switch_clear_flag_locked(member, MFLAG_FLUSH_BUFFER);
}
again:
if (switch_test_flag((&fh), SWITCH_FILE_PAUSE)) {
switch_set_flag_locked(member, MFLAG_FLUSH_BUFFER);
} else {
if (mux_used) {
/* Flush the output buffer and write all the data (presumably muxed) to the file */
switch_mutex_lock(member->audio_out_mutex);
low_count = 0;
if ((rlen = (uint32_t) switch_buffer_read(member->mux_buffer, data_buf, data_buf_len))) {
len = (switch_size_t) rlen / sizeof(int16_t);
}
switch_mutex_unlock(member->audio_out_mutex);
}
if (len < (switch_size_t) samples) {
memset(data_buf + (len * sizeof(int16_t)), 255, ((switch_size_t) samples - len) * sizeof(int16_t));
len = (switch_size_t) samples;
}
if (!len || switch_core_file_write(&fh, data_buf, &len) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Failed\n");
switch_clear_flag_locked(member, MFLAG_RUNNING);
}
goto loop;
}
if (mux_used >= data_buf_len) {
/* Flush the output buffer and write all the data (presumably muxed) to the file */
switch_mutex_lock(member->audio_out_mutex);
low_count = 0;
if ((rlen = (uint32_t) switch_buffer_read(member->mux_buffer, data_buf, data_buf_len))) {
len = (switch_size_t) rlen / sizeof(int16_t);
no_data = 0;
}
switch_mutex_unlock(member->audio_out_mutex);
}
if (len == 0) {
mux_used = (uint32_t) switch_buffer_inuse(member->mux_buffer);
if (mux_used >= data_buf_len) {
goto again;
}
if (++no_data < 2) {
goto loop;
}
memset(data_buf, 255, (switch_size_t) data_buf_len);
len = (switch_size_t) samples;
}
if (!len || switch_core_file_write(&fh, data_buf, &len) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Failed\n");
switch_clear_flag_locked(member, MFLAG_RUNNING);
}
loop:
switch_core_timer_next(&timer);
} /* Rinse ... Repeat */
end:
for(;;) {
switch_mutex_lock(member->audio_out_mutex);
if ((rlen = (uint32_t) switch_buffer_read(member->mux_buffer, data_buf, data_buf_len))) {
len = (switch_size_t) rlen / sizeof(int16_t);
switch_core_file_write(&fh, data_buf, &len);
} else {
break;
}
switch_mutex_unlock(member->audio_out_mutex);
}
switch_safe_free(data_buf);
switch_core_timer_destroy(&timer);
conference_del_member(conference, member);
@@ -4511,18 +4563,17 @@ static switch_status_t conf_api_sub_bgdial(conference_obj_t *conference, switch_
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv)
{
switch_status_t ret_status = SWITCH_STATUS_SUCCESS;
char *conf_name = NULL, *profile_name;
switch_event_t *params = NULL;
conference_obj_t *new_conference = NULL;
int locked = 0;
switch_core_session_message_t msg = { 0 };
switch_assert(conference != NULL);
switch_assert(stream != NULL);
if (argc > 3 && !zstr(argv[2])) {
int x;
@@ -4539,124 +4590,21 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc
uint32_t id = atoi(argv[x]);
switch_channel_t *channel;
switch_event_t *event;
switch_xml_t cxml = NULL, cfg = NULL, profiles = NULL;
char *xdest = NULL;
if (!id || !(member = conference_member_get(conference, id))) {
stream->write_function(stream, "No Member %u in conference %s.\n", id, conference->name);
continue;
}
channel = switch_core_session_get_channel(member->session);
if (!new_conference) {
if (!locked) {
switch_mutex_lock(globals.setup_mutex);
locked = 1;
}
if ((new_conference = conference_find(conf_name))) {
if (locked) {
switch_mutex_unlock(globals.setup_mutex);
locked = 0;
}
}
if (!(new_conference = conference_find(conf_name))) {
/* build a new conference if it doesn't exist */
switch_memory_pool_t *pool = NULL;
conf_xml_cfg_t xml_cfg = { 0 };
/* Setup a memory pool to use. */
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Pool Failure\n");
switch_thread_rwlock_unlock(member->rwlock);
goto done;
}
switch_event_create(&params, SWITCH_EVENT_REQUEST_PARAMS);
switch_assert(params);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "conf_name", conf_name);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "profile_name", profile_name);
switch_channel_event_set_data(channel, params);
/* Open the config from the xml registry */
if (!(cxml = switch_xml_open_cfg(global_cf_name, &cfg, params))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf_name);
switch_thread_rwlock_unlock(member->rwlock);
goto done;
}
if ((profiles = switch_xml_child(cfg, "profiles"))) {
xml_cfg.profile = switch_xml_find_child(profiles, "profile", "name", profile_name);
}
/* Create the conference object. */
new_conference = conference_new(conf_name, xml_cfg, member->session, pool);
/* Release the config registry handle */
if (cxml) {
switch_xml_free(cxml);
cxml = NULL;
}
if (!new_conference) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
if (pool != NULL) {
switch_core_destroy_memory_pool(&pool);
}
switch_thread_rwlock_unlock(member->rwlock);
goto done;
}
if (locked) {
switch_mutex_unlock(globals.setup_mutex);
locked = 0;
}
/* Set the minimum number of members (once you go above it you cannot go below it) */
new_conference->min = 1;
/* Indicate the conference is dynamic */
switch_set_flag_locked(new_conference, CFLAG_DYNAMIC);
switch_mutex_lock(new_conference->mutex);
/* Start the conference thread for this conference */
launch_conference_thread(new_conference);
} else {
switch_mutex_lock(new_conference->mutex);
}
}
/* move the member from the old conference to the new one */
lock_member(member);
switch_thread_rwlock_unlock(member->rwlock);
if (conference != new_conference) {
conference_del_member(conference, member);
conference_add_member(new_conference, member);
if (conference->rate != new_conference->rate) {
if (setup_media(member, new_conference)) {
switch_clear_flag_locked(member, MFLAG_RUNNING);
} else {
switch_channel_set_app_flag(channel, CF_APP_TAGGED);
switch_set_flag_locked(member, MFLAG_RESTART);
}
}
}
switch_channel_set_variable(channel, "last_transfered_conference", argv[2]);
/* Sync the recovery data */
msg.from = __FILE__;
msg.message_id = SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH;
switch_core_session_receive_message(member->session, &msg);
unlock_member(member);
xdest = switch_core_session_sprintf(member->session, "conference:%s@%s", conf_name, profile_name);
switch_ivr_session_transfer(member->session, xdest, "inline", NULL);
switch_channel_set_variable(channel, "last_transfered_conference", conf_name);
stream->write_function(stream, "OK Member '%d' sent to conference %s.\n", member->id, argv[2]);
/* tell them what happened */
if (test_eflag(conference, EFLAG_TRANSFER) &&
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
@@ -4666,30 +4614,23 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "transfer");
switch_event_fire(&event);
}
}
if (new_conference) {
switch_mutex_unlock(new_conference->mutex);
switch_thread_rwlock_unlock(member->rwlock);
}
} else {
ret_status = SWITCH_STATUS_GENERR;
}
done:
if (locked) {
switch_mutex_unlock(globals.setup_mutex);
locked = 0;
}
if (params) {
switch_event_destroy(&params);
}
switch_safe_free(conf_name);
return ret_status;
}
static switch_status_t conf_api_sub_record(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv)
{
switch_assert(conference != NULL);
@@ -5621,6 +5562,7 @@ SWITCH_STANDARD_APP(conference_function)
conf_xml_cfg_t xml_cfg = { 0 };
switch_event_t *params = NULL;
int locked = 0;
uint32_t *mid;
if (!switch_channel_test_app_flag_key("conf_silent", channel, CONF_SILENT_DONE) &&
(switch_channel_test_flag(channel, CF_RECOVERED) || switch_true(switch_channel_get_variable(channel, "conference_silent_entry")))) {
@@ -5993,8 +5935,17 @@ SWITCH_STANDARD_APP(conference_function)
goto done;
}
if (!(mid = switch_channel_get_private(channel, "__confmid"))) {
mid = switch_core_session_alloc(session, sizeof(*mid));
*mid = next_member_id();
switch_channel_set_private(channel, "__confmid", mid);
}
switch_channel_set_variable_printf(channel, "conference_member_id", "%u", *mid);
/* Prepare MUTEXS */
member.id = next_member_id();
member.id = *mid;
switch_mutex_init(&member.flag_mutex, SWITCH_MUTEX_NESTED, member.pool);
switch_mutex_init(&member.write_mutex, SWITCH_MUTEX_NESTED, member.pool);
switch_mutex_init(&member.read_mutex, SWITCH_MUTEX_NESTED, member.pool);
@@ -6219,7 +6170,13 @@ static conference_obj_t *conference_find(char *name)
conference_obj_t *conference;
switch_mutex_lock(globals.hash_mutex);
conference = switch_core_hash_find(globals.conference_hash, name);
if ((conference = switch_core_hash_find(globals.conference_hash, name))) {
if (switch_test_flag(conference, CFLAG_DESTRUCT)) {
switch_core_hash_delete(globals.conference_hash, conference->name);
switch_clear_flag(conference, CFLAG_INHASH);
conference = NULL;
}
}
switch_mutex_unlock(globals.hash_mutex);
return conference;
@@ -6669,7 +6626,9 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
switch_mutex_init(&conference->flag_mutex, SWITCH_MUTEX_NESTED, conference->pool);
switch_thread_rwlock_create(&conference->rwlock, conference->pool);
switch_mutex_init(&conference->member_mutex, SWITCH_MUTEX_NESTED, conference->pool);
switch_mutex_lock(globals.hash_mutex);
switch_set_flag(conference, CFLAG_INHASH);
switch_core_hash_insert(globals.conference_hash, conference->name, conference);
switch_mutex_unlock(globals.hash_mutex);
+255 -51
View File
@@ -29,6 +29,7 @@
* Neal Horman <neal at wanlink dot com>
* Bret McDanel <trixter AT 0xdecafbad dot com>
* Luke Dashjr <luke@openmethods.com> (OpenMethods, LLC)
* Cesar Cepeda <cesar@auronix.com>
*
* mod_dptools.c -- Raw Audio File Streaming Application Module
*
@@ -2077,7 +2078,7 @@ SWITCH_STANDARD_APP(play_and_get_digits_function)
prompt_audio_file, bad_input_audio_file, var_name, digit_buffer, sizeof(digit_buffer), digits_regex, digit_timeout);
}
#define SAY_SYNTAX "<module_name> <say_type> <say_method> [<say_gender>] <text>"
#define SAY_SYNTAX "<module_name>[:<lang>] <say_type> <say_method> [<say_gender>] <text>"
SWITCH_STANDARD_APP(say_function)
{
char *argv[5] = { 0 };
@@ -2093,6 +2094,11 @@ SWITCH_STANDARD_APP(say_function)
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
/* Set default langauge according to the <module_name> */
if (!strchr(argv[0], ':')) {
argv[0] = switch_core_session_sprintf(session, "%s:%s", argv[0], argv[0]);
}
switch_ivr_say(session, (argc == 4) ? argv[3] : argv[4], argv[0], argv[1], argv[2], (argc == 5) ? argv[3] : NULL ,&args);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", SAY_SYNTAX);
@@ -2473,6 +2479,11 @@ SWITCH_STANDARD_APP(audio_bridge_function)
{
switch_channel_t *caller_channel = switch_core_session_get_channel(session);
switch_core_session_t *peer_session = NULL;
const char *transfer_on_fail = NULL;
char *tof_data = NULL;
char *tof_array[4] = { 0 };
int tof_arrayc = 0;
const char *continue_on_fail = NULL, *failure_causes = NULL,
*v_campon = NULL, *v_campon_retries, *v_campon_sleep, *v_campon_timeout, *v_campon_fallback_exten = NULL;
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
@@ -2489,8 +2500,14 @@ SWITCH_STANDARD_APP(audio_bridge_function)
}
continue_on_fail = switch_channel_get_variable(caller_channel, "continue_on_fail");
failure_causes = switch_channel_get_variable(caller_channel, "failure_causes");
transfer_on_fail = switch_channel_get_variable(caller_channel, "transfer_on_fail");
tof_data = switch_core_session_strdup(session, transfer_on_fail);
tof_arrayc = switch_split(tof_data, ' ', tof_array);
transfer_on_fail = tof_array[0];
failure_causes = switch_channel_get_variable(caller_channel, "failure_causes");
if ((v_campon = switch_channel_get_variable(caller_channel, "campon")) && switch_true(v_campon)) {
const char *cid_name = NULL;
const char *cid_number = NULL;
@@ -2681,6 +2698,57 @@ SWITCH_STANDARD_APP(audio_bridge_function)
return;
}
}
if (transfer_on_fail || failure_causes) {
const char *cause_str;
char cause_num[35] = "";
cause_str = switch_channel_cause2str(cause);
switch_snprintf(cause_num, sizeof(cause_num), "%u", cause);
if ((tof_array[1] == NULL ) || (!strcasecmp(tof_array[1], "auto_cause"))){
tof_array[1] = (char *) cause_str;
}
if (failure_causes) {
char *lbuf = switch_core_session_strdup(session, failure_causes);
char *argv[256] = { 0 };
int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0])));
int i, x = 0;
for (i = 0; i < argc; i++) {
if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) {
x++;
break;
}
}
if (!x) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"Failure causes [%s]: Cause: %s\n", failure_causes, cause_str);
switch_ivr_session_transfer(session, tof_array[1], tof_array[2], tof_array[3]);
}
}
if (transfer_on_fail) {
if (switch_true(transfer_on_fail)) {
return;
} else {
char *lbuf = switch_core_session_strdup(session, transfer_on_fail);
char *argv[256] = { 0 };
int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0])));
int i;
for (i = 0; i < argc; i++) {
if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"Transfer on fail [%s]: Cause: %s\n", transfer_on_fail, cause_str);
switch_ivr_session_transfer(session, tof_array[1], tof_array[2], tof_array[3]);
}
}
}
}
}
}
if (!switch_channel_test_flag(caller_channel, CF_TRANSFER) && switch_channel_get_state(caller_channel) != CS_ROUTING) {
switch_channel_hangup(caller_channel, cause);
@@ -2789,7 +2857,7 @@ static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session
if ((domain = strchr(group, '@'))) {
*domain++ = '\0';
} else {
domain = switch_core_get_variable_pdup("domain", switch_core_session_get_pool(session));
domain = switch_core_get_variable_dup("domain");
dup_domain = domain;
}
@@ -2890,7 +2958,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
switch_call_cause_t *cancel_cause)
{
switch_xml_t x_domain = NULL, xml = NULL, x_user = NULL, x_group = NULL, x_param, x_params;
switch_xml_t xml = NULL, x_user = NULL, x_param, x_params;
char *user = NULL, *domain = NULL, *dup_domain = NULL;
const char *dest = NULL;
switch_call_cause_t cause = SWITCH_CAUSE_NONE;
@@ -2937,48 +3005,12 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
var_event = NULL;
}
if (switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, &x_group, params) != SWITCH_STATUS_SUCCESS) {
if (switch_xml_locate_user_merged("id", user, domain, NULL, &x_user, params) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Can't find user [%s@%s]\n", user, domain);
cause = SWITCH_CAUSE_SUBSCRIBER_ABSENT;
goto done;
}
if ((x_params = switch_xml_child(x_domain, "params"))) {
for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
const char *pvar = switch_xml_attr(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
if (!strcasecmp(pvar, "dial-string")) {
dest = val;
} else if (!strncasecmp(pvar, "dial-var-", 9)) {
if (!var_event) {
switch_event_create(&var_event, SWITCH_EVENT_GENERAL);
} else {
switch_event_del_header(var_event, pvar + 9);
}
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, pvar + 9, val);
}
}
}
if ((x_params = switch_xml_child(x_group, "params"))) {
for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
const char *pvar = switch_xml_attr(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
if (!strcasecmp(pvar, "dial-string")) {
dest = val;
} else if (!strncasecmp(pvar, "dial-var-", 9)) {
if (!var_event) {
switch_event_create(&var_event, SWITCH_EVENT_GENERAL);
} else {
switch_event_del_header(var_event, pvar + 9);
}
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, pvar + 9, val);
}
}
}
if ((x_params = switch_xml_child(x_user, "params"))) {
for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
const char *pvar = switch_xml_attr(x_param, "name");
@@ -2996,8 +3028,9 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
}
}
}
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_user", user);
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_user", user);
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
if (!dest) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No dial-string available, please check your user directory.\n");
@@ -3090,14 +3123,6 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
}
if (new_channel && xml) {
if ((x_params = switch_xml_child(x_domain, "variables"))) {
for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
const char *pvar = switch_xml_attr(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
switch_channel_set_variable(new_channel, pvar, val);
}
}
if ((x_params = switch_xml_child(x_user, "variables"))) {
for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
const char *pvar = switch_xml_attr(x_param, "name");
@@ -3463,6 +3488,173 @@ SWITCH_STANDARD_APP(limit_hash_execute_function)
}
}
/* FILE STRING INTERFACE */
/* for apr_pstrcat */
#define DEFAULT_PREBUFFER_SIZE 1024 * 64
struct file_string_source;
struct file_string_context {
char *argv[128];
int argc;
int index;
int samples;
switch_file_handle_t fh;
};
typedef struct file_string_context file_string_context_t;
static int next_file(switch_file_handle_t *handle)
{
file_string_context_t *context = handle->private_info;
char *file;
const char *prefix = handle->prefix;
top:
context->index++;
if (switch_test_flag((&context->fh), SWITCH_FILE_OPEN)) {
switch_core_file_close(&context->fh);
}
if (context->index >= context->argc) {
return 0;
}
if (!prefix) {
if (!(prefix = switch_core_get_variable_pdup("sound_prefix", handle->memory_pool))) {
prefix = SWITCH_GLOBAL_dirs.sounds_dir;
}
}
if (!prefix || switch_is_file_path(context->argv[context->index])) {
file = context->argv[context->index];
} else {
file = switch_core_sprintf(handle->memory_pool, "%s%s%s", prefix, SWITCH_PATH_SEPARATOR, context->argv[context->index]);
}
if (switch_core_file_open(&context->fh,
file, handle->channels, handle->samplerate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
goto top;
}
handle->samples = context->fh.samples;
handle->samplerate = context->fh.samplerate;
handle->channels = context->fh.channels;
handle->format = context->fh.format;
handle->sections = context->fh.sections;
handle->seekable = context->fh.seekable;
handle->speed = context->fh.speed;
handle->interval = context->fh.interval;
if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) {
switch_set_flag(handle, SWITCH_FILE_NATIVE);
} else {
switch_clear_flag(handle, SWITCH_FILE_NATIVE);
}
if (!switch_test_flag(handle, SWITCH_FILE_NATIVE)) {
if (context->index == 0) {
context->samples = (handle->samplerate / 1000) * 250;
}
}
return 1;
}
static switch_status_t file_string_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
{
file_string_context_t *context = handle->private_info;
if (samples == 0 && whence == SEEK_SET) {
context->index = -1;
return SWITCH_STATUS_SUCCESS;
}
if (!handle->seekable) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "File is not seekable\n");
return SWITCH_STATUS_NOTIMPL;
}
return switch_core_file_seek(&context->fh, cur_sample, samples, whence);
}
static switch_status_t file_string_file_open(switch_file_handle_t *handle, const char *path)
{
file_string_context_t *context;
char *file_dup;
if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "This format does not support writing!\n");
return SWITCH_STATUS_FALSE;
}
context = switch_core_alloc(handle->memory_pool, sizeof(*context));
file_dup = switch_core_strdup(handle->memory_pool, path);
context->argc = switch_separate_string(file_dup, '!', context->argv, (sizeof(context->argv) / sizeof(context->argv[0])));
context->index = -1;
handle->private_info = context;
return next_file(handle) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
}
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);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t file_string_file_read(switch_file_handle_t *handle, void *data, size_t *len)
{
file_string_context_t *context = handle->private_info;
switch_status_t status;
size_t llen = *len;
if (context->samples > 0) {
if (*len > (size_t) context->samples) {
*len = context->samples;
}
context->samples -= *len;
memset(data, 255, *len *2);
status = SWITCH_STATUS_SUCCESS;
} else {
status = switch_core_file_read(&context->fh, data, len);
}
if (status != SWITCH_STATUS_SUCCESS) {
if (!next_file(handle)) {
return SWITCH_STATUS_FALSE;
}
*len = llen;
status = switch_core_file_read(&context->fh, data, len);
}
return SWITCH_STATUS_SUCCESS;
}
/* Registration */
static char *file_string_supported_formats[SWITCH_MAX_CODECS] = { 0 };
/* /FILE STRING INTERFACE */
#define SPEAK_DESC "Speak text to a channel via the tts interface"
#define DISPLACE_DESC "Displace audio from a file to the channels input"
#define SESS_REC_DESC "Starts a background recording of the entire session"
@@ -3484,10 +3676,22 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
switch_application_interface_t *app_interface;
switch_dialplan_interface_t *dp_interface;
switch_chat_interface_t *chat_interface;
switch_file_interface_t *file_interface;
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
file_string_supported_formats[0] = "file_string";
file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
file_interface->interface_name = modname;
file_interface->extens = file_string_supported_formats;
file_interface->file_open = file_string_file_open;
file_interface->file_close = file_string_file_close;
file_interface->file_read = file_string_file_read;
file_interface->file_seek = file_string_file_seek;
error_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
error_endpoint_interface->interface_name = "error";
error_endpoint_interface->io_routines = &error_io_routines;
+2 -15
View File
@@ -1,17 +1,6 @@
# LDNS=ldns-1.6.9
# BASE=../../../..
# LDNS_DIR=$(switch_srcdir)/libs/$(LDNS)
# LDNS_BUILDDIR=$(switch_builddir)/libs/$(LDNS)
# LDNSLA=$(LDNS_BUILDDIR)/libldns.la
# include $(BASE)/build/modmake.rules
# LOCAL_LIBADD=$(LDNSLA)
BASE=../../../..
LDNS=ldns-1.6.9
LDNS=ldns
LDNS_DIR=$(switch_srcdir)/libs/$(LDNS)
LDNS_BUILDDIR=$(switch_builddir)/libs/$(LDNS)
@@ -20,9 +9,6 @@ LDNS_LA=$(LDNS_BUILDDIR)/libldns.la
LOCAL_LIBADD=$(LDNS_LA)
include $(BASE)/build/modmake.rules
$(LDNS_DIR)/Makefile.in:
$(GETLIB) $(LDNS).tar.gz
$(LDNS_BUILDDIR)/Makefile: $(LDNS_DIR)/Makefile.in
mkdir -p $(LDNS_BUILDDIR)
cd $(LDNS_BUILDDIR) && $(DEFAULT_VARS) $(LDNS_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(LDNS_DIR) --disable-gost --without-ssl --disable-sha2
@@ -32,3 +18,4 @@ $(LDNS_LA): $(LDNS_BUILDDIR)/Makefile
cd $(LDNS_BUILDDIR) && $(MAKE)
$(TOUCH_TARGET)
$(MODNAME).lo: $(LDNS_LA)
+323
View File
@@ -0,0 +1,323 @@
diff -ru b/ldns/ldns.h a/ldns/ldns.h
--- b/ldns/ldns.h 2011-03-24 20:32:30.000000000 -0500
+++ a/ldns/ldns.h 2011-03-24 20:29:03.000000000 -0500
@@ -148,6 +148,16 @@
/** EDNS flags */
extern ldns_lookup_table ldns_edns_flags[];
+
+#ifdef USE_WINSOCK
+#define SOCK_INVALID INVALID_SOCKET
+#define close_socket(_s) if (_s > SOCK_INVALID) {closesocket(_s); _s = SOCK_INVALID;}
+#else
+#define SOCK_INVALID -1
+#define close_socket(_s) if (_s > SOCK_INVALID) {close(_s); _s = SOCK_INVALID;}
+#endif
+
+
#ifdef __cplusplus
}
#endif
diff -ru b/net.c a/net.c
--- b/net.c 2011-02-11 10:50:46.000000000 -0600
+++ a/net.c 2011-03-24 20:28:15.000000000 -0500
@@ -261,12 +261,18 @@
#endif
}
+#ifndef WIN32
+#include <poll.h>
+#endif
+
/** wait for a socket to become ready */
static int
ldns_sock_wait(int sockfd, struct timeval timeout, int write)
{
- fd_set fds;
int ret;
+
+#ifdef WIN32
+ fd_set fds;
#ifndef S_SPLINT_S
FD_ZERO(&fds);
FD_SET(FD_SET_T sockfd, &fds);
@@ -275,6 +281,26 @@
ret = select(sockfd+1, NULL, &fds, NULL, &timeout);
else
ret = select(sockfd+1, &fds, NULL, NULL, &timeout);
+#else
+
+ struct pollfd pfds[2];
+ int x = 0;
+
+ memset(&pfds[0], 0, sizeof(pfds[0]) * 2);
+
+ pfds[0].fd = sockfd;
+ pfds[0].events = POLLIN|POLLERR;
+
+ if (write) {
+ pfds[0].events |= POLLOUT;
+ }
+
+ ret = poll(pfds, 1, timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
+
+#endif
+
+
+
if(ret == 0)
/* timeout expired */
return 0;
@@ -299,11 +325,7 @@
/* wait for an response*/
if(!ldns_sock_wait(sockfd, timeout, 0)) {
-#ifndef USE_WINSOCK
- close(sockfd);
-#else
- closesocket(sockfd);
-#endif
+ close_socket(sockfd);
return LDNS_STATUS_NETWORK_ERR;
}
@@ -313,11 +335,7 @@
ldns_sock_nonblock(sockfd);
answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
-#ifndef USE_WINSOCK
- close(sockfd);
-#else
- closesocket(sockfd);
-#endif
+ close_socket(sockfd);
if (*answer_size == 0) {
/* oops */
@@ -353,9 +371,10 @@
if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM,
IPPROTO_UDP))
- == -1) {
+ == SOCK_INVALID) {
return 0;
}
+
return sockfd;
}
@@ -366,20 +385,20 @@
int sockfd;
if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM,
- IPPROTO_TCP)) == -1) {
+ IPPROTO_TCP)) == SOCK_INVALID) {
return 0;
}
/* perform nonblocking connect, to be able to wait with select() */
ldns_sock_nonblock(sockfd);
- if (connect(sockfd, (struct sockaddr*)to, tolen) == -1) {
+ if (connect(sockfd, (struct sockaddr*)to, tolen) == SOCK_INVALID) {
#ifndef USE_WINSOCK
#ifdef EINPROGRESS
if(errno != EINPROGRESS) {
#else
if(1) {
#endif
- close(sockfd);
+ close_socket(sockfd);
return 0;
}
#else /* USE_WINSOCK */
@@ -398,11 +417,7 @@
socklen_t len = (socklen_t)sizeof(error);
if(!ldns_sock_wait(sockfd, timeout, 1)) {
-#ifndef USE_WINSOCK
- close(sockfd);
-#else
- closesocket(sockfd);
-#endif
+ close_socket(sockfd);
return 0;
}
@@ -421,7 +436,7 @@
continue; /* try again */
#endif
else if(error != 0) {
- close(sockfd);
+ close_socket(sockfd);
/* error in errno for our user */
errno = error;
return 0;
@@ -645,11 +660,7 @@
}
answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout);
-#ifndef USE_WINSOCK
- close(sockfd);
-#else
- closesocket(sockfd);
-#endif
+ close_socket(sockfd);
if (*answer_size == 0) {
/* oops */
@@ -782,7 +793,7 @@
* @hostname is used */
for (ns_i = 0;
ns_i < ldns_resolver_nameserver_count(resolver) &&
- resolver->_socket == 0;
+ resolver->_socket == SOCK_INVALID;
ns_i++) {
ns = ldns_rdf2native_sockaddr_storage(
resolver->_nameservers[ns_i],
@@ -792,7 +803,7 @@
ldns_resolver_timeout(resolver));
}
- if (resolver->_socket == 0) {
+ if (resolver->_socket == SOCK_INVALID) {
ldns_pkt_free(query);
LDNS_FREE(ns);
return LDNS_STATUS_NETWORK_ERR;
@@ -807,13 +818,7 @@
if (status != LDNS_STATUS_OK) {
/* RoRi: to prevent problems on subsequent calls to ldns_axfr_start
we have to close the socket here! */
-#ifndef USE_WINSOCK
- close(resolver->_socket);
-#else
- closesocket(resolver->_socket);
-#endif
- resolver->_socket = 0;
-
+ close_socket(resolver->_socket);
return LDNS_STATUS_CRYPTO_TSIG_ERR;
}
}
@@ -826,12 +831,8 @@
if(!query_wire) {
ldns_pkt_free(query);
LDNS_FREE(ns);
-#ifndef USE_WINSOCK
- close(resolver->_socket);
-#else
- closesocket(resolver->_socket);
-#endif
- resolver->_socket = 0;
+
+ close_socket(resolver->_socket);
return LDNS_STATUS_MEM_ERR;
}
@@ -843,12 +844,8 @@
/* RoRi: to prevent problems on subsequent calls to ldns_axfr_start
we have to close the socket here! */
-#ifndef USE_WINSOCK
- close(resolver->_socket);
-#else
- closesocket(resolver->_socket);
-#endif
- resolver->_socket = 0;
+
+ close_socket(resolver->_socket);
return status;
}
@@ -862,12 +859,8 @@
/* RoRi: to prevent problems on subsequent calls to ldns_axfr_start
we have to close the socket here! */
-#ifndef USE_WINSOCK
- close(resolver->_socket);
-#else
- closesocket(resolver->_socket);
-#endif
- resolver->_socket = 0;
+
+ close_socket(resolver->_socket);
return LDNS_STATUS_NETWORK_ERR;
}
diff -ru b/resolver.c a/resolver.c
--- b/resolver.c 2010-12-14 08:41:38.000000000 -0600
+++ a/resolver.c 2011-03-24 20:07:17.000000000 -0500
@@ -627,9 +627,7 @@
r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
- /* TODO: fd=0 is actually a valid socket (stdin),
- replace with -1 */
- r->_socket = 0;
+ r->_socket = -1;
r->_axfr_soa_count = 0;
r->_axfr_i = 0;
r->_cur_axfr_pkt = NULL;
@@ -903,6 +901,8 @@
size_t i;
if (res) {
+ close_socket(res->_socket);
+
if (res->_searchlist) {
for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
ldns_rdf_deep_free(res->_searchlist[i]);
@@ -1198,7 +1198,7 @@
ldns_status status;
/* check if start() has been called */
- if (!resolver || resolver->_socket == 0) {
+ if (!resolver || resolver->_socket == -1) {
return NULL;
}
@@ -1215,12 +1215,9 @@
if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
resolver->_axfr_soa_count++;
if (resolver->_axfr_soa_count >= 2) {
-#ifndef USE_WINSOCK
- close(resolver->_socket);
-#else
- closesocket(resolver->_socket);
-#endif
- resolver->_socket = 0;
+
+ close_socket(resolver->_socket);
+
ldns_pkt_free(resolver->_cur_axfr_pkt);
resolver->_cur_axfr_pkt = NULL;
}
@@ -1243,12 +1240,8 @@
/* RoRi: we must now also close the socket, otherwise subsequent uses of the
same resolver structure will fail because the link is still open or
in an undefined state */
-#ifndef USE_WINSOCK
- close(resolver->_socket);
-#else
- closesocket(resolver->_socket);
-#endif
- resolver->_socket = 0;
+
+ close_socket(resolver->_socket);
return NULL;
} else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
@@ -1258,12 +1251,8 @@
/* RoRi: we must now also close the socket, otherwise subsequent uses of the
same resolver structure will fail because the link is still open or
in an undefined state */
-#ifndef USE_WINSOCK
- close(resolver->_socket);
-#else
- closesocket(resolver->_socket);
-#endif
- resolver->_socket = 0;
+
+ close_socket(resolver->_socket);
return NULL;
} else {
@@ -42,7 +42,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;$(InputDir)..\..\..\..\libs\udns&quot;"
AdditionalIncludeDirectories="&quot;$(InputDir)..\..\..\..\libs\ldns&quot;"
UsePrecompiledHeader="0"
/>
<Tool
@@ -106,7 +106,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;$(InputDir)..\..\..\..\libs\udns&quot;"
AdditionalIncludeDirectories="&quot;$(InputDir)..\..\..\..\libs\ldns&quot;"
UsePrecompiledHeader="0"
/>
<Tool
@@ -171,7 +171,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;$(InputDir)..\..\..\..\libs\udns&quot;"
AdditionalIncludeDirectories="&quot;$(InputDir)..\..\..\..\libs\ldns&quot;"
UsePrecompiledHeader="0"
/>
<Tool
@@ -235,7 +235,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;$(InputDir)..\..\..\..\libs\udns&quot;"
AdditionalIncludeDirectories="&quot;$(InputDir)..\..\..\..\libs\ldns&quot;"
UsePrecompiledHeader="0"
/>
<Tool
@@ -66,7 +66,7 @@
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\udns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\ldns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
@@ -82,7 +82,7 @@
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\udns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\ldns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
@@ -96,7 +96,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\udns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\ldns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
@@ -112,7 +112,7 @@
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\udns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\ldns;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
@@ -128,9 +128,8 @@
<ClCompile Include="mod_enum.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\libs\win32\udns\libudns.2010.vcxproj">
<Project>{4043fc6a-9a30-4577-8ad5-9b233c9575d8}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<ProjectReference Include="..\..\..\..\libs\win32\ldns\ldns-lib\ldns-lib.2010.vcxproj">
<Project>{23b4d303-79fc-49e0-89e2-2280e7e28940}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj">
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
+34 -13
View File
@@ -30,6 +30,9 @@
*/
#include <switch.h>
#ifdef _MSC_VER
#define ssize_t int
#endif
#include <ldns/ldns.h>
SWITCH_MODULE_LOAD_FUNCTION(mod_enum_load);
@@ -141,6 +144,32 @@ static switch_status_t load_config(void)
}
done:
#ifdef _MSC_VER
if (!globals.server) {
HKEY hKey;
DWORD data_sz;
char* buf;
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
0, KEY_QUERY_VALUE, &hKey);
if (hKey) {
RegQueryValueEx(hKey, "DhcpNameServer", NULL, NULL, NULL, &data_sz);
if (data_sz) {
buf = (char*)malloc(data_sz + 1);
RegQueryValueEx(hKey, "DhcpNameServer", NULL, NULL, (LPBYTE)buf, &data_sz);
RegCloseKey(hKey);
if(buf[data_sz - 1] != 0) {
buf[data_sz] = 0;
}
globals.server = buf;
}
}
}
#endif
if (xml) {
switch_xml_free(xml);
@@ -380,9 +409,7 @@ switch_status_t ldns_lookup(const char *number, const char *root, const char *se
goto end;
}
domain = ldns_dname_new_frm_str(name);
if (!domain) {
if (!(domain = ldns_dname_new_frm_str(name))) {
goto end;
}
@@ -403,12 +430,6 @@ switch_status_t ldns_lookup(const char *number, const char *root, const char *se
goto end;
}
/* use the resolver to send a query for the naptr
* records of the domain given on the command line
*/
if ((p = ldns_resolver_query(res,
domain,
LDNS_RR_TYPE_NAPTR,
@@ -417,7 +438,7 @@ switch_status_t ldns_lookup(const char *number, const char *root, const char *se
/* retrieve the NAPTR records from the answer section of that
* packet
*/
if ((naptr = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NAPTR, LDNS_SECTION_ANSWER))) {
size_t i;
@@ -472,11 +493,10 @@ static switch_status_t enum_lookup(char *root, char *in, enum_record_t **results
root = globals.root;
}
#if 0
if (!(server = switch_core_get_variable("enum-server"))) {
server = globals.server;
}
#endif
ldns_lookup(mnum, root, server, results);
@@ -775,8 +795,9 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_enum_shutdown)
}
switch_safe_free(globals.root);
switch_safe_free(globals.server);
switch_safe_free(globals.isn_root);
return SWITCH_STATUS_UNLOAD;
}
+14 -1
View File
@@ -153,6 +153,14 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_lcr_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_lcr_shutdown);
SWITCH_MODULE_DEFINITION(mod_lcr, mod_lcr_load, mod_lcr_shutdown, NULL);
static void lcr_destroy(lcr_route route)
{
while(route) {
switch_event_destroy(&route->fields);
route=route->next;
}
}
static const char *do_cid(switch_memory_pool_t *pool, const char *cid, const char *number, switch_core_session_t *session)
{
switch_regex_t *re = NULL;
@@ -717,7 +725,7 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
end:
switch_event_destroy(&additional->fields);
/* event is freed in lcr_destroy() switch_event_destroy(&additional->fields); */
return r;
@@ -900,6 +908,7 @@ static switch_bool_t test_profile(char *lcr_profile)
routes.lookup_number = "15555551212";
routes.cid = "18005551212";
lcr_destroy(routes.head);
return (lcr_do_lookup(&routes) == SWITCH_STATUS_SUCCESS) ?
SWITCH_TRUE : SWITCH_FALSE;
}
@@ -1378,6 +1387,7 @@ static switch_call_cause_t lcr_outgoing_channel(switch_core_session_t *session,
if (mysession) {
switch_core_session_rwunlock(mysession);
}
lcr_destroy(routes.head);
switch_core_destroy_memory_pool(&pool);
switch_safe_free(dest);
@@ -1475,6 +1485,7 @@ SWITCH_STANDARD_DIALPLAN(lcr_dialplan_hunt)
}
end:
lcr_destroy(routes.head);
if (event) {
switch_event_destroy(&event);
}
@@ -1607,6 +1618,7 @@ SWITCH_STANDARD_APP(lcr_app_function)
}
end:
lcr_destroy(routes.head);
if (routes.event) {
switch_event_destroy(&event);
}
@@ -1819,6 +1831,7 @@ SWITCH_STANDARD_API(dialplan_lcr_function)
}
end:
lcr_destroy(cb_struct.head);
if (!session) {
if (pool) {
switch_core_destroy_memory_pool(&pool);
+1
View File
@@ -21,3 +21,4 @@ $(CELT_LA): $(CELT_BUILDDIR)/Makefile
cd $(CELT_BUILDDIR) && $(MAKE)
$(TOUCH_TARGET)
$(MODNAME).lo: $(CELT_LA)
+7 -3
View File
@@ -6,9 +6,9 @@ OPUS_DIR=$(switch_srcdir)/libs/$(OPUS)
OPUS_BUILDDIR=$(switch_builddir)/libs/$(OPUS)
LOCAL_CFLAGS=-I$(OPUS_DIR)/src -g -O2
IETF_LA=$(OPUS_BUILDDIR)/src/.libs/libietfcodec.a
CELT_LA=$(OPUS_BUILDDIR)/celt/libcelt/.libs/libcelt0.a
SILK_LA=$(OPUS_BUILDDIR)/silk/.libs/libSKP_SILK_SDK.a
IETF_LA=$(OPUS_BUILDDIR)/src/libietfcodec.la
CELT_LA=$(OPUS_BUILDDIR)/celt/libcelt/libcelt0.la
SILK_LA=$(OPUS_BUILDDIR)/silk/libSKP_SILK_SDK.la
LOCAL_LIBADD=$(IETF_LA) $(CELT_LA) $(SILK_LA) -lm -lz
@@ -26,3 +26,7 @@ $(IETF_LA): $(OPUS_BUILDDIR)/Makefile
cd $(OPUS_BUILDDIR) && $(MAKE)
$(TOUCH_TARGET)
$(CELT_LA): $(IETF_LA)
$(SILK_LA): $(IETF_LA)
$(MODNAME).lo: $(IETF_LA) $(CELT_LA) $(SILK_LA)
+2
View File
@@ -10,8 +10,10 @@ DING_DIR=$(BASE)/libs/libdingaling
LOCAL_CFLAGS += -I$(DING_DIR)/src -I$(BASE)/libs/iksemel/include
LOCAL_OBJS=$(DING_DIR)/src/libdingaling.o $(DING_DIR)/src/sha1.o $(IKS_LA)
LOCAL_SOURCES=$(DING_DIR)/src/libdingaling.c $(DING_DIR)/src/sha1.c
LOCAL_LDFLAGS=$(LIBGNUTLS_LIBS)
include $(BASE)/build/modmake.rules
$(IKS_LA): $(IKS_DIR) $(IKS_DIR)/.update
@cd $(IKS_DIR) && $(MAKE)
@$(TOUCH_TARGET)
+23 -30
View File
@@ -65,19 +65,20 @@ typedef enum {
TFLAG_CODEC_READY = (1 << 8),
TFLAG_TRANSPORT = (1 << 9),
TFLAG_ANSWER = (1 << 10),
TFLAG_VAD_IN = (1 << 11),
TFLAG_VAD_OUT = (1 << 12),
TFLAG_VAD = (1 << 13),
TFLAG_DO_CAND = (1 << 14),
TFLAG_DO_DESC = (1 << 15),
TFLAG_LANADDR = (1 << 16),
TFLAG_AUTO = (1 << 17),
TFLAG_DTMF = (1 << 18),
TFLAG_TIMER = (1 << 19),
TFLAG_TERM = (1 << 20),
TFLAG_TRANSPORT_ACCEPT = (1 << 21),
TFLAG_READY = (1 << 22),
TFLAG_NAT_MAP = (1 << 22)
TFLAG_VAD_NONE = (1 << 11),
TFLAG_VAD_IN = (1 << 12),
TFLAG_VAD_OUT = (1 << 13),
TFLAG_VAD = (1 << 14),
TFLAG_DO_CAND = (1 << 15),
TFLAG_DO_DESC = (1 << 16),
TFLAG_LANADDR = (1 << 17),
TFLAG_AUTO = (1 << 18),
TFLAG_DTMF = (1 << 19),
TFLAG_TIMER = (1 << 20),
TFLAG_TERM = (1 << 21),
TFLAG_TRANSPORT_ACCEPT = (1 << 22),
TFLAG_READY = (1 << 23),
TFLAG_NAT_MAP = (1 << 24)
} TFLAGS;
typedef enum {
@@ -966,7 +967,7 @@ static int do_candidates(struct private_object *tech_pvt, int force)
if (force || !switch_test_flag(tech_pvt, TFLAG_RTP_READY)) {
ldl_candidate_t cand[1];
char *advip = tech_pvt->profile->extip ? tech_pvt->profile->extip : tech_pvt->profile->ip;
char *err = NULL;
char *err = NULL, *address = NULL;
memset(cand, 0, sizeof(cand));
switch_stun_random_string(tech_pvt->local_user, 16, NULL);
@@ -975,10 +976,14 @@ static int do_candidates(struct private_object *tech_pvt, int force)
if (switch_test_flag(tech_pvt, TFLAG_LANADDR)) {
advip = tech_pvt->profile->ip;
}
address = advip;
if(address && !strncasecmp(address, "host:", 5)) {
address = address + 5;
}
cand[0].port = tech_pvt->adv_local_port;
cand[0].address = advip;
cand[0].address = address;
if (!strncasecmp(advip, "stun:", 5)) {
char *stun_ip = advip + 5;
@@ -1568,22 +1573,8 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
channel_answer_channel(session);
break;
case SWITCH_MESSAGE_INDICATE_BRIDGE:
/*
if (tech_pvt->rtp_session && switch_test_flag(tech_pvt->profile, TFLAG_TIMER)) {
switch_rtp_clear_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "De-activate timed RTP!\n");
//switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_TIMER_RECLOCK);
}
*/
break;
case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
/*
if (tech_pvt->rtp_session && switch_test_flag(tech_pvt->profile, TFLAG_TIMER)) {
switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Re-activate timed RTP!\n");
//switch_rtp_clear_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_TIMER_RECLOCK);
}
*/
break;
default:
break;
@@ -2110,8 +2101,10 @@ static void set_profile_val(mdl_profile_t *profile, char *var, char *val)
} else if (!strcasecmp(val, "both")) {
switch_set_flag(profile, TFLAG_VAD_IN);
switch_set_flag(profile, TFLAG_VAD_OUT);
} else if (!strcasecmp(val, "none")) {
switch_set_flag(profile, TFLAG_VAD_NONE);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invald option %s for VAD\n", val);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid option %s for VAD\n", val);
}
}
}
@@ -1198,14 +1198,14 @@ static switch_status_t load_config(void)
if (globals.outdev > -1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Switching to default output device\n");
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find an input device\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find an output device\n");
status = SWITCH_STATUS_GENERR;
}
}
if (globals.ringdev < 0) {
if (globals.outdev > -1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid ring device configured using output device\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid or no ring device configured, using output device as ring device\n");
globals.ringdev = globals.outdev;
}
}
+117 -2
View File
@@ -1655,6 +1655,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
const char *ip = NULL, *port = NULL;
switch_channel_set_flag(channel, CF_PROXY_MODE);
if (tech_pvt->rm_encoding) {
tech_pvt->rm_encoding = NULL;
}
sofia_glue_tech_set_local_sdp(tech_pvt, NULL, SWITCH_FALSE);
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))
@@ -3480,6 +3483,96 @@ SWITCH_STANDARD_API(sofia_count_reg_function)
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_API(sofia_username_of_function)
{
char *data;
char *user = NULL;
char *domain = NULL;
char *profile_name = NULL;
char *p;
char *reply = "";
sofia_profile_t *profile = NULL;
if (!cmd) {
stream->write_function(stream, "%s", "");
return SWITCH_STATUS_SUCCESS;
}
data = strdup(cmd);
switch_assert(data);
if ((p = strchr(data, '/'))) {
profile_name = data;
*p++ = '\0';
user = p;
} else {
user = data;
}
if ((domain = strchr(user, '@'))) {
*domain++ = '\0';
}
if (!profile_name && domain) {
profile_name = domain;
}
if (user && profile_name) {
char *sql;
if (!(profile = sofia_glue_find_profile(profile_name))) {
profile_name = domain;
domain = NULL;
}
if (!profile && profile_name) {
profile = sofia_glue_find_profile(profile_name);
}
if (profile) {
struct cb_helper_sql2str cb;
char username[256] = "";
cb.buf = username;
cb.len = sizeof(username);
if (!domain || !strchr(domain, '.')) {
domain = profile->name;
}
switch_assert(!zstr(user));
sql = switch_mprintf("select sip_username "
"from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
user, domain, domain);
switch_assert(sql);
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sql2str_callback, &cb);
switch_safe_free(sql);
if (!zstr(username)) {
stream->write_function(stream, "%s", username);
} else {
stream->write_function(stream, "");
}
reply = NULL;
}
}
if (reply) {
stream->write_function(stream, "%s", reply);
}
switch_safe_free(data);
if (profile) {
sofia_glue_release_profile(profile);
}
return SWITCH_STATUS_SUCCESS;
}
static void select_from_profile(sofia_profile_t *profile,
const char *user,
const char *domain,
@@ -3987,6 +4080,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
const char *hval = NULL;
char *not_const = NULL;
int cid_locked = 0;
switch_channel_t *o_channel = NULL;
*new_session = NULL;
@@ -4015,6 +4109,11 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
nchannel = switch_core_session_get_channel(nsession);
if (session) {
o_channel = switch_core_session_get_channel(session);
}
if ((hval = switch_event_get_header(var_event, "sip_invite_to_uri"))) {
dest_to = switch_core_session_strdup(nsession, hval);
}
@@ -4121,7 +4220,23 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
gateway_ptr->ob_calls++;
if (!zstr(gateway_ptr->from_domain) && !switch_channel_get_variable(nchannel, "sip_invite_domain")) {
switch_channel_set_variable(nchannel, "sip_invite_domain", gateway_ptr->from_domain);
if (!strcasecmp(gateway_ptr->from_domain, "auto-aleg-full")) {
const char *sip_full_from = switch_channel_get_variable(o_channel, "sip_full_from");
if (!zstr(sip_full_from)) {
switch_channel_set_variable(nchannel, "sip_force_full_from", sip_full_from);
}
} else if (!strcasecmp(gateway_ptr->from_domain, "auto-aleg-domain")) {
const char *sip_from_host = switch_channel_get_variable(o_channel, "sip_from_host");
if (!zstr(sip_from_host)) {
switch_channel_set_variable(nchannel, "sip_invite_domain", sip_from_host);
}
} else {
switch_channel_set_variable(nchannel, "sip_invite_domain", gateway_ptr->from_domain);
}
}
if (!zstr(gateway_ptr->outbound_sticky_proxy) && !switch_channel_get_variable(nchannel, "sip_route_uri")) {
@@ -4320,7 +4435,6 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
}
if (session) {
switch_channel_t *o_channel = switch_core_session_get_channel(session);
const char *vval = NULL;
if ((vval = switch_channel_get_variable(o_channel, "sip_auto_answer")) && switch_true(vval)) {
@@ -5090,6 +5204,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
switch_console_add_complete_func("::sofia::list_profile_gateway", list_profile_gateway);
SWITCH_ADD_API(api_interface, "sofia_username_of", "Sofia Username Lookup", sofia_username_of_function, "[profile/]<user>@<domain>");
SWITCH_ADD_API(api_interface, "sofia_contact", "Sofia Contacts", sofia_contact_function, "[profile/]<user>@<domain>");
SWITCH_ADD_API(api_interface, "sofia_count_reg", "Count Sofia registration", sofia_count_reg_function, "[profile/]<user>@<domain>");
SWITCH_ADD_API(api_interface, "sofia_dig", "SIP DIG", sip_dig_function, "<url>");
+2 -1
View File
@@ -564,7 +564,8 @@ struct sofia_profile {
uint32_t reg_acl_count;
char *nat_acl[SOFIA_MAX_ACL];
uint32_t nat_acl_count;
int rport_level;
int server_rport_level;
int client_rport_level;
sofia_presence_type_t pres_type;
sofia_media_options_t media_options;
uint32_t force_subscription_expires;
+55 -21
View File
@@ -76,14 +76,15 @@ void sofia_handle_sip_r_notify(switch_core_session_t *session, int status,
char const *phrase,
nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, tagi_t tags[])
{
#if 0
if (status >= 300 && sip && sip->sip_call_id) {
char *sql;
sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", sip->sip_call_id->i_id);
switch_assert(sql != NULL);
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
nua_handle_destroy(nh);
}
#endif
}
#define url_set_chanvars(session, url, varprefix) _url_set_chanvars(session, url, #varprefix "_user", #varprefix "_host", #varprefix "_port", #varprefix "_uri", #varprefix "_params")
@@ -1275,6 +1276,11 @@ static void sofia_perform_profile_start_failure(sofia_profile_t *profile, char *
}
}
/* not a static function so that it's still visible on stacktraces */
void watchdog_triggered_abort(void) {
abort();
}
#define sofia_profile_start_failure(p, xp) sofia_perform_profile_start_failure(p, xp, __FILE__, __LINE__)
@@ -1390,10 +1396,10 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread
}
if (event_fail || step_fail) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile %s: SIP STACK FAILURE DETECTED!\n"
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile %s: SIP STACK FAILURE DETECTED BY WATCHDOG!\n"
"GOODBYE CRUEL WORLD, I'M LEAVING YOU TODAY....GOODBYE, GOODBYE, GOOD BYE\n", profile->name);
switch_yield(2000000);
abort();
watchdog_triggered_abort();
}
}
@@ -1516,7 +1522,8 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
TAG_IF(sofia_test_pflag(profile, PFLAG_DISABLE_NAPTR),
NTATAG_USE_NAPTR(0)),
NTATAG_DEFAULT_PROXY(profile->outbound_proxy),
NTATAG_SERVER_RPORT(profile->rport_level),
NTATAG_SERVER_RPORT(profile->server_rport_level),
NTATAG_CLIENT_RPORT(profile->client_rport_level),
TPTAG_LOG(sofia_test_flag(profile, TFLAG_TPORT_LOG)),
TAG_IF(sofia_test_pflag(profile, PFLAG_SIPCOMPACT),
NTATAG_SIPFLAGS(MSG_DO_COMPACT)),
@@ -1579,7 +1586,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
node->nua = nua_create(profile->s_root, /* Event loop */
sofia_event_callback, /* Callback for processing events */
profile, /* Additional data to pass to callback */
NTATAG_SERVER_RPORT(profile->rport_level), NUTAG_URL(node->url), TAG_END()); /* Last tag should always finish the sequence */
NTATAG_SERVER_RPORT(profile->server_rport_level), NUTAG_URL(node->url), TAG_END()); /* Last tag should always finish the sequence */
nua_set_params(node->nua,
NUTAG_APPL_METHOD("OPTIONS"),
@@ -2342,7 +2349,6 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
}
/* you could change profile->foo here if it was a minor change like context or dialplan ... */
profile->rport_level = 1; /* default setting */
profile->acl_count = 0;
profile->reg_acl_count = 0;
profile->proxy_acl_count = 0;
@@ -2493,12 +2499,6 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
} else {
profile->dtmf_type = DTMF_NONE;
}
} else if (!strcasecmp(var, "NDLB-force-rport")) {
if (val && !strcasecmp(val, "safe")) {
profile->rport_level = 3;
} else if (switch_true(val)) {
profile->rport_level = 2;
}
} else if (!strcasecmp(var, "caller-id-type")) {
profile->cid_type = sofia_cid_name2type(val);
} else if (!strcasecmp(var, "record-template")) {
@@ -3064,7 +3064,8 @@ switch_status_t config_sofia(int reload, char *profile_name)
profile->dtmf_duration = 100;
profile->tls_version = 0;
profile->mflags = MFLAG_REFER | MFLAG_REGISTER;
profile->rport_level = 1;
profile->server_rport_level = 1;
profile->client_rport_level = 1;
sofia_set_pflag(profile, PFLAG_STUN_ENABLED);
sofia_set_pflag(profile, PFLAG_DISABLE_100REL);
profile->auto_restart = 1;
@@ -3206,9 +3207,19 @@ switch_status_t config_sofia(int reload, char *profile_name)
}
} else if (!strcasecmp(var, "NDLB-force-rport")) {
if (val && !strcasecmp(val, "safe")) {
profile->rport_level = 3;
profile->server_rport_level = 3;
profile->client_rport_level = 1;
} else if (val && !strcasecmp(val, "disabled")) {
profile->server_rport_level = 0;
profile->client_rport_level = 0;
} else if (val && !strcasecmp(val, "client-only")) {
profile->client_rport_level = 1;
} else if (val && !strcasecmp(val, "server-only")) {
profile->client_rport_level = 0;
profile->client_rport_level = 1;
} else if (switch_true(val)) {
profile->rport_level = 2;
profile->server_rport_level = 2;
profile->client_rport_level = 1;
}
} else if (!strcasecmp(var, "auto-rtp-bugs")) {
sofia_glue_parse_rtp_bugs(&profile->auto_rtp_bugs, val);
@@ -4404,7 +4415,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
if (switch_channel_test_flag(channel, CF_PROXY_MODE) ||
switch_channel_test_flag(channel, CF_PROXY_MEDIA) ||
(sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && has_t38)) {
(sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && (has_t38 || status > 299))) {
if (sofia_test_flag(tech_pvt, TFLAG_SENT_UPDATE)) {
sofia_clear_flag_locked(tech_pvt, TFLAG_SENT_UPDATE);
@@ -4413,6 +4424,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
const char *r_sdp = NULL;
switch_core_session_message_t *msg;
private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
if (sip->sip_payload && sip->sip_payload->pl_data &&
sip->sip_content_type && sip->sip_content_type->c_subtype && switch_stristr("sdp", sip->sip_content_type->c_subtype)) {
@@ -4423,9 +4435,14 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing %d %s to other leg\n", status, phrase);
if (status == 200 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && has_t38 && sip->sip_payload && sip->sip_payload->pl_data) {
if (status > 299) {
switch_channel_set_private(channel, "t38_options", NULL);
switch_channel_set_private(other_channel, "t38_options", NULL);
sofia_clear_flag(tech_pvt, TFLAG_T38_PASSTHRU);
sofia_clear_flag(other_tech_pvt, TFLAG_T38_PASSTHRU);
} else if (status == 200 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && has_t38 && sip->sip_payload && sip->sip_payload->pl_data) {
switch_t38_options_t *t38_options = sofia_glue_extract_t38_options(session, sip->sip_payload->pl_data);
if (!t38_options) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_WARNING, "%s Error parsing SDP:\n%s\n",
switch_channel_get_name(tech_pvt->channel), sip->sip_payload->pl_data);
@@ -4912,7 +4929,11 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
match = sofia_glue_negotiate_sdp(session, r_sdp);
}
if (match) {
if (!match) {
if (switch_channel_get_state(channel) != CS_NEW) {
nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
}
} else {
nua_handle_t *bnh;
sip_replaces_t *replaces;
su_home_t *home = NULL;
@@ -4920,6 +4941,8 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
sofia_set_flag_locked(tech_pvt, TFLAG_READY);
if (switch_channel_get_state(channel) == CS_NEW) {
switch_channel_set_state(channel, CS_INIT);
} else {
nua_respond(tech_pvt->nh, SIP_200_OK, TAG_END());
}
sofia_set_flag(tech_pvt, TFLAG_SDP);
if (replaces_str) {
@@ -5688,6 +5711,11 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
switch_core_event_hook_add_state_change(a_session, xfer_hanguphook);
switch_channel_set_variable(a_channel, "att_xfer_kill_uuid", switch_core_session_get_uuid(b_session));
if (profile->media_options & MEDIA_OPT_BYPASS_AFTER_ATT_XFER) {
switch_channel_set_flag(a_channel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
}
if ((tmp = switch_channel_get_hold_music(a_channel))) {
moh = tmp;
}
@@ -5747,6 +5775,12 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
switch_core_session_rwunlock(tmp);
}
if ((profile->media_options & MEDIA_OPT_BYPASS_AFTER_ATT_XFER) && (tmp = switch_core_session_locate(br_a))) {
switch_channel_t *tchannel = switch_core_session_get_channel(tmp);
switch_channel_set_flag(tchannel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
switch_core_session_rwunlock(tmp);
}
switch_ivr_uuid_bridge(br_b, br_a);
switch_channel_set_variable(channel_b, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"),
@@ -6129,7 +6163,7 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t
/* Barf if we didn't get our private */
assert(switch_core_session_get_private(session));
if (sip->sip_content_type && sip->sip_content_type->c_subtype && sip->sip_content_type->c_type &&
if (sip && sip->sip_content_type && sip->sip_content_type->c_subtype && sip->sip_content_type->c_type &&
!strncasecmp(sip->sip_content_type->c_type, "message", 7) &&
!strcasecmp(sip->sip_content_type->c_subtype, "update_display")) {
sofia_update_callee_id(session, profile, sip, SWITCH_TRUE);
+25 -5
View File
@@ -505,7 +505,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, uint32
ptime = tech_pvt->read_codec.implementation->microseconds_per_packet / 1000;
}
if (tech_pvt->dtmf_type == DTMF_2833 && tech_pvt->te > 95) {
switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=rtpmap:%d telephone-event/8000\na=fmtp:%d 0-16\n", tech_pvt->te, tech_pvt->te);
}
@@ -729,6 +729,8 @@ void sofia_glue_tech_prepare_codecs(private_object_t *tech_pvt)
return;
}
tech_pvt->payload_space = 0;
switch_assert(tech_pvt->session != NULL);
if ((abs = switch_channel_get_variable(tech_pvt->channel, "absolute_codec_string"))) {
@@ -1893,6 +1895,8 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
const char *invite_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_to");
const char *handle_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_handle_full_from");
const char *handle_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_handle_full_to");
const char *force_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_force_full_from");
const char *force_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_force_full_to");
char *mp = NULL, *mp_type = NULL;
rep = switch_channel_get_variable(channel, SOFIA_REPLACES_HEADER);
@@ -2125,6 +2129,15 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
}
if (force_full_from) {
from_str = (char *) force_full_from;
}
if (force_full_to) {
to_str = (char *) force_full_to;
}
if (invite_req_uri) {
url_str = (char *) invite_req_uri;
}
@@ -4754,6 +4767,11 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
switch_rtp_set_telephony_recv_event(tech_pvt->rtp_session, te);
}
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Disable 2833 dtmf\n");
switch_channel_set_variable(tech_pvt->channel, "dtmf_type", "none");
tech_pvt->dtmf_type = DTMF_NONE;
te = tech_pvt->recv_te = 0;
}
@@ -5210,12 +5228,14 @@ void sofia_glue_del_profile(sofia_profile_t *profile)
}
for (gp = profile->gateways; gp; gp = gp->next) {
char *pkey = switch_mprintf("%s::%s", profile->name, gp->name);
switch_core_hash_delete(mod_sofia_globals.gateway_hash, gp->name);
switch_core_hash_delete(mod_sofia_globals.gateway_hash, gp->register_from);
switch_core_hash_delete(mod_sofia_globals.gateway_hash, gp->register_contact);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "deleted gateway %s\n", gp->name);
profile->gateways = NULL;
switch_core_hash_delete(mod_sofia_globals.gateway_hash, pkey);
switch_safe_free(pkey);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "deleted gateway %s from profile %s\n", gp->name, profile->name);
}
profile->gateways = NULL;
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
}
+3 -3
View File
@@ -1506,9 +1506,9 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char *
stream.write_function(&stream,
"<?xml version=\"1.0\"?>\n"
"<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" "
"version=\"%s\" state=\"%s\" entity=\"%s\">\n",
version,
zstr(uuid) ? "partial" : "full", clean_id);
"version=\"%s\" state=\"partial\" entity=\"%s\">\n", version, clean_id);
}
//if (strcasecmp(event_status, "Registered")) {
+2 -2
View File
@@ -800,7 +800,7 @@ void sofia_reg_auth_challenge(nua_t *nua, sofia_profile_t *profile, nua_handle_t
sql = switch_mprintf("insert into sip_authentication (nonce,expires,profile_name,hostname, last_nc) "
"values('%q', %ld, '%q', '%q', 0)", uuid_str,
switch_epoch_time_now(NULL) + (profile->nonce_ttl ? profile->nonce_ttl : DEFAULT_NONCE_TTL),
(long) switch_epoch_time_now(NULL) + (profile->nonce_ttl ? profile->nonce_ttl : DEFAULT_NONCE_TTL),
profile->name, mod_sofia_globals.hostname);
switch_assert(sql != NULL);
sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex);
@@ -1104,7 +1104,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
to_user = force_user;
}
if (profile->rport_level == 3 && sip->sip_user_agent &&
if (profile->server_rport_level == 3 && sip->sip_user_agent &&
sip->sip_user_agent->g_string && !strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7)) {
if (sip && sip->sip_via) {
const char *host = sip->sip_via->v_host;
@@ -0,0 +1,27 @@
BASE=../../../..
ZMQ=zeromq-2.1.3
ZMQ_BASEURL=http://download.zeromq.org
ZMQ_DIR=$(switch_srcdir)/libs/$(ZMQ)
ZMQ_BUILDDIR=$(switch_builddir)/libs/$(ZMQ)
LOCAL_CFLAGS=-I$(ZMQ_DIR)/include
ZMQ_LA=$(ZMQ_BUILDDIR)/src/libzmq.la
LOCAL_LIBADD=$(ZMQ_LA)
include $(BASE)/build/modmake.rules
$(ZMQ_DIR):
$(GETLIB) $(ZMQ_BASEURL) $(ZMQ).tar.gz
cd $(ZMQ_DIR) && ./autogen.sh
$(ZMQ_BUILDDIR)/Makefile: $(ZMQ_DIR)
mkdir -p $(ZMQ_DIR)
cd $(ZMQ_BUILDDIR) && $(DEFAULT_VARS) $(ZMQ_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(ZMQ_DIR)
$(TOUCH_TARGET)
$(ZMQ_LA): $(ZMQ_BUILDDIR)/Makefile
cd $(ZMQ_BUILDDIR) && $(MAKE)
$(TOUCH_TARGET)
@@ -0,0 +1,150 @@
#include <switch.h>
#include <zmq.hpp>
#include <exception>
#include <stdexcept>
#include <memory>
namespace mod_event_zmq {
SWITCH_MODULE_LOAD_FUNCTION(load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(shutdown);
SWITCH_MODULE_RUNTIME_FUNCTION(runtime);
extern "C" {
SWITCH_MODULE_DEFINITION(mod_event_zmq, load, shutdown, runtime);
};
// Handles publishing events out to clients
class ZmqEventPublisher {
public:
ZmqEventPublisher() :
context(1),
event_publisher(context, ZMQ_PUB)
{
event_publisher.bind("tcp://*:5556");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Listening for clients\n");
}
void PublishEvent(const switch_event_t *event) {
// Serialize the event into a JSON string
char* pjson;
switch_event_serialize_json(const_cast<switch_event_t*>(event), &pjson);
// Use the JSON string as the message body
zmq::message_t msg(pjson, strlen(pjson), free_message_data, NULL);
// Send the message
event_publisher.send(msg);
}
private:
static void free_message_data(void *data, void *hint) {
free (data);
}
zmq::context_t context;
zmq::socket_t event_publisher;
};
// Handles global inititalization and teardown of the module
class ZmqModule {
public:
ZmqModule(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) :
_running(false) {
// Subscribe to all switch events of any subclass
// Store a pointer to ourself in the user data
if (switch_event_bind_removable(modname, SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, event_handler, (void*)this, &_node)
!= SWITCH_STATUS_SUCCESS) {
throw std::runtime_error("Couldn't bind to switch events.");
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Subscribed to events\n");
// Create our module interface registration
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Module loaded\n");
}
void Listen() {
if(_running)
return;
_publisher.reset(new ZmqEventPublisher());
_running = true;
while(_running) {
switch_yield(100000);
}
}
~ZmqModule() {
// Unsubscribe from the switch events
_running = false;
switch_event_unbind(&_node);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Module shut down\n");
}
private:
// Dispatches events to the publisher
static void event_handler(switch_event_t *event) {
try {
ZmqModule *module = (ZmqModule*)event->bind_user_data;
if(module->_publisher.get())
module->_publisher->PublishEvent(event);
} catch(std::exception ex) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error publishing event via 0MQ: %s\n", ex.what());
} catch(...) { // Exceptions must not propogate to C caller
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown error publishing event via 0MQ\n");
}
}
switch_event_node_t *_node;
std::auto_ptr<ZmqEventPublisher> _publisher;
bool _running;
};
//*****************************//
// GLOBALS //
//*****************************//
std::auto_ptr<ZmqModule> module;
//*****************************//
// Module interface funtions //
//*****************************//
SWITCH_MODULE_LOAD_FUNCTION(load) {
try {
module.reset(new ZmqModule(module_interface, pool));
return SWITCH_STATUS_SUCCESS;
} catch(...) { // Exceptions must not propogate to C caller
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error loading 0MQ module\n");
return SWITCH_STATUS_GENERR;
}
}
SWITCH_MODULE_RUNTIME_FUNCTION(runtime) {
try {
// Begin listening for clients
module->Listen();
} catch(std::exception &ex) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error listening for clients: %s\n", ex.what());
} catch(...) { // Exceptions must not propogate to C caller
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown error listening for clients\n");
}
// Tell the switch to stop calling this runtime loop
return SWITCH_STATUS_TERM;
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(shutdown) {
try {
// Free the module object
module.reset();
} catch(...) { // Exceptions must not propogate to C caller
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error shutting down module\n");
}
}
}
@@ -1,221 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* 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 <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
* Cesar Cepeda <cesar@auronix.com>
*
*
* mod_file_string.c -- Local Streaming Audio
*
*/
#include <switch.h>
/* for apr_pstrcat */
#define DEFAULT_PREBUFFER_SIZE 1024 * 64
SWITCH_MODULE_LOAD_FUNCTION(mod_file_string_load);
SWITCH_MODULE_DEFINITION(mod_file_string, mod_file_string_load, NULL, NULL);
struct file_string_source;
static struct {
switch_mutex_t *mutex;
switch_hash_t *source_hash;
} globals;
struct file_string_context {
char *argv[128];
int argc;
int index;
int samples;
switch_file_handle_t fh;
};
typedef struct file_string_context file_string_context_t;
static int next_file(switch_file_handle_t *handle)
{
file_string_context_t *context = handle->private_info;
char *file;
const char *prefix = handle->prefix;
top:
context->index++;
if (switch_test_flag((&context->fh), SWITCH_FILE_OPEN)) {
switch_core_file_close(&context->fh);
}
if (context->index >= context->argc) {
return 0;
}
if (!prefix) {
if (!(prefix = switch_core_get_variable_pdup("sound_prefix", handle->memory_pool))) {
prefix = SWITCH_GLOBAL_dirs.sounds_dir;
}
}
if (!prefix || switch_is_file_path(context->argv[context->index])) {
file = context->argv[context->index];
} else {
file = switch_core_sprintf(handle->memory_pool, "%s%s%s", prefix, SWITCH_PATH_SEPARATOR, context->argv[context->index]);
}
if (switch_core_file_open(&context->fh,
file, handle->channels, handle->samplerate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
goto top;
}
handle->samples = context->fh.samples;
handle->samplerate = context->fh.samplerate;
handle->channels = context->fh.channels;
handle->format = context->fh.format;
handle->sections = context->fh.sections;
handle->seekable = context->fh.seekable;
handle->speed = context->fh.speed;
handle->interval = context->fh.interval;
if (context->index == 0) {
context->samples = (handle->samplerate / 1000) * 250;
}
return 1;
}
static switch_status_t file_string_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
{
file_string_context_t *context = handle->private_info;
if (samples == 0 && whence == SEEK_SET) {
context->index = -1;
return SWITCH_STATUS_SUCCESS;
}
if (!handle->seekable) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "File is not seekable\n");
return SWITCH_STATUS_NOTIMPL;
}
return switch_core_file_seek(&context->fh, cur_sample, samples, whence);
}
static switch_status_t file_string_file_open(switch_file_handle_t *handle, const char *path)
{
file_string_context_t *context;
char *file_dup;
if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "This format does not support writing!\n");
return SWITCH_STATUS_FALSE;
}
context = switch_core_alloc(handle->memory_pool, sizeof(*context));
file_dup = switch_core_strdup(handle->memory_pool, path);
context->argc = switch_separate_string(file_dup, '!', context->argv, (sizeof(context->argv) / sizeof(context->argv[0])));
context->index = -1;
handle->private_info = context;
return next_file(handle) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
}
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);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t file_string_file_read(switch_file_handle_t *handle, void *data, size_t *len)
{
file_string_context_t *context = handle->private_info;
switch_status_t status;
size_t llen = *len;
if (context->samples > 0) {
if (*len > (size_t) context->samples) {
*len = context->samples;
}
context->samples -= *len;
switch_generate_sln_silence((int16_t *) data, *len, 400);
status = SWITCH_STATUS_SUCCESS;
} else {
status = switch_core_file_read(&context->fh, data, len);
}
if (status != SWITCH_STATUS_SUCCESS) {
if (!next_file(handle)) {
return SWITCH_STATUS_FALSE;
}
*len = llen;
status = switch_core_file_read(&context->fh, data, len);
}
return SWITCH_STATUS_SUCCESS;
}
/* Registration */
static char *supported_formats[SWITCH_MAX_CODECS] = { 0 };
SWITCH_MODULE_LOAD_FUNCTION(mod_file_string_load)
{
switch_file_interface_t *file_interface;
supported_formats[0] = "file_string";
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
file_interface->interface_name = modname;
file_interface->extens = supported_formats;
file_interface->file_open = file_string_file_open;
file_interface->file_close = file_string_file_close;
file_interface->file_read = file_string_file_read;
file_interface->file_seek = file_string_file_seek;
memset(&globals, 0, sizeof(globals));
/* indicate that the module should continue to be loaded */
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:
*/
@@ -142,11 +142,6 @@ void Session::do_hangup_hook()
}
docall(L, arg_count, 1, 1);
err = lua_tostring(L, -1);
if (!zstr(err)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", err);
}
if (channel) {
switch_channel_set_private(channel, "CoreSession", NULL);
+16 -11
View File
@@ -127,10 +127,23 @@ static switch_status_t de_say_general_count(switch_core_session_t *session, char
int in;
int x = 0;
int places[9] = { 0 };
char sbuf[13] = "";
char sbuf[128] = "";
switch_status_t status;
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
if (say_args->method == SSM_ITERATED) {
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
return SWITCH_STATUS_SUCCESS;
}
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
@@ -158,14 +171,6 @@ static switch_status_t de_say_general_count(switch_core_session_t *session, char
return status;
}
break;
case SSM_ITERATED:
{
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
}
break;
default:
break;
}
@@ -327,7 +332,7 @@ static switch_status_t de_say_money(switch_core_session_t *session, char *tosay,
char *dollars = NULL;
char *cents = NULL;
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
+208 -89
View File
@@ -51,7 +51,8 @@
SWITCH_MODULE_LOAD_FUNCTION(mod_say_en_load);
SWITCH_MODULE_DEFINITION(mod_say_en, mod_say_en_load, NULL, NULL);
#define say_num(num, meth) { \
#define say_num(_sh, num, meth) { \
char tmp[80]; \
switch_status_t tstatus; \
switch_say_method_t smeth = say_args->method; \
@@ -59,7 +60,7 @@ SWITCH_MODULE_DEFINITION(mod_say_en, mod_say_en_load, NULL, NULL);
say_args->type = SST_ITEMS; say_args->method = meth; \
switch_snprintf(tmp, sizeof(tmp), "%u", (unsigned)num); \
if ((tstatus = \
en_say_general_count(session, tmp, say_args, args)) \
en_say_general_count(_sh, tmp, say_args)) \
!= SWITCH_STATUS_SUCCESS) { \
return tstatus; \
} \
@@ -67,57 +68,44 @@ SWITCH_MODULE_DEFINITION(mod_say_en, mod_say_en_load, NULL, NULL);
} \
#define say_file(...) { \
char tmp[80]; \
switch_status_t tstatus; \
switch_snprintf(tmp, sizeof(tmp), __VA_ARGS__); \
if ((tstatus = \
switch_ivr_play_file(session, NULL, tmp, args)) \
!= SWITCH_STATUS_SUCCESS){ \
return tstatus; \
} \
if (!switch_channel_ready(switch_core_session_get_channel(session))) { \
return SWITCH_STATUS_FALSE; \
}} \
static switch_status_t play_group(switch_say_method_t method, int a, int b, int c, char *what, switch_core_session_t *session, switch_input_args_t *args)
static switch_status_t play_group(switch_say_method_t method, int a, int b, int c, char *what, switch_say_file_handle_t *sh)
{
if (a) {
say_file("digits/%d.wav", a);
say_file("digits/hundred.wav");
switch_say_file(sh, "digits/%d", a);
switch_say_file(sh, "digits/hundred");
}
if (b) {
if (b > 1) {
if ((c == 0) && (method == SSM_COUNTED)) {
say_file("digits/h-%d0.wav", b);
switch_say_file(sh, "digits/h-%d0", b);
} else {
say_file("digits/%d0.wav", b);
switch_say_file(sh, "digits/%d0", b);
}
} else {
say_file("digits/%d%d.wav", b, c);
switch_say_file(sh, "digits/%d%d", b, c);
c = 0;
}
}
if (c) {
if (method == SSM_COUNTED) {
say_file("digits/h-%d.wav", c);
switch_say_file(sh, "digits/h-%d", c);
} else {
say_file("digits/%d.wav", c);
switch_say_file(sh, "digits/%d", c);
}
}
if (what && (a || b || c)) {
say_file(what);
switch_say_file(sh, what);
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t en_say_general_count(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
static switch_status_t en_say_general_count(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
{
int in;
int x = 0;
@@ -126,10 +114,10 @@ static switch_status_t en_say_general_count(switch_core_session_t *session, char
switch_status_t status;
if (say_args->method == SSM_ITERATED) {
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)))) {
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
switch_say_file(sh, "digits/%c", *p);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
@@ -138,7 +126,7 @@ static switch_status_t en_say_general_count(switch_core_session_t *session, char
return SWITCH_STATUS_SUCCESS;
}
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
@@ -156,13 +144,13 @@ static switch_status_t en_say_general_count(switch_core_session_t *session, char
switch (say_args->method) {
case SSM_COUNTED:
case SSM_PRONOUNCED:
if ((status = play_group(SSM_PRONOUNCED, places[8], places[7], places[6], "digits/million.wav", session, args)) != SWITCH_STATUS_SUCCESS) {
if ((status = play_group(SSM_PRONOUNCED, places[8], places[7], places[6], "digits/million", sh)) != SWITCH_STATUS_SUCCESS) {
return status;
}
if ((status = play_group(SSM_PRONOUNCED, places[5], places[4], places[3], "digits/thousand.wav", session, args)) != SWITCH_STATUS_SUCCESS) {
if ((status = play_group(SSM_PRONOUNCED, places[5], places[4], places[3], "digits/thousand", sh)) != SWITCH_STATUS_SUCCESS) {
return status;
}
if ((status = play_group(say_args->method, places[2], places[1], places[0], NULL, session, args)) != SWITCH_STATUS_SUCCESS) {
if ((status = play_group(say_args->method, places[2], places[1], places[0], NULL, sh)) != SWITCH_STATUS_SUCCESS) {
return status;
}
break;
@@ -170,20 +158,21 @@ static switch_status_t en_say_general_count(switch_core_session_t *session, char
break;
}
} else {
say_file("digits/0.wav");
switch_say_file(sh, "digits/0");
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t en_say_time(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
static switch_status_t en_say_time(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
{
int32_t t;
switch_time_t target = 0, target_now = 0;
switch_time_exp_t tm, tm_now;
uint8_t say_date = 0, say_time = 0, say_year = 0, say_month = 0, say_dow = 0, say_day = 0, say_yesterday = 0, say_today = 0;
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *tz = switch_channel_get_variable(channel, "timezone");
const char *tz = NULL;
tz = switch_say_file_handle_get_variable(sh, "timezone");
if (say_args->type == SST_TIME_MEASUREMENT) {
int64_t hours = 0;
@@ -192,7 +181,7 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
int64_t r = 0;
if (strchr(tosay, ':')) {
char *tme = switch_core_session_strdup(session, tosay);
char *tme = strdup(tosay);
char *p;
if ((p = strrchr(tme, ':'))) {
@@ -208,6 +197,7 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
minutes = atoi(tme);
}
}
free(tme);
} else {
if ((seconds = atol(tosay)) <= 0) {
seconds = (int64_t) switch_epoch_time_now(NULL);
@@ -227,39 +217,39 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
}
if (hours) {
say_num(hours, SSM_PRONOUNCED);
say_num(sh, hours, SSM_PRONOUNCED);
if (hours == 1) {
say_file("time/hour.wav");
switch_say_file(sh, "time/hour");
} else {
say_file("time/hours.wav");
switch_say_file(sh, "time/hours");
}
} else {
say_file("digits/0.wav");
say_file("time/hours.wav");
switch_say_file(sh, "digits/0");
switch_say_file(sh, "time/hours");
}
if (minutes) {
say_num(minutes, SSM_PRONOUNCED);
say_num(sh, minutes, SSM_PRONOUNCED);
if (minutes == 1) {
say_file("time/minute.wav");
switch_say_file(sh, "time/minute");
} else {
say_file("time/minutes.wav");
switch_say_file(sh, "time/minutes");
}
} else {
say_file("digits/0.wav");
say_file("time/minutes.wav");
switch_say_file(sh, "digits/0");
switch_say_file(sh, "time/minutes");
}
if (seconds) {
say_num(seconds, SSM_PRONOUNCED);
say_num(sh, seconds, SSM_PRONOUNCED);
if (seconds == 1) {
say_file("time/second.wav");
switch_say_file(sh, "time/second");
} else {
say_file("time/seconds.wav");
switch_say_file(sh, "time/seconds");
}
} else {
say_file("digits/0.wav");
say_file("time/seconds.wav");
switch_say_file(sh, "digits/0");
switch_say_file(sh, "time/seconds");
}
return SWITCH_STATUS_SUCCESS;
@@ -275,7 +265,7 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
if (tz) {
int check = atoi(tz);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Timezone is [%s]\n", tz);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Timezone is [%s]\n", tz);
if (check) {
switch_time_exp_tz(&tm, target, check);
switch_time_exp_tz(&tm_now, target_now, check);
@@ -329,13 +319,13 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
}
if (say_today) {
say_file("time/today.wav");
switch_say_file(sh, "time/today");
}
if (say_yesterday) {
say_file("time/yesterday.wav");
switch_say_file(sh, "time/yesterday");
}
if (say_dow) {
say_file("time/day-%d.wav", tm.tm_wday);
switch_say_file(sh, "time/day-%d", tm.tm_wday);
}
if (say_date) {
@@ -344,20 +334,20 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
}
if (say_month) {
say_file("time/mon-%d.wav", tm.tm_mon);
switch_say_file(sh, "time/mon-%d", tm.tm_mon);
}
if (say_day) {
say_num(tm.tm_mday, SSM_COUNTED);
say_num(sh, tm.tm_mday, SSM_COUNTED);
}
if (say_year) {
say_num(tm.tm_year + 1900, SSM_PRONOUNCED);
say_num(sh, tm.tm_year + 1900, SSM_PRONOUNCED);
}
if (say_time) {
int32_t hour = tm.tm_hour, pm = 0;
if (say_date || say_today || say_yesterday || say_dow) {
say_file("time/at.wav");
switch_say_file(sh, "time/at");
}
if (hour > 12) {
@@ -370,31 +360,31 @@ static switch_status_t en_say_time(switch_core_session_t *session, char *tosay,
pm = 0;
}
say_num(hour, SSM_PRONOUNCED);
say_num(sh, hour, SSM_PRONOUNCED);
if (tm.tm_min > 9) {
say_num(tm.tm_min, SSM_PRONOUNCED);
say_num(sh, tm.tm_min, SSM_PRONOUNCED);
} else if (tm.tm_min) {
say_file("time/oh.wav");
say_num(tm.tm_min, SSM_PRONOUNCED);
switch_say_file(sh, "time/oh");
say_num(sh, tm.tm_min, SSM_PRONOUNCED);
} else {
say_file("time/oclock.wav");
switch_say_file(sh, "time/oclock");
}
say_file("time/%s.wav", pm ? "p-m" : "a-m");
switch_say_file(sh, "time/%s", pm ? "p-m" : "a-m");
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t en_say_money(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
static switch_status_t en_say_money(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
{
char sbuf[16] = ""; /* enough for 999,999,999,999.99 (w/o the commas or leading $) */
char *dollars = NULL;
char *cents = NULL;
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
@@ -415,43 +405,105 @@ static switch_status_t en_say_money(switch_core_session_t *session, char *tosay,
/* If negative say "negative" */
if (sbuf[0] == '-') {
say_file("currency/negative.wav");
switch_say_file(sh, "currency/negative");
dollars++;
}
/* Say dollar amount */
en_say_general_count(session, dollars, say_args, args);
en_say_general_count(sh, dollars, say_args);
if (atoi(dollars) == 1) {
say_file("currency/dollar.wav");
switch_say_file(sh, "currency/dollar");
} else {
say_file("currency/dollars.wav");
switch_say_file(sh, "currency/dollars");
}
/* Say "and" */
say_file("currency/and.wav");
/* Say cents */
if (cents) {
en_say_general_count(session, cents, say_args, args);
/* Say "and" */
switch_say_file(sh, "currency/and");
en_say_general_count(sh, cents, say_args);
if (atoi(cents) == 1) {
say_file("currency/cent.wav");
switch_say_file(sh, "currency/cent");
} else {
say_file("currency/cents.wav");
switch_say_file(sh, "currency/cents");
}
} else {
say_file("digits/0.wav");
say_file("currency/cents.wav");
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t en_say(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
static switch_status_t say_ip(switch_say_file_handle_t *sh,
char *tosay,
switch_say_args_t *say_args)
{
char *a, *b, *c, *d;
switch_status_t status = SWITCH_STATUS_FALSE;
if (!(a = strdup(tosay))) {
abort();
}
switch_say_callback_t say_cb = NULL;
if (!(b = strchr(a, '.'))) {
goto end;
}
*b++ = '\0';
if (!(c = strchr(b, '.'))) {
goto end;
}
*c++ = '\0';
if (!(d = strchr(c, '.'))) {
goto end;
}
*d++ = '\0';
say_num(sh, atoi(a), say_args->method);
switch_say_file(sh, "digits/dot");
say_num(sh, atoi(b), say_args->method);
switch_say_file(sh, "digits/dot");
say_num(sh, atoi(c), say_args->method);
switch_say_file(sh, "digits/dot");
say_num(sh, atoi(d), say_args->method);
end:
free(a);
return status;
}
static switch_status_t say_spell(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
{
char *p;
for (p = tosay; p && *p; p++) {
int a = tolower((int) *p);
if (a >= '0' && a <= '9') {
switch_say_file(sh, "digits/%c", a);
} else {
if (say_args->type == SST_NAME_SPELLED) {
switch_say_file(sh, "ascii/%d", a);
} else if (say_args->type == SST_NAME_PHONETIC) {
switch_say_file(sh, "phonetic-ascii/%d", a);
}
}
}
return SWITCH_STATUS_SUCCESS;
}
static switch_new_say_callback_t choose_callback(switch_say_args_t *say_args)
{
switch_new_say_callback_t say_cb = NULL;
switch (say_args->type) {
case SST_NUMBER:
@@ -468,11 +520,11 @@ static switch_status_t en_say(switch_core_session_t *session, char *tosay, switc
say_cb = en_say_time;
break;
case SST_IP_ADDRESS:
return switch_ivr_say_ip(session, tosay, en_say_general_count, say_args, args);
say_cb = say_ip;
break;
case SST_NAME_SPELLED:
case SST_NAME_PHONETIC:
return switch_ivr_say_spell(session, tosay, say_args, args);
say_cb = say_spell;
break;
case SST_CURRENCY:
say_cb = en_say_money;
@@ -482,11 +534,77 @@ static switch_status_t en_say(switch_core_session_t *session, char *tosay, switc
break;
}
if (say_cb) {
return say_cb(session, tosay, say_args, args);
return say_cb;
}
static switch_status_t run_callback(switch_new_say_callback_t say_cb, char *tosay, switch_say_args_t *say_args, switch_core_session_t *session, char **rstr)
{
switch_say_file_handle_t *sh;
switch_status_t status = SWITCH_STATUS_FALSE;
switch_event_t *var_event = NULL;
if (session) {
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_channel_get_variables(channel, &var_event);
}
return SWITCH_STATUS_FALSE;
switch_say_file_handle_create(&sh, say_args->ext, &var_event);
status = say_cb(sh, tosay, say_args);
if ((*rstr = switch_say_file_handle_detach_path(sh))) {
status = SWITCH_STATUS_SUCCESS;
}
switch_say_file_handle_destroy(&sh);
return status;
}
static switch_status_t en_say(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
{
switch_new_say_callback_t say_cb = NULL;
char *string = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
say_cb = choose_callback(say_args);
if (say_cb) {
status = run_callback(say_cb, tosay, say_args, session, &string);
if (session && string) {
status = switch_ivr_play_file(session, NULL, string, args);
}
switch_safe_free(string);
}
return status;
}
static switch_status_t en_say_string(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, char **rstr)
{
switch_new_say_callback_t say_cb = NULL;
char *string = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
say_cb = choose_callback(say_args);
if (say_cb) {
status = run_callback(say_cb, tosay, say_args, session, &string);
if (string) {
status = SWITCH_STATUS_SUCCESS;
*rstr = string;
}
}
return status;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_say_en_load)
@@ -497,7 +615,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_say_en_load)
say_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_SAY_INTERFACE);
say_interface->interface_name = "en";
say_interface->say_function = en_say;
say_interface->say_string_function = en_say_string;
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
+16 -11
View File
@@ -155,10 +155,23 @@ static switch_status_t es_say_general_count(switch_core_session_t *session, char
int in;
int x = 0;
int places[9] = { 0 };
char sbuf[13] = "";
char sbuf[128] = "";
switch_status_t status;
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
if (say_args->method == SSM_ITERATED) {
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
return SWITCH_STATUS_SUCCESS;
}
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
@@ -191,14 +204,6 @@ static switch_status_t es_say_general_count(switch_core_session_t *session, char
return status;
}
break;
case SSM_ITERATED:
{
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
}
break;
default:
break;
}
@@ -362,7 +367,7 @@ static switch_status_t es_say_money(switch_core_session_t *session, char *tosay,
char *dollars = NULL;
char *cents = NULL;
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
+20 -15
View File
@@ -144,10 +144,27 @@ static switch_status_t fr_say_general_count(switch_core_session_t *session, char
int in;
int x = 0;
int places[9] = { 0 };
char sbuf[13] = "";
char sbuf[128] = "";
switch_status_t status;
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
if (say_args->method == SSM_ITERATED) {
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
char *p;
for (p = tosay; p && *p; p++) {
if (*p == '1' && say_args->gender == SSG_FEMININE) {
say_file("digits/%c_f.wav", *p);
} else {
say_file("digits/%c.wav", *p);
}
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
return SWITCH_STATUS_SUCCESS;
}
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
@@ -175,18 +192,6 @@ static switch_status_t fr_say_general_count(switch_core_session_t *session, char
return status;
}
break;
case SSM_ITERATED:
{
char *p;
for (p = tosay; p && *p; p++) {
if (*p == '1' && say_args->gender == SSG_FEMININE) {
say_file("digits/%c_f.wav", *p);
} else {
say_file("digits/%c.wav", *p);
}
}
}
break;
default:
break;
}
@@ -399,7 +404,7 @@ static switch_status_t fr_say_money(switch_core_session_t *session, char *tosay,
char *dollars = NULL;
char *cents = NULL;
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
File renamed without changes.
@@ -2,9 +2,9 @@
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="mod_file_string"
ProjectGUID="{70564D74-199A-4452-9C60-19ED5F242F0D}"
RootNamespace="mod_file_string"
Name="mod_say_he"
ProjectGUID="{0E1117D4-56BF-4B5F-926C-273FD99593DE}"
RootNamespace="mod_say_he"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
@@ -274,7 +274,7 @@
</References>
<Files>
<File
RelativePath=".\mod_file_string.c"
RelativePath=".\mod_say_he.c"
>
</File>
</Files>
@@ -19,9 +19,9 @@
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>mod_file_string</ProjectName>
<ProjectGuid>{70564D74-199A-4452-9C60-19ED5F242F0D}</ProjectGuid>
<RootNamespace>mod_file_string</RootNamespace>
<ProjectName>mod_say_he</ProjectName>
<ProjectGuid>{0E1117D4-56BF-4B5F-926C-273FD99593DE}</ProjectGuid>
<RootNamespace>mod_say_he</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
@@ -117,9 +117,13 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="mod_file_string.c" />
<ClCompile Include="mod_say_he.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\libs\win32\apr\libapr.2010.vcxproj">
<Project>{f6c55d93-b927-4483-bb69-15aef3dd2dff}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj">
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
@@ -128,4 +132,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
+866
View File
@@ -0,0 +1,866 @@
/*
* Copyright (c) 2011, Shahar Hadas
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The Initial Developers of the Original Code are
* Anthony Minessale II <anthm@freeswitch.org>
* Michael B. Murdock <mike@mmurdock.org>
* Marc O. Chouinard <mochouinard@moctel.com>
* Yehavi Bourvine <yehavi@savion.huji.ac.il>
* Eli Hayun <elihay@savion.huji.ac.il>
* Portions created by the Initial Developers are Copyright (C)
* the Initial Developers. All Rights Reserved.
*
* Contributor(s):
*
* mod_say_he.c -- Say for Hebrew
*
*/
#include <switch.h>
#include <math.h>
#include <ctype.h>
SWITCH_MODULE_LOAD_FUNCTION(mod_say_he_load);
SWITCH_MODULE_DEFINITION(mod_say_he, mod_say_he_load, NULL, NULL);
#define say_num(_sh, num, meth) { \
char tmp[80]; \
switch_status_t tstatus; \
switch_say_method_t smeth = say_args->method; \
switch_say_type_t stype = say_args->type; \
say_args->type = SST_ITEMS; say_args->method = meth; \
switch_snprintf(tmp, sizeof(tmp), "%u", (unsigned)num); \
if ((tstatus = \
he_say_general_count(_sh, tmp, say_args)) \
!= SWITCH_STATUS_SUCCESS) { \
return tstatus; \
} \
say_args->method = smeth; say_args->type = stype; \
} \
typedef enum {
PGR_HUNDREDS = 1000,
PGR_THOUSANDS = 100000,
PGR_MILLIONS = 100000000,
} play_group_range_t;
static switch_status_t play_group(switch_say_method_t method, switch_say_gender_t gender, int total, play_group_range_t range, int a, int b, int c, char *what, switch_say_file_handle_t *sh)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "** total=[%d] range=[%d] a=[%d] b=[%d] c=[%d] gender=[%d] method=[%d] what=[%s]\n", total, range, a, b, c, gender, method, what);
/* Check for special cases of thousands */
if (range == PGR_THOUSANDS && a == 0) {
/* Check for special cases of 1000, 2000 ... 8000, 9000 */
if (b == 0 && c != 0) {
switch_say_file(sh, "digits/%d000", c);
return SWITCH_STATUS_SUCCESS;
}
/* Check for special case of 10,000 */
if (b == 1 && c == 0) {
switch_say_file(sh, "digits/10000");
return SWITCH_STATUS_SUCCESS;
}
}
/* Check for special case of million */
if (range == PGR_MILLIONS && a == 0 && b == 0 && c == 1) {
switch_say_file(sh, "digits/million");
return SWITCH_STATUS_SUCCESS;
}
/* Check for Hebrew SSM_COUNTED special case. Anything above 10 needs to said differently */
if (method == SSM_COUNTED && range == PGR_HUNDREDS && total <= 10) {
if (b) {
switch_say_file(sh, "digits/h-10%s", gender == SSG_MASCULINE ? "_m" : "");
} else {
switch_say_file(sh, "digits/h-%d%s", c, gender == SSG_MASCULINE ? "_m" : "");
}
return SWITCH_STATUS_SUCCESS;
}
/* In Hebrew, hundreds can be said as "<number> hundreds", but the more correct
* form of pronunciation required it to be recorded separately.
* Note that hundreds are always pronounced in SSG_FEMININE form in hebrew, and were recorded as such.
*/
if (a) {
switch_say_file(sh, "digits/%d00", a);
}
if (b) {
/* Check for two digits playback (10 to 19) */
if (b > 1) {
switch_say_file(sh, "digits/%d0", b);
} else {
if (range != PGR_HUNDREDS || gender == SSG_MASCULINE) {
if ((range == PGR_MILLIONS && a) || (range != PGR_MILLIONS && total > 9)){ /* Check if need to say "and" */
switch (c) {
case 0:
case 5:
switch_say_file(sh, "digits/va");
break;
case 2:
case 3:
case 8:
case 9:
switch_say_file(sh, "digits/uu");
break;
case 1:
case 4:
case 6:
case 7:
switch_say_file(sh, "digits/ve");
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "play_group unkonwn digit (%d) Error! (SSG_MASCULINE)\n", c);
break;
}
}
switch_say_file(sh, "digits/%d%d_m", b, c);
} else {
if ((range == PGR_MILLIONS && a) || (range != PGR_MILLIONS && total > 9)){ /* Check if need to say "and" */
switch (c) {
case 2:
case 3:
case 7:
case 8:
case 9:
switch_say_file(sh, "digits/uu");
break;
case 0:
case 1:
case 4:
case 5:
case 6:
switch_say_file(sh, "digits/ve");
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "play_group unkonwn digit (%d) Error! (SSG_FEMININE)\n", c);
break;
}
}
switch_say_file(sh, "digits/%d%d", b, c);
}
c = 0; /* Skip the pronunciation on the c value */
}
}
if (c) {
if (range != PGR_HUNDREDS || gender == SSG_MASCULINE) {
if ((range == PGR_MILLIONS && (b || a)) || (range != PGR_MILLIONS && total > 9)){ /* Check if need to say "and" */
switch (c) {
case 5:
switch_say_file(sh, "digits/va");
break;
case 2:
case 3:
case 8:
switch_say_file(sh, "digits/uu");
break;
case 1:
case 4:
case 6:
case 7:
case 9:
switch_say_file(sh, "digits/ve");
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "play_group unkonwn digit (%d) Error! (SSG_MASCULINE)\n", c);
break;
}
}
switch_say_file(sh, "digits/%d_m", c);
} else {
if ((range == PGR_MILLIONS && (b || a)) || (range != PGR_MILLIONS && total > 9)){ /* Check if need to say "and" */
switch (c) {
case 2:
case 8:
switch_say_file(sh, "digits/uu");
break;
case 1:
case 3:
case 4:
case 5:
case 6:
case 7:
case 9:
switch_say_file(sh, "digits/ve");
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "play_group unkonwn digit (%d) Error! (SSG_FEMININE)\n", c);
break;
}
}
switch_say_file(sh, "digits/%d", c);
}
}
if (what && (a || b || c)) {
switch_say_file(sh, what);
}
/* Incase of SSM_COUNTED, in the case of total > 10, after the number was said, we need to say "be'mispar" (in number).
* Although we shouldn't be here if total <= 10, I still preferred to have the criteria tested again. */
if (method == SSM_COUNTED && range == PGR_HUNDREDS && total > 10) {
switch_say_file(sh, "digits/in_number", c);
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t he_say_general_count(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
{
int in, inCopy;
int x = 0;
int places[9] = { 0 };
char sbuf[128] = "";
switch_status_t status;
if (say_args->method == SSM_ITERATED) {
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
char *p;
for (p = tosay; p && *p; p++) {
if (*p != '0' && say_args->gender == SSG_MASCULINE) {
switch_say_file(sh, "digits/%c_m", *p);
} else {
switch_say_file(sh, "digits/%c", *p);
}
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
return SWITCH_STATUS_SUCCESS;
}
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
in = inCopy = atoi(tosay);
if (in != 0) {
for (x = 8; x >= 0; x--) {
int num = (int) pow(10, x);
if ((places[(uint32_t) x] = in / num)) {
in -= places[(uint32_t) x] * num;
}
}
switch (say_args->method) {
case SSM_COUNTED:
/* TODO add 'ha' (the)? */
case SSM_PRONOUNCED:
if ((status = play_group(SSM_PRONOUNCED, say_args->gender, inCopy, PGR_MILLIONS, places[8], places[7], places[6], "digits/million", sh)) != SWITCH_STATUS_SUCCESS) {
return status;
}
if ((status = play_group(SSM_PRONOUNCED, say_args->gender, inCopy, PGR_THOUSANDS, places[5], places[4], places[3], "digits/thousand", sh)) != SWITCH_STATUS_SUCCESS) {
return status;
}
if ((status = play_group(say_args->method, say_args->gender, inCopy, PGR_HUNDREDS, places[2], places[1], places[0], NULL, sh)) != SWITCH_STATUS_SUCCESS) {
return status;
}
break;
default:
break;
}
} else {
switch_say_file(sh, "digits/0");
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t he_say_time(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
{
int32_t t;
switch_time_t target = 0, target_now = 0;
switch_time_exp_t tm, tm_now;
uint8_t say_date = 0, say_time = 0, say_year = 0, say_month = 0, say_dow = 0, say_day = 0, say_yesterday = 0, say_today = 0;
const char *tz = NULL;
tz = switch_say_file_handle_get_variable(sh, "timezone");
if (say_args->type == SST_TIME_MEASUREMENT) {
int64_t hours = 0;
int64_t minutes = 0;
int64_t seconds = 0;
int64_t r = 0;
if (strchr(tosay, ':')) {
char *tme = strdup(tosay);
char *p;
if ((p = strrchr(tme, ':'))) {
*p++ = '\0';
seconds = atoi(p);
if ((p = strchr(tme, ':'))) {
*p++ = '\0';
minutes = atoi(p);
if (tme) {
hours = atoi(tme);
}
} else {
minutes = atoi(tme);
}
}
free(tme);
} else {
if ((seconds = atol(tosay)) <= 0) {
seconds = (int64_t) switch_epoch_time_now(NULL);
}
if (seconds >= 60) {
minutes = seconds / 60;
r = seconds % 60;
seconds = r;
}
if (minutes >= 60) {
hours = minutes / 60;
r = minutes % 60;
minutes = r;
}
}
say_args->gender = SSG_FEMININE;
if (hours) {
switch_say_file(sh, "time/hour");
say_num(sh, hours, SSM_PRONOUNCED);
} else {
switch_say_file(sh, "digits/0");
switch_say_file(sh, "time/hours");
}
if (minutes) {
if (minutes == 1) {
switch_say_file(sh, "time/minute");
say_num(sh, minutes, SSM_PRONOUNCED);
} else {
say_num(sh, minutes, SSM_PRONOUNCED);
switch_say_file(sh, "time/minutes");
}
} else {
switch_say_file(sh, "digits/0");
switch_say_file(sh, "time/minutes");
}
if (seconds) {
if (seconds == 1) {
switch_say_file(sh, "time/second");
say_num(sh, seconds, SSM_PRONOUNCED);
} else {
say_num(sh, seconds, SSM_PRONOUNCED);
switch_say_file(sh, "time/seconds");
}
} else {
switch_say_file(sh, "digits/0");
switch_say_file(sh, "time/seconds");
}
return SWITCH_STATUS_SUCCESS;
}
if ((t = atol(tosay)) > 0) {
target = switch_time_make(t, 0);
target_now = switch_micro_time_now();
} else {
target = switch_micro_time_now();
target_now = switch_micro_time_now();
}
if (tz) {
int check = atoi(tz);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Timezone is [%s]\n", tz);
if (check) {
switch_time_exp_tz(&tm, target, check);
switch_time_exp_tz(&tm_now, target_now, check);
} else {
switch_time_exp_tz_name(tz, &tm, target);
switch_time_exp_tz_name(tz, &tm_now, target_now);
}
} else {
switch_time_exp_lt(&tm, target);
switch_time_exp_lt(&tm_now, target_now);
}
switch (say_args->type) {
case SST_CURRENT_DATE_TIME:
say_date = say_time = 1;
break;
case SST_CURRENT_DATE:
say_date = 1;
break;
case SST_CURRENT_TIME:
say_time = 1;
break;
case SST_SHORT_DATE_TIME:
say_time = 1;
if (tm.tm_year != tm_now.tm_year) {
say_date = 1;
break;
}
if (tm.tm_yday == tm_now.tm_yday) {
say_today = 1;
break;
}
if (tm.tm_yday == tm_now.tm_yday - 1) {
say_yesterday = 1;
break;
}
if (tm.tm_yday >= tm_now.tm_yday - 5) {
say_dow = 1;
break;
}
if (tm.tm_mon != tm_now.tm_mon) {
say_month = say_day = say_dow = 1;
break;
}
say_month = say_day = say_dow = 1;
break;
default:
break;
}
if (say_today) {
switch_say_file(sh, "time/today");
}
if (say_yesterday) {
switch_say_file(sh, "time/yesterday");
}
if (say_dow) {
switch_say_file(sh, "time/day-%d", tm.tm_wday);
}
if (say_date) {
say_year = say_month = say_day = say_dow = 1;
say_today = say_yesterday = 0;
}
/* In Hebrew it's costumed to speak the day before the month. */
if (say_day) {
say_args->gender = SSG_MASCULINE;
say_num(sh, tm.tm_mday, SSM_PRONOUNCED);
}
if (say_month) {
switch_say_file(sh, "time/at");
switch_say_file(sh, "time/mon-%d", tm.tm_mon);
}
if (say_year) {
say_args->gender = SSG_FEMININE;
say_num(sh, tm.tm_year + 1900, SSM_PRONOUNCED);
}
if (say_time) {
int32_t hour = tm.tm_hour, pm = 0;
if (say_date || say_today || say_yesterday || say_dow) {
switch_say_file(sh, "time/at-hour");
}
else {
switch_say_file(sh, "time/hour");
}
if (hour > 12) {
hour -= 12;
pm = 1;
} else if (hour == 12) {
pm = 1;
} else if (hour == 0) {
hour = 12;
pm = 0;
}
say_args->gender = SSG_FEMININE;
say_num(sh, hour, SSM_PRONOUNCED);
if (tm.tm_min) {
switch (tm.tm_min) {
case 2:
case 8:
case 12:
case 13:
case 17:
case 18:
case 19:
case 30:
switch_say_file(sh, "digits/uu");
break;
case 50:
switch_say_file(sh, "digits/va");
break;
default:
switch_say_file(sh, "digits/ve");
break;
}
if (tm.tm_min == 1) {
switch_say_file(sh, "time/minute");
switch_say_file(sh, "digits/1");
} else {
say_num(sh, tm.tm_min, SSM_PRONOUNCED);
switch_say_file(sh, "time/minutes");
}
}
switch_say_file(sh, "time/%s", pm ? "p-m" : "a-m");
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t he_say_money(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
{
char sbuf[16] = ""; /* enough for 999,999,999,999.99 (w/o the commas or leading $) */
char *currency = NULL;
char *cents = NULL;
int icents = 0;
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
currency = sbuf;
if ((cents = strchr(sbuf, '.'))) {
*cents++ = '\0';
if (strlen(cents) > 2) {
cents[2] = '\0';
}
}
/* If positive sign - skip over" */
if (sbuf[0] == '+') {
++currency;
}
/* If negative say "negative" */
if (sbuf[0] == '-') {
switch_say_file(sh, "currency/negative");
++currency;
}
/* Say shekel amount (Israel currency) */
switch (atoi(currency)) {
case 1:
switch_say_file(sh, "currency/shekel");
switch_say_file(sh, "digits/1_m");
break;
case 2:
/* In the case of 2, because currency, we need a special case of 2 pronunciation */
switch_say_file(sh, "digits/shney");
switch_say_file(sh, "currency/shkalim");
break;
default:
say_args->gender = SSG_MASCULINE;
he_say_general_count(sh, currency, say_args);
switch_say_file(sh, "currency/shkalim");
break;
}
if (cents) {
/* We need to use the value twice, so speed it up by atoi only once */
icents = atoi(cents);
/* Say "and" */
switch (icents) {
case 2:
case 8:
case 12:
case 13:
case 17:
case 18:
case 19:
case 30:
case 80:
switch_say_file(sh, "digits/uu");
break;
case 50:
switch_say_file(sh, "digits/va");
break;
default:
switch_say_file(sh, "digits/ve");
break;
}
/* Say agorot (Israel currency equivalent for "cents") */
switch (icents) {
case 0:
switch_say_file(sh, "digits/0");
switch_say_file(sh, "currency/agorot");
break;
case 1:
switch_say_file(sh, "currency/agora");
switch_say_file(sh, "digits/1");
break;
case 2:
/* In the case of 2, because currency, we need a special case of 2 pronunciation */
switch_say_file(sh, "digits/shtey");
switch_say_file(sh, "currency/agorot");
break;
default:
say_args->gender = SSG_FEMININE;
he_say_general_count(sh, cents, say_args);
switch_say_file(sh, "currency/agorot");
break;
}
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t say_ip(switch_say_file_handle_t *sh,
char *tosay,
switch_say_args_t *say_args)
{
char *a, *b, *c, *d;
switch_status_t status = SWITCH_STATUS_FALSE;
if (!(a = strdup(tosay))) {
abort();
}
if (!(b = strchr(a, '.'))) {
goto end;
}
*b++ = '\0';
if (!(c = strchr(b, '.'))) {
goto end;
}
*c++ = '\0';
if (!(d = strchr(c, '.'))) {
goto end;
}
*d++ = '\0';
say_num(sh, atoi(a), say_args->method);
switch_say_file(sh, "digits/dot");
say_num(sh, atoi(b), say_args->method);
switch_say_file(sh, "digits/dot");
say_num(sh, atoi(c), say_args->method);
switch_say_file(sh, "digits/dot");
say_num(sh, atoi(d), say_args->method);
end:
free(a);
return status;
}
static switch_status_t say_spell(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args)
{
char *p;
for (p = tosay; p && *p; p++) {
int a = tolower((int) *p);
if (a >= '0' && a <= '9') {
if (a != '0' && say_args->gender == SSG_MASCULINE) {
switch_say_file(sh, "digits/%c_m", a);
} else {
switch_say_file(sh, "digits/%c", a);
}
} else {
if (say_args->type == SST_NAME_SPELLED) {
switch_say_file(sh, "ascii/%d", a);
} else if (say_args->type == SST_NAME_PHONETIC) {
switch_say_file(sh, "phonetic-ascii/%d", a);
}
}
}
return SWITCH_STATUS_SUCCESS;
}
static switch_new_say_callback_t choose_callback(switch_say_args_t *say_args)
{
switch_new_say_callback_t say_cb = NULL;
switch (say_args->type) {
case SST_NUMBER:
case SST_ITEMS:
case SST_PERSONS:
case SST_MESSAGES:
say_cb = he_say_general_count;
break;
case SST_TIME_MEASUREMENT:
case SST_CURRENT_DATE:
case SST_CURRENT_TIME:
case SST_CURRENT_DATE_TIME:
case SST_SHORT_DATE_TIME:
say_cb = he_say_time;
break;
case SST_IP_ADDRESS:
say_cb = say_ip;
break;
case SST_NAME_SPELLED:
case SST_NAME_PHONETIC:
say_cb = say_spell;
break;
case SST_CURRENCY:
say_cb = he_say_money;
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown Say type=[%d]\n", say_args->type);
break;
}
return say_cb;
}
static switch_status_t run_callback(switch_new_say_callback_t say_cb, char *tosay, switch_say_args_t *say_args, switch_core_session_t *session, char **rstr)
{
switch_say_file_handle_t *sh;
switch_status_t status = SWITCH_STATUS_FALSE;
switch_event_t *var_event = NULL;
if (session) {
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_channel_get_variables(channel, &var_event);
}
switch_say_file_handle_create(&sh, say_args->ext, &var_event);
status = say_cb(sh, tosay, say_args);
if ((*rstr = switch_say_file_handle_detach_path(sh))) {
status = SWITCH_STATUS_SUCCESS;
}
switch_say_file_handle_destroy(&sh);
return status;
}
static switch_status_t he_say(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
{
switch_new_say_callback_t say_cb = NULL;
char *string = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
say_cb = choose_callback(say_args);
if (say_cb) {
status = run_callback(say_cb, tosay, say_args, session, &string);
if (session && string) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "** he_say [%s]\n", string);
status = switch_ivr_play_file(session, NULL, string, args);
}
switch_safe_free(string);
}
return status;
}
static switch_status_t he_say_string(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, char **rstr)
{
switch_new_say_callback_t say_cb = NULL;
char *string = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
say_cb = choose_callback(say_args);
if (say_cb) {
status = run_callback(say_cb, tosay, say_args, session, &string);
if (string) {
status = SWITCH_STATUS_SUCCESS;
*rstr = string;
}
}
return status;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_say_he_load)
{
switch_say_interface_t *say_interface;
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
say_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_SAY_INTERFACE);
say_interface->interface_name = "he";
say_interface->say_function = he_say;
say_interface->say_string_function = he_say_string;
/* indicate that the module should continue to be loaded */
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:
*/
@@ -2,9 +2,9 @@
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="mod_file_string"
ProjectGUID="{2CA40887-1622-46A1-A7F9-17FD7E7E545B}"
RootNamespace="mod_file_string"
Name="mod_say_he"
ProjectGUID="{0E1117D4-56BF-4B5F-926C-273FD99593DE}"
RootNamespace="mod_say_he"
Keyword="Win32Proj"
>
<Platforms>
@@ -42,7 +42,7 @@
</References>
<Files>
<File
RelativePath=".\mod_file_string.c"
RelativePath=".\mod_say_he.c"
>
</File>
</Files>
+16 -11
View File
@@ -232,7 +232,7 @@ static switch_status_t hr_say_count(switch_core_session_t *session, char* gen,
strcpy(tgen, gen);
if (!(tosay = strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
if (!(tosay = strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
@@ -356,10 +356,23 @@ static switch_status_t hr_say_general_count(switch_core_session_t *session, char
int in;
int x = 0;
int places[9] = { 0 };
char sbuf[13] = "";
char sbuf[128] = "";
int number;
switch_status_t status;
if (say_args->method == SSM_ITERATED) {
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
return SWITCH_STATUS_SUCCESS;
}
if (!(tosay = strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
@@ -391,14 +404,6 @@ static switch_status_t hr_say_general_count(switch_core_session_t *session, char
return status;
}
break;
case SSM_ITERATED:
{
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
}
break;
default:
break;
}
@@ -1016,7 +1021,7 @@ static switch_status_t hr_say_money(switch_core_session_t *session, char *tosay,
int zadnja_lipa = 0;
int predzadnja_lipa = 0;
if (strlen(tosay) > 15 || !(tosay = strip_nonnumerics(tosay, sbuf, sizeof(sbuf))))
if (strlen(tosay) > 15 || !(tosay = strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1)))
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
+16 -11
View File
@@ -122,11 +122,24 @@ static switch_status_t hu_say_general_count(switch_core_session_t *session, char
int in;
int x = 0;
int places[9] = { 0 };
char sbuf[13] = "";
char sbuf[128] = "";
int number;
switch_status_t status;
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
if (say_args->method == SSM_ITERATED) {
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
return SWITCH_STATUS_SUCCESS;
}
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
@@ -157,14 +170,6 @@ static switch_status_t hu_say_general_count(switch_core_session_t *session, char
return status;
}
break;
case SSM_ITERATED:
{
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
}
break;
default:
break;
}
@@ -356,7 +361,7 @@ static switch_status_t hu_say_money(switch_core_session_t *session, char *tosay,
char sbuf[16] = "";
char *forint;
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
+16 -11
View File
@@ -131,10 +131,23 @@ static switch_status_t it_say_general_count(switch_core_session_t *session, char
int in;
int places_count = 0;
int places[9] = { 0 };
char sbuf[13] = "";
char sbuf[128] = "";
switch_status_t status;
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
if (say_args->method == SSM_ITERATED) {
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
return SWITCH_STATUS_SUCCESS;
}
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
@@ -202,14 +215,6 @@ static switch_status_t it_say_general_count(switch_core_session_t *session, char
return status;
}
break;
case SSM_ITERATED:
{
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
}
break;
default:
break;
}
@@ -355,7 +360,7 @@ static switch_status_t it_say_money(switch_core_session_t *session, char *tosay,
char *dollars = NULL;
char *cents = NULL;
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
+16 -10
View File
@@ -84,11 +84,24 @@ SWITCH_MODULE_DEFINITION(mod_say_ja, mod_say_ja_load, NULL, NULL);
static switch_status_t ja_say_general_count(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
{
int in;
char sbuf[13] = "";
char sbuf[128] = "";
char digits[11];
int i;
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
if (say_args->method == SSM_ITERATED) {
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
return SWITCH_STATUS_SUCCESS;
}
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
@@ -218,13 +231,6 @@ static switch_status_t ja_say_general_count(switch_core_session_t *session, char
}
}
break;
case SSM_ITERATED:
{
char *p;
for (p = tosay; p && *p; p++)
say_file("digits/%c.wav", *p);
}
break;
default:
break;
}
@@ -398,7 +404,7 @@ static switch_status_t ja_say_money(switch_core_session_t *session, char *tosay,
char *dollars = NULL;
char *cents = NULL;
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
+16 -11
View File
@@ -118,10 +118,23 @@ static switch_status_t nl_say_general_count(switch_core_session_t *session, char
int in;
int x = 0;
int places[9] = { 0 };
char sbuf[13] = "";
char sbuf[128] = "";
switch_status_t status;
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
if (say_args->method == SSM_ITERATED) {
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
return SWITCH_STATUS_SUCCESS;
}
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
@@ -149,14 +162,6 @@ static switch_status_t nl_say_general_count(switch_core_session_t *session, char
return status;
}
break;
case SSM_ITERATED:
{
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
}
break;
default:
break;
}
@@ -319,7 +324,7 @@ static switch_status_t nl_say_money(switch_core_session_t *session, char *tosay,
char *dollars = NULL;
char *cents = NULL;
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
+3 -3
View File
@@ -154,7 +154,7 @@ static switch_status_t pt_say_general_count(switch_core_session_t *session, char
switch_status_t status;
if (say_args->method == SSM_ITERATED) {
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)))) {
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
@@ -166,7 +166,7 @@ static switch_status_t pt_say_general_count(switch_core_session_t *session, char
return SWITCH_STATUS_SUCCESS;
}
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
@@ -428,7 +428,7 @@ static switch_status_t pt_say_money(switch_core_session_t *session, char *tosay,
char *dollars = NULL;
char *cents = NULL;
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
+343 -152
View File
@@ -58,63 +58,57 @@ struct say_t matrix[7][8] = { {m_00, m_01, m_02, m_03, m_04, m_05, m_06, m_07},
{m_60, m_61, m_62, m_63, m_64, m_65, m_66, m_67}
};
struct say_cur_t matrix_currency[3] = {c_0, c_1, c_2};
SWITCH_MODULE_LOAD_FUNCTION(mod_say_ru_load);
SWITCH_MODULE_DEFINITION(mod_say_ru, mod_say_ru_load, NULL, NULL);
#define say_file(...) {\
char tmp[80];\
switch_status_t tstatus;\
switch_snprintf(tmp, sizeof(tmp), __VA_ARGS__);\
if ((tstatus = switch_ivr_play_file(session, NULL, tmp, args)) != SWITCH_STATUS_SUCCESS){ \
return tstatus;\
}\
if (!switch_channel_ready(switch_core_session_get_channel(session))) {\
return SWITCH_STATUS_FALSE;\
}}
static switch_status_t play_group(say_type_t say_type, casus_t casus, int a, int b, int c,
unit_t what, switch_core_session_t *session, switch_input_args_t *args)
static switch_status_t play_group(say_gender_t gender, cases_t cases, int a, int b, int c, unit_t what, switch_say_file_handle_t *sh)
{
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play_group ! %d%d%d gender=%d causes=%d\n",a,b,c,gender,cases);
if (a) {
if (((b == 0) && (c == 0)) || (matrix[casus][say_type].all == 1)) { //если b и с равны 0 то сказать шестьсот, сестисотый, шестисотая
if (((b == 0) && (c == 0)) || (matrix[cases][gender].all == 1)) { //если b и с равны 0 то сказать шестьсот, сестисотый, шестисотая
if (what == million) { //префикс число окончание
say_file("digits/%s%d00%s.wav", matrix[casus][say_type].million[12], a, matrix[casus][say_type].million[13]);
say_file("digits/%s.wav", matrix[casus][say_type].million[11]);
switch_say_file(sh, "digits/%s%d00%s", matrix[cases][gender].million[12], a, matrix[cases][gender].million[13]);
switch_say_file(sh, "digits/%s", matrix[cases][gender].million[11]);
} else if (what == thousand) {
say_file("digits/%s%d00%s.wav", matrix[casus][say_type].thousand[12], a, matrix[casus][say_type].thousand[13]);
say_file("digits/%s.wav", matrix[casus][say_type].thousand[11]);
switch_say_file(sh, "digits/%s%d00%s", matrix[cases][gender].thousand[12], a, matrix[cases][gender].thousand[13]);
switch_say_file(sh, "digits/%s", matrix[cases][gender].thousand[11]);
} else {
say_file("digits/%s%d00%s.wav", matrix[casus][say_type].num[6], a, matrix[casus][say_type].num[7]);
switch_say_file(sh, "digits/%s%d00%s", matrix[cases][gender].num[6], a, matrix[cases][gender].num[7]);
}
} else { //если дальше есть цифры то тысячи и миллионы не прозносить пока
say_file("digits/%d00.wav", a);
switch_say_file(sh, "digits/%d00", a);
}
}
if (b) {
if (b > 1) { //если 20 и больше
if ((c == 0) || (matrix[casus][say_type].all == 1)) { //если с равны 0 то сказать 20, двадцати, двадцатая
if ((c == 0) || (matrix[cases][gender].all == 1)) { //если с равны 0 то сказать 20, двадцати, двадцатая
if (what == million) { //префикс число окончание
say_file("digits/%s%d0%s.wav", matrix[casus][say_type].million[12], b, matrix[casus][say_type].million[13]);
say_file("digits/%s.wav", matrix[casus][say_type].million[11]);
switch_say_file(sh, "digits/%s%d0%s", matrix[cases][gender].million[12], b, matrix[cases][gender].million[13]);
switch_say_file(sh, "digits/%s", matrix[cases][gender].million[11]);
} else if (what == thousand) {
say_file("digits/%s%d0%s.wav", matrix[casus][say_type].thousand[12], b, matrix[casus][say_type].thousand[13]);
say_file("digits/%s.wav", matrix[casus][say_type].thousand[11]);
switch_say_file(sh, "digits/%s%d0%s", matrix[cases][gender].thousand[12], b, matrix[cases][gender].thousand[13]);
switch_say_file(sh, "digits/%s", matrix[cases][gender].thousand[11]);
} else {
say_file("digits/%s%d0%s.wav", matrix[casus][say_type].num[6], b, matrix[casus][say_type].num[7]);
switch_say_file(sh, "digits/%s%d0%s", matrix[cases][gender].num[6], b, matrix[cases][gender].num[7]);
}
} else { //если есть дальше цифры
say_file("digits/%d0.wav", b);
switch_say_file(sh, "digits/%d0", b);
}
} else { //от 10 до 19
if (what == million) {
say_file("digits/%s%d%d%s.wav", matrix[casus][say_type].million[12], b, c, matrix[casus][say_type].million[13]);
say_file("digits/%s.wav", matrix[casus][say_type].million[11]);
switch_say_file(sh, "digits/%s%d%d%s", matrix[cases][gender].million[12], b, c, matrix[cases][gender].million[13]);
switch_say_file(sh, "digits/%s", matrix[cases][gender].million[11]);
} else if (what == thousand) {
say_file("digits/%s%d%d%s.wav", matrix[casus][say_type].thousand[12], b, c, matrix[casus][say_type].thousand[13]);
say_file("digits/%s.wav", matrix[casus][say_type].thousand[11]);
switch_say_file(sh, "digits/%s%d%d%s", matrix[cases][gender].thousand[12], b, c, matrix[cases][gender].thousand[13]);
switch_say_file(sh, "digits/%s", matrix[cases][gender].thousand[11]);
} else { //просто произнести цифры с префиксом и окончанием
say_file("digits/%s%d%d%s.wav", matrix[casus][say_type].num[6], b, c, matrix[casus][say_type].num[7]);
switch_say_file(sh, "digits/%s%d%d%s", matrix[cases][gender].num[6], b, c, matrix[cases][gender].num[7]);
}
c = 0;
}
@@ -123,28 +117,28 @@ static switch_status_t play_group(say_type_t say_type, casus_t casus, int a, int
if (c || what == zero) {
if (c <= 5) {
if (what == million) {
if ((strlen(matrix[casus][say_type].million[c * 2])) > 0) { // не произносить если не заданно например 1 миллион а просто миллион
say_file("digits/%s.wav", matrix[casus][say_type].million[c * 2])
if ((strlen(matrix[cases][gender].million[c * 2])) > 0) { // не произносить если не заданно например 1 миллион а просто миллион
switch_say_file(sh, "digits/%s", matrix[cases][gender].million[c * 2]);
}
say_file("digits/%s.wav", matrix[casus][say_type].million[c * 2 + 1]);
switch_say_file(sh, "digits/%s", matrix[cases][gender].million[c * 2 + 1]);
} else if (what == thousand) {
if ((strlen(matrix[casus][say_type].thousand[c * 2])) > 0) { // не произносить если не заданно например одна тысячас а просто тысяча
say_file("digits/%s.wav", matrix[casus][say_type].thousand[c * 2])
if ((strlen(matrix[cases][gender].thousand[c * 2])) > 0) { // не произносить если не заданно например одна тысячас а просто тысяча
switch_say_file(sh, "digits/%s", matrix[cases][gender].thousand[c * 2]);
}
say_file("digits/%s.wav", matrix[casus][say_type].thousand[c * 2 + 1]);
switch_say_file(sh, "digits/%s", matrix[cases][gender].thousand[c * 2 + 1]);
} else { //просто произнести цифры с префиксом и окончанием
say_file("digits/%s.wav", matrix[casus][say_type].num[c]);
switch_say_file(sh, "digits/%s", matrix[cases][gender].num[c]);
}
} else { /* больше 5 */
if (what == million) {
say_file("digits/%s%d%s.wav", matrix[casus][say_type].million[12], c, matrix[casus][say_type].million[13]);
say_file("digits/%s.wav", matrix[casus][say_type].million[11]);
switch_say_file(sh, "digits/%s%d%s", matrix[cases][gender].million[12], c, matrix[cases][gender].million[13]);
switch_say_file(sh, "digits/%s", matrix[cases][gender].million[11]);
} else if (what == thousand) {
say_file("digits/%s%d%s.wav", matrix[casus][say_type].thousand[12], c, matrix[casus][say_type].thousand[13]);
say_file("digits/%s.wav", matrix[casus][say_type].thousand[11]);
switch_say_file(sh, "digits/%s%d%s", matrix[cases][gender].thousand[12], c, matrix[cases][gender].thousand[13]);
switch_say_file(sh, "digits/%s", matrix[cases][gender].thousand[11]);
} else { //просто произнести цифры с префиксом и окончанием
say_file("digits/%s%d%s.wav", matrix[casus][say_type].num[6], c, matrix[casus][say_type].num[7]);
switch_say_file(sh, "digits/%s%d%s", matrix[cases][gender].num[6], c, matrix[cases][gender].num[7]);
}
}
}
@@ -152,7 +146,7 @@ static switch_status_t play_group(say_type_t say_type, casus_t casus, int a, int
}
static switch_status_t ru_say_count(switch_core_session_t *session, char *tosay, say_type_t say_type, casus_t casus, switch_input_args_t *args)
static switch_status_t ru_say_count(switch_say_file_handle_t *sh, char *tosay, say_gender_t gender, cases_t cases)
{
int in;
int x = 0;
@@ -162,10 +156,10 @@ static switch_status_t ru_say_count(switch_core_session_t *session, char *tosay,
switch_status_t status;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ru_say_count %s!\n", tosay);
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ru_say_count %s! gender=%d causes=%d\n", tosay,gender,cases);
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
@@ -182,44 +176,40 @@ static switch_status_t ru_say_count(switch_core_session_t *session, char *tosay,
//миллионы
if (places[8] || places[7] || places[6]) {
if ((in_ % 1000000 > 0) && (matrix[casus][say_type].all != 1)) { // если поле миллионов есть цифры поизнести как числительое именительного падежа
if ((status = play_group(male_c, nominativus, places[8], places[7], places[6], million, session, args)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d million! status=%d\n", places[8], places[7], places[6],
status);
if ((in_ % 1000000 > 0) && (matrix[cases][gender].all != 1)) { // если поле миллионов есть цифры поизнести как числительое именительного падежа
if ((status = play_group(male, nominativus, places[8], places[7], places[6], million, sh)) != SWITCH_STATUS_SUCCESS) {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d million! status=%d\n", places[8], places[7], places[6], status);
return status;
}
} else { // иначе произнести в нужном падеже
if ((status = play_group(say_type, casus, places[8], places[7], places[6], million, session, args)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d million! status=%d\n", places[8], places[7], places[6],
status);
if ((status = play_group(gender, cases, places[8], places[7], places[6], million, sh)) != SWITCH_STATUS_SUCCESS) {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d million! status=%d\n", places[8], places[7], places[6], status);
return status;
}
}
}
//тысячи
if (places[5] || places[4] || places[3]) {
if ((in_ % 1000 > 0) && (matrix[casus][say_type].all != 1)) { // если поле миллионов есть цифры поизнести как числительое именительного падежа
if ((status = play_group(male_c, nominativus, places[5], places[4], places[3], thousand, session, args)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d thousand! status=%d\n", places[5], places[4], places[3],
status);
if ((in_ % 1000 > 0) && (matrix[cases][gender].all != 1)) { // если поле миллионов есть цифры поизнести как числительое именительного падежа
if ((status = play_group(male, nominativus, places[5], places[4], places[3], thousand, sh)) != SWITCH_STATUS_SUCCESS) {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d thousand! status=%d\n", places[5], places[4], places[3], status);
return status;
}
} else { // иначе произнести в нужном падеже
if ((status = play_group(say_type, casus, places[5], places[4], places[3], thousand, session, args)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d thousand! status=%d\n", places[5], places[4], places[3],
status);
if ((status = play_group(gender, cases, places[5], places[4], places[3], thousand, sh)) != SWITCH_STATUS_SUCCESS) {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d thousand! status=%d\n", places[5], places[4], places[3], status);
return status;
}
}
}
// сотни
if ((status = play_group(say_type, casus, places[2], places[1], places[0], empty, session, args)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d thousand! status=%d\n", places[5], places[4], places[3], status);
if ((status = play_group(gender, cases, places[2], places[1], places[0], empty, sh)) != SWITCH_STATUS_SUCCESS) {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d thousand! status=%d\n", places[5], places[4], places[3], status);
return status;
}
} else {
if ((status = play_group(say_type, casus, places[2], places[1], places[0], zero, session, args)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d other!\n", places[2], places[1], places[0]);
if ((status = play_group(gender, cases, places[2], places[1], places[0], zero, sh)) != SWITCH_STATUS_SUCCESS) {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "play group %d %d %d other!\n", places[2], places[1], places[0]);
return status;
}
}
@@ -228,28 +218,37 @@ static switch_status_t ru_say_count(switch_core_session_t *session, char *tosay,
}
//дописать
static switch_status_t ru_say_general_count(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
static switch_status_t ru_say_general_count(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args,say_opt_t *say_opt)
{
switch_status_t status;
casus_t casus; //падеж
say_type_t say_type; //тип произношения
cases_t cases; //падеж
say_gender_t gender; //тип произношения
switch (say_args->type) {
case SST_MESSAGES:
say_type = it_c;
casus = nominativus;
gender = it;
cases = nominativus;
break;
default:
say_type = male_c;
casus = nominativus;
gender = male;
cases = nominativus;
if (say_opt->gender>0) {
gender=say_opt->gender;
// //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " opt_gender=%d type=%d cases=%d\n", gender, cases,say_opt->gender);
}
if (say_opt->cases>0) {
cases=say_opt->cases;
// //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " opt_gender=%d type=%d cases=%d\n", gender, cases,say_opt->gender);
}
break;
};
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " type=%d casus=%d\n", say_type, casus);
status = ru_say_count(session, tosay, say_type, casus, args);
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " opt_gender=%d type=%d cases=%d\n", gender, cases,say_opt->gender);
status = ru_say_count(sh, tosay, (say_gender_t)gender, (cases_t)cases);
return status;
}
static switch_status_t ru_say_money(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
static switch_status_t ru_say_money(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args,say_opt_t *say_opt)
{
char sbuf[16] = "";
char *rubles = NULL;
@@ -258,11 +257,10 @@ static switch_status_t ru_say_money(switch_core_session_t *session, char *tosay,
int iruble = 0;
int ikopecks = 0;
int ikopeck = 0;
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " ru_say_money %s say_opt->currency=%d\n", tosay,say_opt->currency);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " ru_say_money %s\n", tosay);
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
@@ -279,58 +277,66 @@ static switch_status_t ru_say_money(switch_core_session_t *session, char *tosay,
}
if (sbuf[0] == '-') {
say_file("currency/minus.wav");
switch_say_file(sh, "currency/minus");
rubles++;
}
ru_say_count(session, rubles, male_c, nominativus, args);
ru_say_count(sh, rubles, matrix_currency[say_opt->currency].first_gender,matrix_currency[say_opt->currency].first_cases);
if (rubles) {
irubles = atoi(rubles) % 100;
iruble = atoi(rubles) % 10;
}
if (irubles == 1 || (irubles > 20 && iruble == 1)) { /* рубль */
say_file("currency/ruble.wav");
} else if ((irubles > 1 && irubles < 5) || (irubles > 20 && iruble > 1 && iruble < 5)) { /*рубля */
say_file("currency/ruble-a.wav");
} else { /*рублей */
say_file("currency/rubles.wav");
if (iruble<5) {
if ((irubles>10)&&(irubles<15)) {
switch_say_file(sh, "currency/%s",matrix_currency->first[5]);
}
else {
switch_say_file(sh, "currency/%s",matrix_currency->first[iruble]);
}
}
else {
switch_say_file(sh, "currency/%s",matrix_currency->first[5]);
}
/* Say kopecks */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " %s\n", kopecks);
ru_say_count(session, kopecks, female_c, nominativus, args);
ru_say_count(sh, kopecks, matrix_currency[say_opt->currency].second_gender,matrix_currency[say_opt->currency].second_cases);
if (kopecks) {
ikopecks = atoi(kopecks) % 100;
ikopeck = atoi(kopecks) % 10;
}
if (ikopecks == 1 || (ikopecks > 20 && ikopeck == 1)) {
/* копейка */
say_file("currency/kopeck.wav");
} else if ((ikopecks > 1 && ikopecks < 5) || (ikopecks > 20 && ikopeck > 1 && ikopeck < 5)) {
/* копейки */
say_file("currency/kopeck-i.wav");
} else {
/* копеек */
say_file("currency/kopecks.wav");
if (ikopeck<5) {
if ((ikopecks>10)&&(ikopecks<15)) {
switch_say_file(sh, "currency/%s",matrix_currency->second[5]);
}
else {
switch_say_file(sh, "currency/%s",matrix_currency->second[ikopeck]);
}
}
else {
switch_say_file(sh, "currency/%s",matrix_currency->second[5]);
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t ru_say_time(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
static switch_status_t ru_say_time(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args,say_opt_t *say_opt)
{
int32_t t;
char buf[80];
switch_time_t target = 0, target_now = 0;
switch_time_exp_t tm, tm_now;
uint8_t say_date = 0, say_time = 0, say_year = 0, say_month = 0, say_dow = 0, say_day = 0, say_yesterday = 0, say_today = 0;
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *tz = switch_channel_get_variable(channel, "timezone");
const char *tz = NULL;
tz = switch_say_file_handle_get_variable(sh, "timezone");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " ru_say_time %s type=%d method=%d\n", tosay, say_args->type, say_args->method);
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, " ru_say_time %s type=%d method=%d\n", tosay, say_args->type, say_args->method);
if (say_args->type == SST_TIME_MEASUREMENT) {
int64_t hours = 0;
@@ -339,7 +345,7 @@ static switch_status_t ru_say_time(switch_core_session_t *session, char *tosay,
int64_t r = 0;
if (strchr(tosay, ':')) {
char *tme = switch_core_session_strdup(session, tosay);
char *tme = strdup(tosay);
char *p;
if ((p = strrchr(tme, ':'))) {
@@ -355,6 +361,7 @@ static switch_status_t ru_say_time(switch_core_session_t *session, char *tosay,
minutes = atoi(tme);
}
}
free(tme);
} else {
if ((seconds = atol(tosay)) <= 0) {
seconds = (int64_t) switch_epoch_time_now(NULL);
@@ -373,37 +380,37 @@ static switch_status_t ru_say_time(switch_core_session_t *session, char *tosay,
}
switch_snprintf(buf, sizeof(buf), "%u", (unsigned) hours);
ru_say_count(session, buf, male_c, nominativus, args);
ru_say_count(sh, buf, male, nominativus);
if (((hours % 10) == 1) && (hours != 11)) {
/* час */
say_file("time/hour.wav");
switch_say_file(sh, "time/hour");
} else if (((hours % 10 > 1) && (hours % 10 < 5)) && ((hours < 12) || (hours > 14))) {
say_file("time/hours-a.wav"); /* часа */
switch_say_file(sh, "time/hours-a"); /* часа */
} else {
say_file("time/hours.wav"); /* часов */
switch_say_file(sh, "time/hours"); /* часов */
}
switch_snprintf(buf, sizeof(buf), "%u", (unsigned) minutes); //перевести минуты в *char
ru_say_count(session, buf, female_c, nominativus, args);
ru_say_count(sh, buf, female, nominativus);
if (((minutes % 10) == 1) && (minutes != 11)) {
say_file("time/minute.wav"); //минута
switch_say_file(sh, "time/minute"); //минута
} else if (((minutes % 10 > 1) && (minutes % 10 < 5)) && ((minutes < 12) || (minutes > 14))) {
say_file("time/minutes-i.wav"); // минуты
switch_say_file(sh, "time/minutes-i"); // минуты
} else {
say_file("time/minutes.wav"); //минут
switch_say_file(sh, "time/minutes"); //минут
}
if (seconds != 0) {
switch_snprintf(buf, sizeof(buf), "%u", (unsigned) seconds);
ru_say_count(session, buf, female_c, nominativus, args);
ru_say_count(sh, buf, female, nominativus);
if (((seconds % 10) == 1) && (seconds != 11)) {
say_file("time/second.wav"); // секунда
switch_say_file(sh, "time/second"); // секунда
} else if (((seconds % 10 > 1) && (seconds % 10 < 5)) && ((seconds < 12) || (seconds > 14))) {
say_file("time/seconds-i.wav"); // секуны
switch_say_file(sh, "time/seconds-i"); // секуны
} else {
say_file("time/seconds.wav"); //секунд
switch_say_file(sh, "time/seconds"); //секунд
}
}
return SWITCH_STATUS_SUCCESS;
@@ -419,6 +426,7 @@ static switch_status_t ru_say_time(switch_core_session_t *session, char *tosay,
if (tz) {
int check = atoi(tz);
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Timezone is [%s]\n", tz);
if (check) {
switch_time_exp_tz(&tm, target, check);
switch_time_exp_tz(&tm_now, target_now, check);
@@ -472,13 +480,13 @@ static switch_status_t ru_say_time(switch_core_session_t *session, char *tosay,
}
if (say_today) {
say_file("time/today.wav");
switch_say_file(sh, "time/today");
}
if (say_yesterday) {
say_file("time/yesterday.wav");
switch_say_file(sh, "time/yesterday");
}
if (say_dow) {
say_file("time/day-%d.wav", tm.tm_wday);
switch_say_file(sh, "time/day-%d", tm.tm_wday);
}
if (say_date) {
say_year = say_month = say_day = say_dow = 1;
@@ -486,74 +494,103 @@ static switch_status_t ru_say_time(switch_core_session_t *session, char *tosay,
}
if (say_day) {
switch_snprintf(buf, sizeof(buf), "%u", (unsigned) tm.tm_mday);
ru_say_count(session, buf, male_h, genitivus, args);
ru_say_count(sh, buf, male_h, genitivus);
}
if (say_month) {
say_file("time/mon-%d.wav", tm.tm_mon);
switch_say_file(sh, "time/mon-%d", tm.tm_mon);
}
if (say_year) {
switch_snprintf(buf, sizeof(buf), "%u", (unsigned) (tm.tm_year + 1900));
ru_say_count(session, buf, male_h, genitivus, args);
say_file("time/h-year.wav");
}
if (say_month || say_year || say_date || say_dow) {
say_file("time/at.wav");
ru_say_count(sh, buf, male_h, genitivus);
switch_say_file(sh, "time/h-year");
}
if (say_time) {
if (say_month || say_year || say_date || say_dow) {
switch_say_file(sh, "time/at");
}
switch_snprintf(buf, sizeof(buf), "%d:%d:%d", tm.tm_hour, tm.tm_min, tm.tm_sec);
say_args->type = SST_TIME_MEASUREMENT;
ru_say_time(session, buf, say_args, args);
ru_say_time(sh, buf, say_args,say_opt);
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t ru_ip(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
static switch_status_t ru_ip(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args,say_opt_t *say_opt)
{
char *a, *b, *c, *d;
if (!(a = switch_core_session_strdup(session, tosay))) {
return SWITCH_STATUS_FALSE;
switch_status_t status = SWITCH_STATUS_FALSE;
if (!(a = strdup(tosay))) {
abort();
// return SWITCH_STATUS_FALSE;
}
if (!(b = strchr(a, '.'))) {
return SWITCH_STATUS_FALSE;
goto end;
}
*b++ = '\0';
if (!(c = strchr(b, '.'))) {
return SWITCH_STATUS_FALSE;
goto end;
}
*c++ = '\0';
if (!(d = strchr(c, '.'))) {
return SWITCH_STATUS_FALSE;
goto end;
}
*d++ = '\0';
ru_say_count(session, a, male_c, nominativus, args);
say_file("digits/dot.wav");
ru_say_count(sh, a, male, nominativus);
switch_say_file(sh, "digits/dot");
ru_say_count(session, b, male_c, nominativus, args);
say_file("digits/dot.wav");
ru_say_count(sh, b, male, nominativus);
switch_say_file(sh, "digits/dot");
ru_say_count(session, c, male_c, nominativus, args);
say_file("digits/dot.wav");
ru_say_count(sh, c, male, nominativus);
switch_say_file(sh, "digits/dot");
ru_say_count(session, d, male_c, nominativus, args);
return SWITCH_STATUS_SUCCESS;
ru_say_count(sh, d, male, nominativus);
end:
free(a);
return status;
}
static switch_status_t ru_say(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
{
switch_say_callback_t say_cb = NULL;
static switch_status_t ru_say_spell(switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args,say_opt_t *say_opt)
{
char *p;
for (p = tosay; p && *p; p++) {
int a = tolower((int) *p);
if (a >= '0' && a <= '9') {
switch_say_file(sh, "digits/%c", a);
} else {
if (say_args->type == SST_NAME_SPELLED) {
switch_say_file(sh, "ascii/%d", a);
} else if (say_args->type == SST_NAME_PHONETIC) {
switch_say_file(sh, "phonetic-ascii/%d", a);
}
}
}
return SWITCH_STATUS_SUCCESS;
}
static switch_new_say_callback_ru_t choose_callback(switch_say_args_t *say_args)
{
switch_new_say_callback_ru_t say_cb = NULL;
switch (say_args->type) {
case SST_NUMBER:
case SST_ITEMS:
case SST_PERSONS:
case SST_MESSAGES:
say_cb = ru_say_general_count;
break;
case SST_TIME_MEASUREMENT:
@@ -576,23 +613,176 @@ static switch_status_t ru_say(switch_core_session_t *session, char *tosay, switc
break;
case SST_NAME_SPELLED:
case SST_NAME_PHONETIC:
return switch_ivr_say_spell(session, tosay, say_args, args);
say_cb = ru_say_spell;
break;
case SST_CURRENCY:
say_cb = ru_say_money;
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown Say type=[%d]\n", say_args->type);
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown Say type=[%d]\n", say_args->type);
break;
}
if (say_cb) {
return say_cb(session, tosay, say_args, args);
}
return SWITCH_STATUS_FALSE;
return say_cb;
}
static switch_status_t run_callback(switch_new_say_callback_ru_t say_cb, char *tosay, switch_say_args_t *say_args, switch_core_session_t *session, char **rstr)
{
switch_say_file_handle_t *sh;
switch_status_t status = SWITCH_STATUS_FALSE;
switch_event_t *var_event = NULL;
const char *cases=NULL;
const char *gender=NULL;
const char *currency=NULL;
say_opt_t say_opt;
say_opt.cases=0;
say_opt.gender=0;
say_opt.currency=0;
if (session) {
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_channel_get_variables(channel, &var_event);
// проверяем не заданы ли канальные переменные род, падеж, валюта
gender = switch_channel_get_variable(channel, "gender");
cases = switch_channel_get_variable(channel, "cases");
currency = switch_channel_get_variable(channel, "currency");
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ru_say!!! %s %s %s !\n",gender, cases,currency);
if (cases) {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ru_say!!! %s!\n", cases);
if ((strcmp(cases,"nominativus")==0) || (strcmp(cases,"именительный")==0)) {
say_opt.cases=(cases_t)0;
}
if ((strcmp(cases,"genitivus")==0) || (strcmp(cases,"родительный")==0)) {
say_opt.cases=(cases_t)1;
}
if ((strcmp(cases,"dativus")==0) || (strcmp(cases,"дательный")==0)) {
say_opt.cases=(cases_t)2;
}
if ((strcmp(cases,"accusativus_a")==0) || (strcmp(cases,"винительный_о")==0)) {
say_opt.cases=(cases_t)3;
}
if ((strcmp(cases,"accusativus_i")==0) || (strcmp(cases,"винительный_н")==0)) {
say_opt.cases=(cases_t)4;
}
if ((strcmp(cases,"instrumentalis")==0) || (strcmp(cases,"творительный")==0)) {
say_opt.cases=(cases_t)5;
}
if ((strcmp(cases,"prepositive")==0) || (strcmp(cases,"предложный")==0)) {
say_opt.cases=(cases_t)6;
}
}
if (gender) {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ru_say!!! %s!\n", gender);
if ((strcmp(gender,"male")==0) || (strcmp(gender,"мужской")==0)) {
say_opt.gender=(say_gender_t)0;
}
if ((strcmp(gender,"it")==0) || (strcmp(gender,"средний")==0)) {
say_opt.gender=(say_gender_t)1;
}
if ((strcmp(gender,"female")==0) || (strcmp(gender,"женский")==0)) {
say_opt.gender=(say_gender_t)2;
}
if ((strcmp(gender,"plural")==0) || (strcmp(gender,"множественное")==0)) {
say_opt.gender=(say_gender_t)3;
}
if ((strcmp(gender,"male_h")==0) || (strcmp(gender,"мужской_порядковый")==0)) {
say_opt.gender=(say_gender_t)4;
}
if ((strcmp(gender,"it_h")==0) || (strcmp(gender,"средний_порядковый")==0)) {
say_opt.gender=(say_gender_t)5;
}
if ((strcmp(gender,"female_h")==0) || (strcmp(gender,"женский_порядковый")==0)) {
say_opt.gender=(say_gender_t)6;
}
if ((strcmp(gender,"plural_h")==0) || (strcmp(gender,"множественное_порядковый")==0)) {
say_opt.gender=(say_gender_t)7;
}
}
if (currency) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ru_say!!! %s!\n", currency);
if ((strcmp(currency,"ruble")==0) || (strcmp(currency,"рубль")==0)) {
say_opt.currency=(currency_t)0;
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "rul!!! \n");
}
if ((strcmp(currency,"dollar")==0) || (strcmp(currency,"доллар")==0)) {
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "dollar!!! !\n");
say_opt.currency=(currency_t)1;
}
}
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ru_say!!! %s! say_opt.gender=%d say_opt.cases=%d\n", tosay,say_opt.gender,say_opt.cases);
}
switch_say_file_handle_create(&sh, say_args->ext, &var_event);
//запуск ru_ip,ru_say_money ...
status = say_cb(sh, tosay, say_args,&say_opt);
if ((*rstr = switch_say_file_handle_detach_path(sh))) {
status = SWITCH_STATUS_SUCCESS;
}
switch_say_file_handle_destroy(&sh);
return status;
}
static switch_status_t ru_say(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
{
switch_new_say_callback_ru_t say_cb = NULL;
char *string = NULL;
switch_status_t status;
status = SWITCH_STATUS_FALSE;
say_cb = choose_callback(say_args);
if (say_cb) {
status = run_callback(say_cb, tosay, say_args, session, &string);
if (session && string) {
status = switch_ivr_play_file(session, NULL, string, args);
}
switch_safe_free(string);
}
return status;
}
static switch_status_t ru_say_string(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, char **rstr)
{
switch_new_say_callback_ru_t say_cb = NULL;
char *string = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
say_cb = choose_callback(say_args);
if (say_cb) {
status = run_callback(say_cb, tosay, say_args, session, &string);
if (string) {
status = SWITCH_STATUS_SUCCESS;
*rstr = string;
}
}
return status;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_say_ru_load)
{
switch_say_interface_t *say_interface;
@@ -601,6 +791,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_say_ru_load)
say_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_SAY_INTERFACE);
say_interface->interface_name = "ru";
say_interface->say_function = ru_say;
say_interface->say_string_function = ru_say_string;
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
+65 -23
View File
@@ -12,6 +12,8 @@
//http://ru.wiktionary.org/wiki/%D0%BE%D0%B4%D0%B8%D0%BD
//http://ru.wiktionary.org/wiki/%D0%BF%D0%B5%D1%80%D0%B2%D1%8B%D0%B9
typedef enum {
million,
thousand,
@@ -22,29 +24,43 @@ typedef enum {
//тип числа порядковое или количественное
typedef enum {
nominativus, // именительный Кто? Что?
genitivus, // Родительный Кого? Чего?
dativus, // дательный Кого? Что?
genitivus, // Родительный Кого? Чего?
dativus, // дательный Кого? Что?
accusativus_a, // Винительный Кого? animate - одушевлённый
accusativus_i, // Винительный Что? inanimate - неодушевлённый
instrumentalis, // Творительный Кем? Чем?
prepositive // Предложный О ком? О чём?
} casus_t;
prepositive // Предложный О ком? О чём?
} cases_t;
typedef enum {
//количественный
male_c, //мужского пола
it_c, //среднего
female_c, //женского
plural_c, //множественное число
male, //мужского пола
it, //среднего
female, //женского
plural, //множественное число
//порядковый
male_h, //порядковое мужского пола
it_h, //порядковое среднего
female_h, //порядковое женского
plural_h //порядковое множественное число
} say_type_t;
male_h, //порядковое мужского пола
it_h, //порядковое среднего
female_h, //порядковое женского
plural_h //порядковое множественное число
} say_gender_t;
typedef enum {
ruble,
dollar,
euro
} currency_t;
typedef struct {
say_gender_t gender;
cases_t cases;
currency_t currency;
} say_opt_t;
struct say_t {
char *num[8];
@@ -52,7 +68,31 @@ struct say_t {
char *million[14];
int all;
};
struct say_cur_t {
char *first[6];
say_gender_t first_gender;
cases_t first_cases;
char *second[6];
say_gender_t second_gender;
cases_t second_cases;
};
// описываем как произносить валяюты от 0 до 5 дальше идёт номер рода и падежа (с нуля)
//рубли
#define c_0 {{"rubles","ruble","ruble-a","ruble-a","ruble-a","rubles"},male,nominativus,\
{"kopecks","kopeck","kopeck-i","kopeck-i","kopeck-i","kopecks"},female,nominativus}
#define c_1 {{"dollars","dollar","dollara","dollara","dollara","dollars"},male,nominativus,\
{"centov","cent","centa","centa","centa","centov"},male,nominativus}
#define c_2 {{"rubles","ruble","ruble-a","ruble-a","ruble-a","rubles"},male,nominativus,\
{"kopecks","kopeck","kopeck-i","kopeck-i","kopeck-i","kopecks"},female,nominativus}
typedef switch_status_t (*switch_new_say_callback_ru_t) (switch_say_file_handle_t *sh, char *tosay, switch_say_args_t *say_args,say_opt_t *say_opt);
//именительный
//именительный количественный/числительное
@@ -60,7 +100,7 @@ struct say_t {
//мужской род родительный падеж
//первая строка описывае как произносить цифры от 0 до 5 потом пристаставка и окончания для остальных
// тоже самое для тысяч и миллионов, только ещё с произношением тысяч и миллионов в вонце так же окончание для цифр
// тоже самое для тысяч и миллионов, только ещё с произношением тысяч и миллионов в конце так же окончание для цифр
// как произносить тысячи и миллионы берёт с цифры 5
#define m_00 {\
@@ -96,23 +136,25 @@ struct say_t {
//порядковый
//мужской
#define m_04 {\
{"","","","","","","",""},\
{"","","","","","","","","","","","","",""},\
{"","","","","","","","","","","","","",""},\
{"h-0m","h-1m","h-2m","h-3m","h-4m","h-5m","h-","m"},\
{"","","1f","thousand","2f","thousands-i","3","thousands-i","4","thousands-i","5","thousands","",""},\
{"","","","million","2","million-a","3","million-a","4","million-a","5","millions","",""},\
0,\
}\
//средний
#define m_05 {\
{"","","","","","","",""},\
{"","","","","","","","","","","","","",""},\
{"","","","","","","","","","","","","",""},\
{"0","1n","2","3","4","5","",""},\
{"","","1f","thousand","2f","thousands-i","3","thousands-i","4","thousands-i","5","thousands","",""},\
{"","","","million","2","million-a","3","million-a","4","million-a","5","millions","",""},\
0,\
}\
//женский
#define m_06 {\
{"","","","","","","",""},\
{"","","","","","","","","","","","","",""},\
{"","","","","","","","","","","","","",""},\
{"h-0f","h-1f","h-2f","h-3f","h-4f","h-5f","h-","f"},\
{"","","1f","thousand","2f","thousands-i","3","thousands-i","4","thousands-i","5","thousands","",""},\
{"","","1","million","2","million-a","3","million-a","4","million-a","5","millions","",""},\
0,\
}\
+16 -12
View File
@@ -90,11 +90,24 @@ SWITCH_MODULE_DEFINITION(mod_say_th, mod_say_th_load, NULL, NULL);
static switch_status_t th_say_general_count(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
{
int in;
char sbuf[13] = "";
char sbuf[128] = "";
char digits[11];
int i;
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
if (say_args->method == SSM_ITERATED) {
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
return SWITCH_STATUS_SUCCESS;
}
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
@@ -206,15 +219,6 @@ static switch_status_t th_say_general_count(switch_core_session_t *session, char
}
}
break;
case SSM_ITERATED:
{
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
}
break;
default:
break;
}
@@ -422,7 +426,7 @@ static switch_status_t th_say_money(switch_core_session_t *session, char *tosay,
char *dollars = NULL;
char *cents = NULL;
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
+16 -12
View File
@@ -89,11 +89,24 @@ SWITCH_MODULE_DEFINITION(mod_say_zh, mod_say_zh_load, NULL, NULL);
static switch_status_t zh_say_general_count(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
{
int in;
char sbuf[13] = "";
char sbuf[128] = "";
char digits[11];
int i;
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf))) || strlen(tosay) > 9) {
if (say_args->method == SSM_ITERATED) {
if ((tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1))) {
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
return SWITCH_STATUS_SUCCESS;
}
if (!(tosay = switch_strip_commas(tosay, sbuf, sizeof(sbuf)-1)) || strlen(tosay) > 9) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
@@ -170,15 +183,6 @@ static switch_status_t zh_say_general_count(switch_core_session_t *session, char
}
}
break;
case SSM_ITERATED:
{
char *p;
for (p = tosay; p && *p; p++) {
say_file("digits/%c.wav", *p);
}
}
break;
default:
break;
}
@@ -386,7 +390,7 @@ static switch_status_t zh_say_money(switch_core_session_t *session, char *tosay,
char *dollars = NULL;
char *cents = NULL;
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)))) {
if (strlen(tosay) > 15 || !(tosay = switch_strip_nonnumerics(tosay, sbuf, sizeof(sbuf)-1))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
+8 -2
View File
@@ -200,7 +200,7 @@ void WINAPI ServiceCtrlHandler(DWORD control)
/* the main service entry point */
void WINAPI service_main(DWORD numArgs, char **args)
{
switch_core_flag_t flags = SCF_USE_SQL | SCF_USE_AUTO_NAT | SCF_CALIBRATE_CLOCK | SCF_USE_CLOCK_RT;
switch_core_flag_t flags = SCF_USE_SQL | SCF_USE_AUTO_NAT | SCF_USE_NAT_MAPPING | SCF_CALIBRATE_CLOCK | SCF_USE_CLOCK_RT;
const char *err = NULL; /* error value for return from freeswitch initialization */
/* Override flags if they have been set earlier */
@@ -364,7 +364,7 @@ int main(int argc, char *argv[])
#ifdef __sun
switch_core_flag_t flags = SCF_USE_SQL;
#else
switch_core_flag_t flags = SCF_USE_SQL | SCF_USE_AUTO_NAT | SCF_CALIBRATE_CLOCK | SCF_USE_CLOCK_RT;
switch_core_flag_t flags = SCF_USE_SQL | SCF_USE_AUTO_NAT | SCF_USE_NAT_MAPPING | SCF_CALIBRATE_CLOCK | SCF_USE_CLOCK_RT;
#endif
int ret = 0;
switch_status_t destroy_status;
@@ -412,6 +412,7 @@ int main(int argc, char *argv[])
"\t-nosql -- disable internal sql scoreboard\n"
"\t-heavy-timer -- Heavy Timer, possibly more accurate but at a cost\n"
"\t-nonat -- disable auto nat detection\n"
"\t-nonatmap -- disable auto nat port mapping\n"
"\t-nocal -- disable clock calibration\n"
"\t-nort -- disable clock clock_realtime\n"
"\t-stop -- stop freeswitch\n"
@@ -581,6 +582,11 @@ int main(int argc, char *argv[])
known_opt++;
}
if (local_argv[x] && !strcmp(local_argv[x], "-nonatmap")) {
flags &= ~SCF_USE_NAT_MAPPING;
known_opt++;
}
if (local_argv[x] && !strcmp(local_argv[x], "-heavy-timer")) {
flags |= SCF_USE_HEAVY_TIMING;
known_opt++;
+59 -51
View File
@@ -2456,8 +2456,8 @@ SWITCH_DECLARE(void) switch_channel_flip_cid(switch_channel_t *channel)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session), SWITCH_LOG_INFO, "%s Flipping CID from \"%s\" <%s> to \"%s\" <%s>\n",
switch_channel_get_name(channel),
switch_channel_get_variable(channel, "pre_transfer_caller_id_name"),
switch_channel_get_variable(channel, "pre_transfer_caller_id_number"),
switch_str_nil(switch_channel_get_variable(channel, "pre_transfer_caller_id_name")),
switch_str_nil(switch_channel_get_variable(channel, "pre_transfer_caller_id_number")),
channel->caller_profile->caller_id_name,
channel->caller_profile->caller_id_number
);
@@ -2588,8 +2588,6 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_ring_ready_value(swi
switch_ring_ready_t rv,
const char *file, const char *func, int line)
{
const char *var;
char *app;
switch_event_t *event;
if (!switch_channel_test_flag(channel, CF_RING_READY) &&
@@ -2619,21 +2617,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_ring_ready_value(swi
switch_event_fire(&event);
}
var = switch_channel_get_variable(channel, SWITCH_CHANNEL_EXECUTE_ON_RING_VARIABLE);
if (var) {
char *arg = NULL;
app = switch_core_session_strdup(channel->session, var);
if (strstr(app, "::")) {
switch_core_session_execute_application_async(channel->session, app, arg);
} else {
if ((arg = strchr(app, ' '))) {
*arg++ = '\0';
}
switch_core_session_execute_application(channel->session, app, arg);
}
}
switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_RING_VARIABLE);
return SWITCH_STATUS_SUCCESS;
}
@@ -2645,7 +2629,6 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_pre_answered(switch_
{
switch_event_t *event;
const char *var = NULL;
char *app;
if (!switch_channel_test_flag(channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(channel, CF_ANSWERED)) {
const char *uuid;
@@ -2678,20 +2661,9 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_pre_answered(switch_
switch_mutex_unlock(channel->profile_mutex);
}
if (((var = switch_channel_get_variable(channel, SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE)) ||
(var = switch_channel_get_variable(channel, SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE))) && !zstr(var)) {
char *arg = NULL;
app = switch_core_session_strdup(channel->session, var);
if (strstr(app, "::")) {
switch_core_session_execute_application_async(channel->session, app, arg);
} else {
if ((arg = strchr(app, ' '))) {
*arg++ = '\0';
}
switch_core_session_execute_application(channel->session, app, arg);
if (switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE) != SWITCH_STATUS_SUCCESS) {
if (!switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE);
}
}
@@ -2785,6 +2757,42 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_ring_ready_value(switch_c
return status;
}
SWITCH_DECLARE(switch_status_t) switch_channel_execute_on(switch_channel_t *channel, const char *variable_prefix)
{
switch_event_header_t *hi;
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;
if (!strncasecmp(var, variable_prefix, strlen(variable_prefix))) {
char *arg = NULL;
x++;
app = switch_core_session_strdup(channel->session, val);
if (strstr(app, "::")) {
switch_core_session_execute_application_async(channel->session, app, arg);
} else {
if ((arg = strchr(app, ' '))) {
*arg++ = '\0';
}
switch_core_session_execute_application(channel->session, app, arg);
}
}
}
switch_event_destroy(&event);
return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_answered(switch_channel_t *channel, const char *file, const char *func, int line)
{
switch_event_t *event;
@@ -2852,21 +2860,10 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_answered(switch_chan
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Channel [%s] has been answered\n",
channel->name);
if (((var = switch_channel_get_variable(channel, SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE)) ||
(!switch_channel_test_flag(channel, CF_EARLY_MEDIA) && (var = switch_channel_get_variable(channel, SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE))))
&& !zstr(var)) {
char *arg = NULL;
app = switch_core_session_strdup(channel->session, var);
if (strstr(app, "::")) {
switch_core_session_execute_application_async(channel->session, app, arg);
} else {
if ((arg = strchr(app, ' '))) {
*arg++ = '\0';
}
switch_core_session_execute_application(channel->session, app, arg);
if (switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE) != SWITCH_STATUS_SUCCESS) {
if (!switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE);
}
}
@@ -2943,7 +2940,7 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
char *data, *indup, *endof_indup;
size_t sp = 0, len = 0, olen = 0, vtype = 0, br = 0, cpos, block = 128;
char *cloned_sub_val = NULL, *sub_val = NULL;
char *func_val = NULL;
char *func_val = NULL, *sb = NULL;
int nv = 0;
if (zstr(in)) {
@@ -3033,8 +3030,19 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
}
p = e > endof_indup ? endof_indup : e;
if ((vval = strchr(vname, '(')) || (vval = strchr(vname, ' '))) {
if (*vval == '(') br = 1;
vval = NULL;
for(sb = vname; sb && *sb; sb++) {
if (*sb == ' ') {
vval = sb;
break;
} else if (*sb == '(') {
vval = sb;
br = 1;
break;
}
}
if (vval) {
e = vval - 1;
*vval++ = '\0';
while (*e == ' ') {
+6 -6
View File
@@ -1404,7 +1404,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc
}
if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) {
switch_nat_init(runtime.memory_pool);
switch_nat_init(runtime.memory_pool, switch_test_flag((&runtime), SCF_USE_NAT_MAPPING));
}
switch_log_init(runtime.memory_pool, runtime.colorize_console);
@@ -1661,18 +1661,18 @@ static void switch_load_core_config(const char *file)
switch_core_default_dtmf_duration((uint32_t) tmp);
}
} else if (!strcasecmp(var, "enable-monotonic-timing")) {
switch_time_set_monotonic(switch_true(var));
switch_time_set_monotonic(switch_true(val));
} else if (!strcasecmp(var, "enable-softtimer-timerfd")) {
switch_time_set_timerfd(switch_true(var));
switch_time_set_timerfd(switch_true(val));
if (switch_true(val)) {
switch_clear_flag((&runtime), SCF_CALIBRATE_CLOCK);
}
} else if (!strcasecmp(var, "enable-clock-nanosleep")) {
switch_time_set_nanosleep(switch_true(var));
switch_time_set_nanosleep(switch_true(val));
} else if (!strcasecmp(var, "enable-cond-yield")) {
switch_time_set_cond_yield(switch_true(var));
switch_time_set_cond_yield(switch_true(val));
} else if (!strcasecmp(var, "enable-timer-matrix")) {
switch_time_set_matrix(switch_true(var));
switch_time_set_matrix(switch_true(val));
} else if (!strcasecmp(var, "max-sessions") && !zstr(val)) {
switch_core_session_limit(atoi(val));
} else if (!strcasecmp(var, "verbose-channel-events") && !zstr(val)) {
+4 -1
View File
@@ -346,13 +346,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
memset(session->raw_read_frame.data, 255, session->raw_read_frame.datalen);
status = SWITCH_STATUS_SUCCESS;
} else {
status = switch_core_codec_decode(use_codec,
switch_thread_rwlock_rdlock(session->bug_rwlock);
status = switch_core_codec_decode(use_codec->implementation?use_codec:read_frame->codec,
session->read_codec,
read_frame->data,
read_frame->datalen,
session->read_impl.actual_samples_per_second,
session->raw_read_frame.data, &session->raw_read_frame.datalen, &session->raw_read_frame.rate,
&read_frame->flags);
switch_thread_rwlock_unlock(session->bug_rwlock);
}
if (status == SWITCH_STATUS_SUCCESS) {
+2
View File
@@ -606,6 +606,8 @@ SWITCH_DECLARE(char *) switch_cache_db_execute_sql2str(switch_cache_db_handle_t
if (io_mutex) switch_mutex_lock(io_mutex);
memset(str, 0, len);
switch (dbh->type) {
case SCDB_TYPE_CORE_DB:
{
+6 -1
View File
@@ -306,7 +306,12 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session)
while ((state = switch_channel_get_state(session->channel)) != CS_DESTROY) {
switch_channel_wait_for_flag(session->channel, CF_BLOCK_STATE, SWITCH_FALSE, 0, NULL);
if (switch_channel_test_flag(session->channel, CF_BLOCK_STATE)) {
switch_channel_wait_for_flag(session->channel, CF_BLOCK_STATE, SWITCH_FALSE, 0, NULL);
if ((state = switch_channel_get_state(session->channel)) == CS_DESTROY) {
break;
}
}
midstate = state;
if (state != switch_channel_get_running_state(session->channel) || state >= CS_HANGUP) {
+19 -3
View File
@@ -1563,7 +1563,11 @@ SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const
char *cloned_sub_val = NULL;
char *func_val = NULL;
int nv = 0;
char *gvar = NULL;
char *gvar = NULL, *sb = NULL;
if (zstr(in)) {
return (char *) in;
}
nv = switch_string_var_check_const(in) || switch_string_has_escaped_data(in);
@@ -1647,10 +1651,22 @@ SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const
}
p = e > endof_indup ? endof_indup : e;
if ((vval = strchr(vname, '(')) || (vval = strchr(vname, ' '))) {
if (*vval == '(') br = 1;
vval = NULL;
for(sb = vname; sb && *sb; sb++) {
if (*sb == ' ') {
vval = sb;
break;
} else if (*sb == '(') {
vval = sb;
br = 1;
break;
}
}
if (vval) {
e = vval - 1;
*vval++ = '\0';
while (*e == ' ') {
*e-- = '\0';
}
+155 -9
View File
@@ -2330,22 +2330,38 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
const char *save_path = NULL, *chan_lang = NULL, *lang = NULL, *lname = NULL, *sound_path = NULL;
switch_event_t *hint_data;
switch_xml_t cfg, xml = NULL, language, macros;
char *p;
switch_assert(session);
channel = switch_core_session_get_channel(session);
switch_assert(channel);
lang = switch_channel_get_variable(channel, "language");
if (zstr(module_name)) {
module_name = "en";
}
if (!lang) {
chan_lang = switch_channel_get_variable(channel, "default_language");
if (!chan_lang) {
chan_lang = "en";
if (module_name) {
p = switch_core_session_strdup(session, module_name);
module_name = p;
if ((p = strchr(module_name, ':'))) {
*p++ = '\0';
chan_lang = p;
}
}
if (!chan_lang) {
lang = switch_channel_get_variable(channel, "language");
if (!lang) {
chan_lang = switch_channel_get_variable(channel, "default_language");
if (!chan_lang) {
chan_lang = module_name;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No language specified - Using [%s]\n", chan_lang);
} else {
chan_lang = lang;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No language specified - Using [%s]\n", chan_lang);
} else {
chan_lang = lang;
}
switch_event_create(&hint_data, SWITCH_EVENT_REQUEST_PARAMS);
@@ -2399,8 +2415,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
if (sound_path) {
switch_channel_set_variable(channel, "sound_prefix", sound_path);
p = switch_core_session_strdup(session, sound_path);
sound_path = p;
}
if (xml) {
switch_xml_free(xml);
}
if ((si = switch_loadable_module_get_say_interface(module_name))) {
/* should go back and proto all the say mods to const.... */
switch_say_args_t say_args = {0};
@@ -2424,6 +2446,129 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
if (save_path) {
switch_channel_set_variable(channel, "sound_prefix", save_path);
}
return status;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_say_string(switch_core_session_t *session,
const char *lang,
const char *ext,
const char *tosay,
const char *module_name,
const char *say_type,
const char *say_method,
const char *say_gender,
char **rstr)
{
switch_say_interface_t *si;
switch_channel_t *channel = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
const char *save_path = NULL, *chan_lang = NULL, *lname = NULL, *sound_path = NULL;
switch_event_t *hint_data;
switch_xml_t cfg, xml = NULL, language, macros;
if (session) {
channel = switch_core_session_get_channel(session);
if (!lang) {
lang = switch_channel_get_variable(channel, "language");
if (!lang) {
chan_lang = switch_channel_get_variable(channel, "default_language");
if (!chan_lang) {
chan_lang = "en";
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No language specified - Using [%s]\n", chan_lang);
} else {
chan_lang = lang;
}
}
}
if (!lang) lang = "en";
if (!chan_lang) chan_lang = lang;
switch_event_create(&hint_data, SWITCH_EVENT_REQUEST_PARAMS);
switch_assert(hint_data);
switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "macro_name", "say_app");
switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "lang", chan_lang);
if (channel) {
switch_channel_event_set_data(channel, hint_data);
}
if (switch_xml_locate("phrases", NULL, NULL, NULL, &xml, &cfg, hint_data, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Open of phrases failed.\n");
goto done;
}
if (!(macros = switch_xml_child(cfg, "macros"))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find macros tag.\n");
goto done;
}
if (!(language = switch_xml_child(macros, "language"))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find language tag.\n");
goto done;
}
while (language) {
if ((lname = (char *) switch_xml_attr(language, "name")) && !strcasecmp(lname, chan_lang)) {
const char *tmp;
if ((tmp = switch_xml_attr(language, "module"))) {
module_name = tmp;
}
break;
}
language = language->next;
}
if (!language) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find language %s.\n", chan_lang);
goto done;
}
if (!module_name) {
module_name = chan_lang;
}
if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) {
sound_path = (char *) switch_xml_attr(language, "sound_path");
}
if (channel) {
save_path = switch_channel_get_variable(channel, "sound_prefix");
}
if (sound_path && channel) {
switch_channel_set_variable(channel, "sound_prefix", sound_path);
}
if ((si = switch_loadable_module_get_say_interface(module_name))) {
/* should go back and proto all the say mods to const.... */
switch_say_args_t say_args = {0};
say_args.type = switch_ivr_get_say_type_by_name(say_type);
say_args.method = switch_ivr_get_say_method_by_name(say_method);
say_args.gender = switch_ivr_get_say_gender_by_name(say_gender);
say_args.ext = ext;
status = si->say_string_function(session, (char *) tosay, &say_args, rstr);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid SAY Interface [%s]!\n", module_name);
status = SWITCH_STATUS_FALSE;
}
done:
if (hint_data) {
switch_event_destroy(&hint_data);
}
if (save_path && channel) {
switch_channel_set_variable(channel, "sound_prefix", save_path);
}
if (xml) {
switch_xml_free(xml);
@@ -2432,6 +2577,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
return status;
}
static const char *get_prefixed_str(char *buffer, size_t buffer_size, const char *prefix, size_t prefix_size, const char *str)
{
size_t str_len;
+4 -2
View File
@@ -357,11 +357,11 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
}
if ((bypass_media_after_bridge || switch_channel_test_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE)) && switch_channel_test_flag(chan_a, CF_ANSWERED)
if ((bypass_media_after_bridge || switch_channel_test_flag(chan_b, CF_BYPASS_MEDIA_AFTER_BRIDGE)) && switch_channel_test_flag(chan_a, CF_ANSWERED)
&& switch_channel_test_flag(chan_b, CF_ANSWERED)) {
switch_ivr_nomedia(switch_core_session_get_uuid(session_a), SMF_REBRIDGE);
bypass_media_after_bridge = 0;
switch_channel_clear_flag(chan_a, CF_BYPASS_MEDIA_AFTER_BRIDGE);
switch_channel_clear_flag(chan_b, CF_BYPASS_MEDIA_AFTER_BRIDGE);
goto end_of_bridge_loop;
}
}
@@ -1367,6 +1367,8 @@ static void cleanup_proxy_mode_a(switch_core_session_t *session)
const char *sbv = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE);
if (!zstr(sbv) && (sbsession = switch_core_session_locate(sbv))) {
switch_channel_t *sbchannel = switch_core_session_get_channel(sbsession);
/* Clear this now, otherwise will cause the one we're interested in to hang up too...*/
switch_channel_set_variable(sbchannel, SWITCH_SIGNAL_BRIDGE_VARIABLE, NULL);
switch_channel_hangup(sbchannel, SWITCH_CAUSE_ATTENDED_TRANSFER);
switch_core_session_rwunlock(sbsession);
}
+2 -16
View File
@@ -2762,23 +2762,9 @@ 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));
}
if ((vvar = switch_channel_get_variable_dup(originate_status[i].peer_channel, "execute_on_originate", SWITCH_FALSE))) {
char *app = switch_core_session_strdup(originate_status[i].peer_session, vvar);
char *arg = NULL;
if (strstr(app, "::")) {
switch_core_session_execute_application_async(originate_status[i].peer_session, app, arg);
} else {
if ((arg = strchr(app, ' '))) {
*arg++ = '\0';
}
switch_core_session_execute_application(originate_status[i].peer_session, app, arg);
}
}
switch_channel_execute_on(originate_status[i].peer_channel, "execute_on_originate");
}
if (table) {
switch_channel_add_state_handler(originate_status[i].peer_channel, table);
}
+73 -60
View File
@@ -1000,7 +1000,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
switch_file_handle_t lfh;
const char *p;
char *title = "", *copyright = "", *software = "", *artist = "", *comment = "", *date = "";
uint8_t asis = 0;
char *ext;
const char *prefix;
const char *timer_name;
@@ -1024,6 +1023,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
int more_data = 0;
char *playback_vars, *tmp;
switch_event_t *event;
uint32_t test_native = 0, last_native = 0;
if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
@@ -1060,9 +1060,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
l16++;
}
if (play_delimiter) {
file_dup = switch_core_session_strdup(session, file);
argc = switch_separate_string(file_dup, play_delimiter, argv, (sizeof(argv) / sizeof(argv[0])));
@@ -1071,9 +1068,18 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
argv[0] = (char *) file;
}
if (!fh) {
fh = &lfh;
memset(fh, 0, sizeof(lfh));
}
if (fh->samples > 0) {
sample_start = fh->samples;
fh->samples = 0;
}
for (cur = 0; switch_channel_ready(channel) && !done && cur < argc; cur++) {
file = argv[cur];
asis = 0;
eof = 0;
if (cur) {
@@ -1168,7 +1174,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
} else {
ext = read_impl.iananame;
file = switch_core_session_sprintf(session, "%s.%s", file, ext);
asis = 1;
}
}
@@ -1186,16 +1191,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
}
}
if (!fh) {
fh = &lfh;
memset(fh, 0, sizeof(lfh));
}
if (fh->samples > 0) {
sample_start = fh->samples;
fh->samples = 0;
}
if ((prebuf = switch_channel_get_variable(channel, "stream_prebuffer"))) {
int maybe = atoi(prebuf);
if (maybe > 0) {
@@ -1221,9 +1216,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
switch_channel_set_private(channel, "__fh", fh);
switch_core_session_io_rwunlock(session);
if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
asis = 1;
}
if (!abuf) {
switch_zmalloc(abuf, FILE_STARTSAMPLES * sizeof(*abuf));
@@ -1275,43 +1267,46 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
switch_assert(fh->audio_buffer);
}
if (asis) {
codec_name = "L16";
if (!switch_core_codec_ready((&codec))) {
if (switch_core_codec_init(&codec,
codec_name,
NULL,
fh->samplerate,
interval, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, pool) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
SWITCH_LOG_DEBUG, "Codec Activated %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
switch_core_session_io_write_lock(session);
switch_channel_set_private(channel, "__fh", NULL);
switch_core_session_io_rwunlock(session);
switch_core_file_close(fh);
switch_core_session_reset(session, SWITCH_TRUE, SWITCH_FALSE);
status = SWITCH_STATUS_GENERR;
continue;
}
}
test_native = switch_test_flag(fh, SWITCH_FILE_NATIVE);
if (test_native) {
write_frame.codec = switch_core_session_get_read_codec(session);
samples = read_impl.samples_per_packet;
framelen = read_impl.encoded_bytes_per_packet;
} else {
codec_name = "L16";
if (!switch_core_codec_ready((&codec))) {
if (switch_core_codec_init(&codec,
codec_name,
NULL,
fh->samplerate,
interval, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, pool) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
SWITCH_LOG_DEBUG, "Codec Activated %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
switch_core_session_io_write_lock(session);
switch_channel_set_private(channel, "__fh", NULL);
switch_core_session_io_rwunlock(session);
switch_core_file_close(fh);
switch_core_session_reset(session, SWITCH_TRUE, SWITCH_FALSE);
status = SWITCH_STATUS_GENERR;
continue;
}
}
write_frame.codec = &codec;
samples = codec.implementation->samples_per_packet;
framelen = codec.implementation->decoded_bytes_per_packet;
}
last_native = test_native;
if (timer_name && !timer.samplecount) {
uint32_t len;
@@ -1429,7 +1424,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
memset(abuf + bread, 255, framelen - bread);
}
olen = asis ? framelen : ilen;
olen = switch_test_flag(fh, SWITCH_FILE_NATIVE) ? framelen : ilen;
do_speed = 0;
} else if (fh->audio_buffer && (eof || (switch_buffer_inuse(fh->audio_buffer) > (switch_size_t) (framelen)))) {
if (!(bread = switch_buffer_read(fh->audio_buffer, abuf, framelen))) {
@@ -1440,30 +1435,48 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
}
}
fh->offset_pos += asis ? bread : bread / 2;
fh->offset_pos += switch_test_flag(fh, SWITCH_FILE_NATIVE) ? bread : bread / 2;
if (bread < framelen) {
memset(abuf + bread, 255, framelen - bread);
}
olen = asis ? framelen : ilen;
olen = switch_test_flag(fh, SWITCH_FILE_NATIVE) ? framelen : ilen;
} else {
if (eof) {
break;
}
olen = FILE_STARTSAMPLES;
if (!asis) {
if (!switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
olen /= 2;
}
if (switch_core_file_read(fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
eof++;
continue;
}
switch_buffer_write(fh->audio_buffer, abuf, asis ? olen : olen * 2);
test_native = switch_test_flag(fh, SWITCH_FILE_NATIVE);
if (test_native != last_native) {
if (test_native) {
write_frame.codec = switch_core_session_get_read_codec(session);
samples = read_impl.samples_per_packet;
framelen = read_impl.encoded_bytes_per_packet;
} else {
write_frame.codec = &codec;
samples = codec.implementation->samples_per_packet;
framelen = codec.implementation->decoded_bytes_per_packet;
}
switch_buffer_zero(fh->audio_buffer);
}
last_native = test_native;
switch_buffer_write(fh->audio_buffer, abuf, switch_test_flag(fh, SWITCH_FILE_NATIVE) ? olen : olen * 2);
olen = switch_buffer_read(fh->audio_buffer, abuf, framelen);
fh->offset_pos += olen / 2;
if (!asis) {
if (!switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
olen /= 2;
}
@@ -1473,7 +1486,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
break;
}
if (!asis) {
if (!switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
if (fh->speed > 2) {
fh->speed = 2;
} else if (fh->speed < -2) {
@@ -1481,7 +1494,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
}
}
if (!asis && fh->audio_buffer && last_speed > -1 && last_speed != fh->speed) {
if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->audio_buffer && last_speed > -1 && last_speed != fh->speed) {
switch_buffer_zero(fh->sp_audio_buffer);
}
@@ -1492,7 +1505,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
}
if (!asis && fh->speed && do_speed) {
if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->speed && do_speed) {
float factor = 0.25f * abs(fh->speed);
switch_size_t newlen, supplement, step;
short *bp = write_frame.data;
@@ -1583,7 +1596,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
more_data = 0;
write_frame.samples = (uint32_t) olen;
if (asis) {
if (switch_test_flag(fh, SWITCH_FILE_NATIVE)) {
write_frame.datalen = (uint32_t) olen;
} else {
write_frame.datalen = write_frame.samples * 2;
@@ -1596,12 +1609,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
}
#ifndef WIN32
#if SWITCH_BYTE_ORDER == __BIG_ENDIAN
if (!asis && l16) {
if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && l16) {
switch_swap_linear(write_frame.data, (int) write_frame.datalen / 2);
}
#endif
#endif
if (!asis && fh->vol) {
if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->vol) {
switch_change_sln_volume(write_frame.data, write_frame.datalen / 2, fh->vol);
}
+95
View File
@@ -1918,6 +1918,101 @@ SWITCH_DECLARE(void *) switch_loadable_module_create_interface(switch_loadable_m
}
}
struct switch_say_file_handle {
char *ext;
int cnt;
struct switch_stream_handle stream;
switch_event_t *param_event;
};
SWITCH_DECLARE(char *) switch_say_file_handle_get_variable(switch_say_file_handle_t *sh, const char *var)
{
char *ret = NULL;
if (sh->param_event) {
ret = switch_event_get_header(sh->param_event, var);
}
return ret;
}
SWITCH_DECLARE(char *) switch_say_file_handle_get_path(switch_say_file_handle_t *sh)
{
return (char *) sh->stream.data;
}
SWITCH_DECLARE(char *) switch_say_file_handle_detach_path(switch_say_file_handle_t *sh)
{
char *path;
switch_assert(sh);
path = (char *) sh->stream.data;
sh->stream.data = NULL;
return path;
}
SWITCH_DECLARE(void) switch_say_file_handle_destroy(switch_say_file_handle_t **sh)
{
switch_assert(sh);
switch_safe_free((*sh)->stream.data);
switch_safe_free((*sh)->ext);
if ((*sh)->param_event) {
switch_event_destroy(&(*sh)->param_event);
}
free(*sh);
*sh = NULL;
}
SWITCH_DECLARE(switch_status_t) switch_say_file_handle_create(switch_say_file_handle_t **sh, const char *ext, switch_event_t **var_event)
{
switch_assert(sh);
if (zstr(ext)) {
ext = "wav";
}
*sh = malloc(sizeof(**sh));
memset(*sh, 0, sizeof(**sh));
SWITCH_STANDARD_STREAM((*sh)->stream);
if (var_event) {
(*sh)->param_event = *var_event;
*var_event = NULL;
}
(*sh)->ext = strdup(ext);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(void) switch_say_file(switch_say_file_handle_t *sh, const char *fmt, ...)
{
char buf[256] = "";
int ret;
va_list ap;
va_start(ap, fmt);
if ((ret = switch_vsnprintf(buf, sizeof(buf), fmt, ap)) > 0) {
if (!sh->cnt++) {
sh->stream.write_function(&sh->stream, "file_string://%s.%s", buf, sh->ext);
} else {
sh->stream.write_function(&sh->stream, "!%s.%s", buf, sh->ext);
}
}
va_end(ap);
}
/* For Emacs:
* Local Variables:
* mode:c
+21 -2
View File
@@ -51,6 +51,7 @@ typedef struct {
char *descURL;
char pub_addr[IP_LEN];
char pvt_addr[IP_LEN];
switch_bool_t mapping;
} nat_globals_t;
static nat_globals_t nat_globals;
@@ -207,9 +208,14 @@ static int init_pmp(void)
return get_pmp_pubaddr(nat_globals.pub_addr);
}
SWITCH_DECLARE(void) switch_nat_set_mapping(switch_bool_t mapping)
{
nat_globals.mapping = mapping;
}
SWITCH_DECLARE(void) switch_nat_reinit(void)
{
switch_nat_init(nat_globals_perm.pool);
switch_nat_init(nat_globals_perm.pool, nat_globals.mapping);
}
switch_status_t init_nat_monitor(switch_memory_pool_t *pool)
@@ -392,7 +398,7 @@ SWITCH_DECLARE(void) switch_nat_thread_stop(void)
}
SWITCH_DECLARE(void) switch_nat_init(switch_memory_pool_t *pool)
SWITCH_DECLARE(void) switch_nat_init(switch_memory_pool_t *pool, switch_bool_t mapping)
{
/* try free dynamic data structures prior to resetting to 0 */
FreeUPNPUrls(&nat_globals.urls);
@@ -405,6 +411,8 @@ SWITCH_DECLARE(void) switch_nat_init(switch_memory_pool_t *pool)
nat_globals_perm.pool = pool;
}
nat_globals.mapping = mapping;
switch_find_local_ip(nat_globals.pvt_addr, sizeof(nat_globals.pvt_addr), NULL, AF_INET);
@@ -577,6 +585,11 @@ SWITCH_DECLARE(switch_status_t) switch_nat_add_mapping_internal(switch_port_t po
switch_status_t status = SWITCH_STATUS_FALSE;
switch_event_t *event = NULL;
if (!nat_globals.mapping) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "NAT port mapping disabled\n");
return status;
}
switch (nat_globals.nat_type) {
case SWITCH_NAT_TYPE_PMP:
status = switch_nat_add_mapping_pmp(port, proto, external_port);
@@ -710,6 +723,12 @@ SWITCH_DECLARE(char *) switch_nat_status(void)
(nat_globals.nat_type == SWITCH_NAT_TYPE_UPNP) ? "UPNP" : (nat_globals.nat_type == SWITCH_NAT_TYPE_PMP ? "NAT-PMP" : "UNKNOWN"),
nat_globals.pub_addr);
if (nat_globals.mapping) {
stream.write_function(&stream, "NAT port mapping enabled.\n");
} else {
stream.write_function(&stream, "NAT port mapping disabled.\n");
}
switch_api_execute("show", "nat_map", NULL, &stream);
return stream.data; /* caller frees */
+6 -1
View File
@@ -756,7 +756,8 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)
while (globals.RUNNING == 1) {
runtime.reference += STEP_MIC;
while ((ts = time_now(runtime.offset)) < runtime.reference) {
while (((ts = time_now(runtime.offset)) + 100) < runtime.reference) {
if (ts < last) {
if (MONO) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Virtual Migration Detected! Syncing Clock\n");
@@ -770,6 +771,10 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)
runtime.initiated += diff;
rev_errs++;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT,
"If you see this message many times try setting the param enable-clock-nanosleep to true in switch.conf.xml or consider a nicer machine to run me on. I AM *FREE* afterall.\n");
} else {
rev_errs = 0;
}
+8 -14
View File
@@ -2579,13 +2579,13 @@ SWITCH_DECLARE(int) switch_isxdigit(int c)
return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_N | _X)));
}
static const char *DOW[] = {
"sat",
"sun",
"mon",
"tue",
"wed",
"thu",
"fri"
"fri",
"sat"
};
SWITCH_DECLARE(const char *) switch_dow_int2str(int val) {
@@ -2601,7 +2601,7 @@ SWITCH_DECLARE(int) switch_dow_str2int(const char *exp) {
for (x = 0; x < switch_arraylen(DOW); x++) {
if (!strncasecmp(DOW[x], exp, 3)) {
ret = x;
ret = x + 1;
break;
}
}
@@ -2611,13 +2611,13 @@ SWITCH_DECLARE(int) switch_dow_str2int(const char *exp) {
typedef enum {
DOW_ERR = -2,
DOW_EOF = -1,
DOW_SAT = 0,
DOW_SUN,
DOW_SUN = 1,
DOW_MON,
DOW_TUE,
DOW_WED,
DOW_THU,
DOW_FRI,
DOW_SAT,
DOW_HYPHEN = '-',
DOW_COMA = ','
} dow_t;
@@ -2632,7 +2632,7 @@ static inline dow_t _dow_read_token(const char **s)
} else if (**s == ',') {
(*s)++;
return DOW_COMA;
} else if (**s >= '0' && **s <= '9') {
} else if (**s >= '1' && **s <= '7') {
dow_t r = **s - '0';
(*s)++;
return r;
@@ -2664,14 +2664,8 @@ SWITCH_DECLARE(switch_bool_t) switch_dow_cmp(const char *exp, int val)
} else {
/* Valid day found */
if (range_start != DOW_EOF) { /* Evaluating a range */
if (range_start < cur) {
if (val >= range_start && val <= cur) {
return SWITCH_TRUE;
}
} else {
if (val >= cur && val <= range_start) {
return SWITCH_TRUE;
}
if (val >= range_start && val <= cur) {
return SWITCH_TRUE;
}
range_start = DOW_EOF;
} else if (val == cur) {
+62 -66
View File
@@ -56,6 +56,7 @@
#include <switch.h>
#ifndef WIN32
#include <sys/wait.h>
#include <switch_private.h>
#include <glob.h>
#else /* we're on windoze :( */
@@ -117,11 +118,6 @@ struct switch_xml_root { /* additional data for the root tag */
char ***pi; /* processing instructions */
short standalone; /* non-zero if <?xml standalone="yes"?> */
char err[SWITCH_XML_ERRL]; /* error string */
/*! is_main_xml_root */
switch_bool_t is_main_xml_root;
/*! rwlock */
switch_thread_rwlock_t *rwlock;
};
char *SWITCH_XML_NIL[] = { NULL }; /* empty, null terminated array of strings */
@@ -137,11 +133,13 @@ struct switch_xml_binding {
static switch_xml_binding_t *BINDINGS = NULL;
static switch_xml_t MAIN_XML_ROOT = NULL;
static switch_memory_pool_t *XML_MEMORY_POOL = NULL;
static switch_thread_rwlock_t *B_RWLOCK = NULL;
static switch_thread_rwlock_t *XML_RWLOCK = NULL;
static switch_mutex_t *XML_LOCK = NULL;
static switch_mutex_t *REFLOCK = NULL;
static switch_mutex_t *FILE_LOCK = NULL;
static switch_mutex_t *XML_GEN_LOCK = NULL;
static switch_mutex_t *XML_FREE_LOCK = NULL;
static switch_mutex_t *XML_RWFILE_LOCK = NULL;
struct xml_section_t {
const char *name;
@@ -1245,6 +1243,7 @@ static int preprocess_exec(const char *cwd, const char *command, int write_fd, i
}
}
close(fds[0]);
waitpid(pid, NULL, 0);
} else { /* child */
close(fds[0]);
dup2(fds[1], STDOUT_FILENO);
@@ -1528,8 +1527,8 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_parse_file(const char *file)
} else {
abs = file;
}
/* Protection against running this code twice on the same filename */
switch_mutex_lock(XML_RWFILE_LOCK);
switch_mutex_lock(FILE_LOCK);
if (!(new_file = switch_mprintf("%s%s%s.fsxml", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, abs))) {
goto done;
@@ -1553,14 +1552,19 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_parse_file(const char *file)
}
done:
switch_mutex_unlock(FILE_LOCK);
if (write_fd > -1) {
close(write_fd);
}
if (fd > -1) {
close(fd);
}
switch_mutex_unlock(XML_RWFILE_LOCK);
switch_safe_free(new_file);
return xml;
}
@@ -1922,16 +1926,14 @@ SWITCH_DECLARE(switch_status_t) switch_xml_locate_user(const char *key,
SWITCH_DECLARE(switch_xml_t) switch_xml_root(void)
{
switch_xml_root_t root = NULL;
switch_xml_t xml;
switch_thread_rwlock_rdlock(XML_RWLOCK);
if (MAIN_XML_ROOT) {
root = (switch_xml_root_t) MAIN_XML_ROOT;
switch_thread_rwlock_rdlock(root->rwlock);
}
switch_thread_rwlock_unlock(XML_RWLOCK);
return (switch_xml_t) root;
switch_mutex_lock(REFLOCK);
xml = MAIN_XML_ROOT;
xml->refs++;
switch_mutex_unlock(REFLOCK);
return xml;
}
struct destroy_xml {
@@ -1975,14 +1977,15 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_open_root(uint8_t reload, const char **e
{
char path_buf[1024];
uint8_t errcnt = 0;
switch_xml_t r = NULL, new_main;
switch_xml_t new_main, r = NULL;
if (!reload) {
r = switch_xml_root();
}
switch_mutex_lock(XML_LOCK);
if (r) {
goto done;
if (MAIN_XML_ROOT) {
if (!reload) {
r = switch_xml_root();
goto done;
}
}
switch_snprintf(path_buf, sizeof(path_buf), "%s%s%s", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR, "freeswitch.xml");
@@ -1995,28 +1998,28 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_open_root(uint8_t reload, const char **e
new_main = NULL;
errcnt++;
} else {
switch_xml_t old_root = NULL;
switch_xml_root_t new_main_root = (switch_xml_root_t) new_main;
new_main_root->is_main_xml_root = SWITCH_TRUE;
switch_xml_t old_root;
*err = "Success";
old_root = switch_xml_root();
switch_mutex_lock(REFLOCK);
switch_set_flag(new_main, SWITCH_XML_ROOT);
switch_thread_rwlock_wrlock(XML_RWLOCK);
old_root = MAIN_XML_ROOT;
MAIN_XML_ROOT = new_main;
switch_thread_rwlock_unlock(XML_RWLOCK);
switch_set_flag(MAIN_XML_ROOT, SWITCH_XML_ROOT);
MAIN_XML_ROOT->refs++;
if (old_root) {
if (old_root->refs) {
old_root->refs--;
}
if (old_root) {
switch_clear_flag(old_root, SWITCH_XML_ROOT);
if (!old_root->refs) {
switch_xml_free(old_root);
}
}
switch_xml_free(old_root);
switch_mutex_unlock(REFLOCK);
/* switch_xml_free_in_thread(old_root); */
}
} else {
*err = "Cannot Open log directory or XML Root!";
@@ -2035,6 +2038,8 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_open_root(uint8_t reload, const char **e
done:
switch_mutex_unlock(XML_LOCK);
return r;
}
@@ -2056,11 +2061,12 @@ SWITCH_DECLARE(switch_status_t) switch_xml_init(switch_memory_pool_t *pool, cons
XML_MEMORY_POOL = pool;
*err = "Success";
switch_mutex_init(&XML_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL);
switch_mutex_init(&REFLOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL);
switch_mutex_init(&FILE_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL);
switch_mutex_init(&XML_GEN_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL);
switch_mutex_init(&XML_FREE_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL);
switch_mutex_init(&XML_RWFILE_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL);
switch_thread_rwlock_create(&B_RWLOCK, XML_MEMORY_POOL);
switch_thread_rwlock_create(&XML_RWLOCK, XML_MEMORY_POOL);
assert(pool != NULL);
@@ -2075,7 +2081,9 @@ SWITCH_DECLARE(switch_status_t) switch_xml_init(switch_memory_pool_t *pool, cons
SWITCH_DECLARE(switch_status_t) switch_xml_destroy(void)
{
switch_status_t status = SWITCH_STATUS_FALSE;
switch_thread_rwlock_wrlock(XML_RWLOCK);
switch_mutex_lock(XML_LOCK);
switch_mutex_lock(REFLOCK);
if (MAIN_XML_ROOT) {
switch_xml_t xml = MAIN_XML_ROOT;
@@ -2084,7 +2092,8 @@ SWITCH_DECLARE(switch_status_t) switch_xml_destroy(void)
status = SWITCH_STATUS_SUCCESS;
}
switch_thread_rwlock_unlock(XML_RWLOCK);
switch_mutex_unlock(XML_LOCK);
switch_mutex_unlock(REFLOCK);
return status;
}
@@ -2370,35 +2379,25 @@ SWITCH_DECLARE(void) switch_xml_free(switch_xml_t xml)
int i, j;
char **a, *s;
switch_xml_t orig_xml;
int refs = 0;
tailrecurse:
root = (switch_xml_root_t) xml;
if (!xml) {
return;
}
/* If xml is currenly the MAIN_XML_ROOT, dont even bother to check to empty it */
if (switch_test_flag(xml, SWITCH_XML_ROOT)) {
switch_thread_rwlock_unlock(root->rwlock);
return;
}
switch_mutex_lock(REFLOCK);
/* This is a trick to find if the struct is still in use or not */
switch_mutex_lock(XML_FREE_LOCK);
if (xml->is_switch_xml_root_t == SWITCH_TRUE && root->is_main_xml_root == SWITCH_TRUE) {
switch_thread_rwlock_unlock(root->rwlock);
if (switch_thread_rwlock_trywrlock(root->rwlock) != SWITCH_STATUS_SUCCESS) {
/* XML Struct is still in used, person who free it will clean it */
switch_mutex_unlock(XML_FREE_LOCK);
return;
if (xml->refs) {
xml->refs--;
refs = xml->refs;
}
switch_thread_rwlock_unlock(root->rwlock);
switch_thread_rwlock_destroy(root->rwlock);
switch_mutex_unlock(REFLOCK);
}
switch_mutex_unlock(XML_FREE_LOCK);
tailrecurse:
root = (switch_xml_root_t) xml;
if (!xml) {
if (refs) {
return;
}
@@ -2447,7 +2446,6 @@ SWITCH_DECLARE(void) switch_xml_free(switch_xml_t xml)
}
switch_xml_free_attr(xml->attr); /* tag attributes */
if ((xml->flags & SWITCH_XML_TXTM))
free(xml->txt); /* character content */
if ((xml->flags & SWITCH_XML_NAMEM))
@@ -2485,8 +2483,6 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_new(const char *name)
root->ent = (char **) memcpy(malloc(sizeof(ent)), ent, sizeof(ent));
root->attr = root->pi = (char ***) (root->xml.attr = SWITCH_XML_NIL);
root->xml.is_switch_xml_root_t = SWITCH_TRUE;
root->is_main_xml_root = SWITCH_FALSE;
switch_thread_rwlock_create(&root->rwlock, XML_MEMORY_POOL);
return &root->xml;
}