Merge branch 'master' into smgmaster

Conflicts:
	src/mod/endpoints/mod_sofia/mod_sofia.c
This commit is contained in:
Moises Silva committed 2011-01-05 12:38:46 -05:00
commit 10d252b0fa
246 files changed
+15717 -6277

No files matched your search

+3 -1
View File
@@ -31,7 +31,8 @@
* this file does not exist!!!!
*
*/
#define SPANDSP_NO_TIFF 1
#include "spandsp.h"
#include "switch_profile.h"
#ifndef WIN32
@@ -169,6 +170,7 @@ struct switch_core_session {
switch_log_level_t loglevel;
uint32_t soft_lock;
switch_ivr_dmachine_t *dmachine;
plc_state_t *plc;
};
struct switch_media_bug {
+2
View File
@@ -1230,6 +1230,8 @@ SWITCH_DECLARE(int) switch_sockaddr_equal(const switch_sockaddr_t *sa1, const sw
SWITCH_DECLARE(switch_status_t) switch_sockaddr_info_get(switch_sockaddr_t ** sa, const char *hostname,
int32_t family, switch_port_t port, int32_t flags, switch_memory_pool_t *pool);
SWITCH_DECLARE(switch_status_t) switch_sockaddr_create(switch_sockaddr_t **sa, switch_memory_pool_t *pool);
/**
* Send data over a network.
* @param sock The socket to send the data over.
+2
View File
@@ -312,6 +312,8 @@ SWITCH_DECLARE(switch_status_t) switch_channel_caller_extension_masquerade(switc
*/
SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension);
SWITCH_DECLARE(void) switch_channel_sort_cid(switch_channel_t *channel, switch_bool_t in);
/*!
\brief Retrieve caller extension from a given channel
\param channel channel to retrieve extension from
+2
View File
@@ -246,6 +246,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_close(_Inout_ switch_media
*/
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_all(_In_ switch_core_session_t *session);
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_enumerate(switch_core_session_t *session, switch_stream_handle_t *stream);
/*!
\brief Read a frame from the bug
\param bug the bug to read from
+1
View File
@@ -216,6 +216,7 @@ SWITCH_DECLARE(void) consoleCleanLog(char *msg);
char *tts_name;
char *voice_name;
SWITCH_DECLARE(int) insertFile(const char *file, const char *insert_file, int sample_point);
SWITCH_DECLARE(int) answer();
SWITCH_DECLARE(int) preAnswer();
SWITCH_DECLARE(void) hangup(const char *cause = "normal_clearing");
+8 -1
View File
@@ -229,7 +229,14 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_rtcp(switch_rtp_t *rtp_sessi
\param queue_frames the number of frames to delay
\return SWITCH_STATUS_SUCCESS
*/
SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *rtp_session, uint32_t queue_frames);
SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *rtp_session,
uint32_t queue_frames,
uint32_t max_queue_frames,
uint32_t samples_per_packet, uint32_t samples_per_second);
SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name);
SWITCH_DECLARE(switch_status_t) switch_rtp_deactivate_jitter_buffer(switch_rtp_t *rtp_session);
/*!
\brief Set an RTP Flag
+6
View File
@@ -790,6 +790,8 @@ typedef enum {
SWITCH_MESSAGE_INDICATE_T38_DESCRIPTION,
SWITCH_MESSAGE_INDICATE_UDPTL_MODE,
SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS,
SWITCH_MESSAGE_INDICATE_JITTER_BUFFER,
SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH,
SWITCH_MESSAGE_INVALID
} switch_core_session_message_types_t;
@@ -1093,6 +1095,10 @@ typedef enum {
CF_PASSTHRU_PTIME_MISMATCH,
CF_BRIDGE_NOWRITE,
CF_RECOVERED,
CF_JITTERBUFFER,
CF_DIALPLAN,
CF_BLOCK_BROADCAST_UNTIL_MEDIA,
CF_CNG_PLC,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
CF_FLAG_MAX
} switch_channel_flag_t;
+1 -1
View File
@@ -622,7 +622,7 @@ SWITCH_DECLARE(unsigned int) switch_separate_string(_In_ char *buf, char delim,
SWITCH_DECLARE(unsigned int) switch_separate_string_string(char *buf, char *delim, _Post_count_(return) char **array, unsigned int arraylen);
SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str);
SWITCH_DECLARE(char *) switch_strip_spaces(const char *str);
SWITCH_DECLARE(char *) switch_strip_spaces(char *str, switch_bool_t dup);
SWITCH_DECLARE(char *) switch_strip_whitespace(const char *str);
SWITCH_DECLARE(char *) switch_strip_commas(char *in, char *out, switch_size_t len);
SWITCH_DECLARE(char *) switch_strip_nonnumerics(char *in, char *out, switch_size_t len);
@@ -1428,8 +1428,8 @@ SWITCH_STANDARD_API(cond_function)
int a_is_num, b_is_num;
*expr++ = '\0';
b = expr;
s_a = switch_strip_spaces(a);
s_b = switch_strip_spaces(b);
s_a = switch_strip_spaces(a, SWITCH_TRUE);
s_b = switch_strip_spaces(b, SWITCH_TRUE);
a_is_num = switch_is_number(s_a);
b_is_num = switch_is_number(s_b);
@@ -2226,6 +2226,40 @@ SWITCH_STANDARD_API(uuid_deflect)
return SWITCH_STATUS_SUCCESS;
}
#define UUID_RECOVERY_REFRESH_SYNTAX "<uuid> <uri>"
SWITCH_STANDARD_API(uuid_recovery_refresh)
{
switch_core_session_t *tsession = NULL;
char *uuid = NULL, *text = NULL;
if (!zstr(cmd) && (uuid = strdup(cmd))) {
if ((text = strchr(uuid, ' '))) {
*text++ = '\0';
}
}
if (zstr(uuid) || zstr(text)) {
stream->write_function(stream, "-USAGE: %s\n", UUID_RECOVERY_REFRESH_SYNTAX);
} else {
if ((tsession = switch_core_session_locate(uuid))) {
switch_core_session_message_t msg = { 0 };
/* Tell the channel to recovery_refresh the call */
msg.from = __FILE__;
msg.string_arg = text;
msg.message_id = SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH;
switch_core_session_receive_message(tsession, &msg);
stream->write_function(stream, "+OK:%s\n", msg.string_reply);
switch_core_session_rwunlock(tsession);
} else {
stream->write_function(stream, "-ERR No Such Channel %s!\n", uuid);
}
}
switch_safe_free(uuid);
return SWITCH_STATUS_SUCCESS;
}
#define SCHED_TRANSFER_SYNTAX "[+]<time> <uuid> <extension> [<dialplan>] [<context>]"
SWITCH_STANDARD_API(sched_transfer_function)
{
@@ -2488,6 +2522,48 @@ SWITCH_STANDARD_API(uuid_display_function)
return SWITCH_STATUS_SUCCESS;
}
#define BUGLIST_SYNTAX "<uuid>"
SWITCH_STANDARD_API(uuid_buglist_function)
{
char *mydata = NULL, *argv[2] = { 0 };
int argc = 0;
switch_status_t status = SWITCH_STATUS_FALSE;
if (zstr(cmd)) {
goto error;
}
mydata = strdup(cmd);
switch_assert(mydata);
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
if (argc < 1) {
goto error;
}
if (argv[0]) {
switch_core_session_t *lsession = NULL;
if ((lsession = switch_core_session_locate(argv[0]))) {
status = switch_core_media_bug_enumerate(lsession, stream);
switch_core_session_rwunlock(lsession);
}
goto ok;
} else {
goto error;
}
error:
stream->write_function(stream, "-USAGE: %s\n", BUGLIST_SYNTAX);
switch_safe_free(mydata);
return SWITCH_STATUS_SUCCESS;
ok:
switch_safe_free(mydata);
return SWITCH_STATUS_SUCCESS;
}
#define SIMPLIFY_SYNTAX "<uuid>"
SWITCH_STANDARD_API(uuid_simplify_function)
{
@@ -2541,6 +2617,59 @@ SWITCH_STANDARD_API(uuid_simplify_function)
return SWITCH_STATUS_SUCCESS;
}
#define JITTERBUFFER_SYNTAX "<uuid> [0|<min_msec>[:<max_msec>]]"
SWITCH_STANDARD_API(uuid_jitterbuffer_function)
{
char *mydata = NULL, *argv[2] = { 0 };
int argc = 0;
switch_status_t status = SWITCH_STATUS_FALSE;
if (zstr(cmd)) {
goto error;
}
mydata = strdup(cmd);
switch_assert(mydata);
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
if (argc < 2) {
goto error;
}
if (argv[1]) {
switch_core_session_message_t msg = { 0 };
switch_core_session_t *lsession = NULL;
msg.message_id = SWITCH_MESSAGE_INDICATE_JITTER_BUFFER;
msg.string_arg = argv[1];
msg.from = __FILE__;
if ((lsession = switch_core_session_locate(argv[0]))) {
status = switch_core_session_receive_message(lsession, &msg);
switch_core_session_rwunlock(lsession);
}
goto ok;
} else {
goto error;
}
error:
stream->write_function(stream, "-USAGE: %s\n", JITTERBUFFER_SYNTAX);
switch_safe_free(mydata);
return SWITCH_STATUS_SUCCESS;
ok:
switch_safe_free(mydata);
if (status == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "+OK Success\n");
} else {
stream->write_function(stream, "-ERR Operation Failed\n");
}
return SWITCH_STATUS_SUCCESS;
}
#define PHONE_EVENT_SYNTAX "<uuid>"
SWITCH_STANDARD_API(uuid_phone_event_function)
@@ -4278,21 +4407,33 @@ SWITCH_STANDARD_API(strftime_tz_api_function)
char *format = NULL;
const char *tz_name = NULL;
char date[80] = "";
char *mycmd = NULL, *p;
switch_time_t when = 0;
if (!zstr(cmd)) {
format = strchr(cmd, ' ');
tz_name = cmd;
if (format) {
if (cmd) mycmd = strdup(cmd);
if (!zstr(mycmd)) {
tz_name = mycmd;
if ((format = strchr(mycmd, ' '))) {
*format++ = '\0';
}
if ((p = strchr(format, '|'))) {
*p++ = '\0';
when = atol(format);
format = p;
}
}
if (switch_strftime_tz(tz_name, format, date, sizeof(date), 0) == SWITCH_STATUS_SUCCESS) { /* The lookup of the zone may fail. */
if (switch_strftime_tz(tz_name, format, date, sizeof(date), when * 1000000) == SWITCH_STATUS_SUCCESS) { /* The lookup of the zone may fail. */
stream->write_function(stream, "%s", date);
} else {
stream->write_function(stream, "-ERR Invalid Timezone\n");
}
switch_safe_free(mycmd);
return SWITCH_STATUS_SUCCESS;
}
@@ -4715,7 +4856,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "show", "Show", show_function, SHOW_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "sql_escape", "Escape a string to prevent sql injection", sql_escape, SQL_ESCAPE_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "status", "status", status_function, "");
SWITCH_ADD_API(commands_api_interface, "strftime_tz", "strftime_tz", strftime_tz_api_function, "<Timezone_name> [format string]");
SWITCH_ADD_API(commands_api_interface, "strftime_tz", "strftime_tz", strftime_tz_api_function, "<Timezone_name> [<epoch>|][format string]");
SWITCH_ADD_API(commands_api_interface, "stun", "stun", stun_function, "<stun_server>[:port]");
SWITCH_ADD_API(commands_api_interface, "system", "Execute a system command", system_function, SYSTEM_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "time_test", "time_test", time_test_function, "<mss> [count]");
@@ -4731,6 +4872,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "uuid_break", "Break", break_function, BREAK_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_bridge", "uuid_bridge", uuid_bridge_function, "");
SWITCH_ADD_API(commands_api_interface, "uuid_broadcast", "broadcast", uuid_broadcast_function, BROADCAST_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_buglist", "List media bugs on a session", uuid_buglist_function, BUGLIST_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_chat", "Send a chat message", uuid_chat, UUID_CHAT_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_debug_audio", "debug audio", uuid_debug_audio_function, DEBUG_AUDIO_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_deflect", "Send a deflect", uuid_deflect, UUID_DEFLECT_SYNTAX);
@@ -4750,6 +4892,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "uuid_phone_event", "Send and event to the phone", uuid_phone_event_function, PHONE_EVENT_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_preprocess", "Pre-process Channel", preprocess_function, PREPROCESS_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_record", "session record", session_record_function, SESS_REC_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_recovery_refresh", "Send a recovery_refresh", uuid_recovery_refresh, UUID_RECOVERY_REFRESH_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_recv_dtmf", "receive dtmf digits", uuid_recv_dtmf_function, UUID_RECV_DTMF_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_send_dtmf", "send dtmf digits", uuid_send_dtmf_function, UUID_SEND_DTMF_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_session_heartbeat", "uuid_session_heartbeat", uuid_session_heartbeat_function, HEARTBEAT_SYNTAX);
@@ -4758,6 +4901,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "uuid_transfer", "Transfer a session", transfer_function, TRANSFER_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_dual_transfer", "Transfer a session and its partner", dual_transfer_function, DUAL_TRANSFER_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_simplify", "Try to cut out of a call path / attended xfer", uuid_simplify_function, SIMPLIFY_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_jitterbuffer", "Try to cut out of a call path / attended xfer",
uuid_jitterbuffer_function, JITTERBUFFER_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "xml_locate", "find some xml", xml_locate_function, "[root | <section> <tag> <tag_attr_name> <tag_attr_val>]");
SWITCH_ADD_API(commands_api_interface, "xml_wrap", "Wrap another api command in xml", xml_wrap_api_function, "<command> <args>");
switch_console_set_complete("add alias add");
@@ -4843,6 +4988,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add uuid_break ::console::list_uuid both");
switch_console_set_complete("add uuid_bridge ::console::list_uuid ::console::list_uuid");
switch_console_set_complete("add uuid_broadcast ::console::list_uuid");
switch_console_set_complete("add uuid_buglist ::console::list_uuid");
switch_console_set_complete("add uuid_chat ::console::list_uuid");
switch_console_set_complete("add uuid_debug_audio ::console::list_uuid");
switch_console_set_complete("add uuid_deflect ::console::list_uuid");
@@ -4854,6 +5000,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add uuid_flush_dtmf ::console::list_uuid");
switch_console_set_complete("add uuid_getvar ::console::list_uuid");
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_release ::console::list_uuid");
switch_console_set_complete("add uuid_loglevel ::console::list_uuid console");
@@ -4870,7 +5017,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add uuid_phone_event ::console::list_uuid talk");
switch_console_set_complete("add uuid_phone_event ::console::list_uuid hold");
switch_console_set_complete("add uuid_preprocess ::console::list_uuid");
switch_console_set_complete("add uuid_record ::console::list_uuid");
switch_console_set_complete("add uuid_record ::console::list_uuid ::[start:stop");
switch_console_set_complete("add uuid_recovery_refresh ::console::list_uuid");
switch_console_set_complete("add uuid_recv_dtmf ::console::list_uuid");
switch_console_set_complete("add uuid_send_dtmf ::console::list_uuid");
switch_console_set_complete("add uuid_session_heartbeat ::console::list_uuid");
@@ -30,6 +30,7 @@
* Chris Danielson <chris at maxpowersoft dot com>
* Rupa Schomaker <rupa@rupa.com>
* David Weekly <david@weekly.org>
* Joao Mesquita <jmesquita@gmail.com>
*
* mod_conference.c -- Software Conference Bridge
*
@@ -191,7 +192,8 @@ typedef enum {
EFLAG_TRANSFER = (1 << 23),
EFLAG_BGDIAL_RESULT = (1 << 24),
EFLAG_FLOOR_CHANGE = (1 << 25),
EFLAG_MUTE_DETECT = (1 << 26)
EFLAG_MUTE_DETECT = (1 << 26),
EFLAG_RECORD = (1 << 27)
} event_type_t;
typedef struct conference_file_node {
@@ -270,6 +272,7 @@ typedef struct conference_obj {
uint32_t not_talking_buf_len;
int comfort_noise_level;
int is_recording;
int record_count;
int video_running;
uint32_t eflags;
uint32_t verbose_events;
@@ -283,6 +286,8 @@ typedef struct conference_obj {
uint32_t avg_score;
uint32_t avg_itt;
uint32_t avg_tally;
switch_time_t run_time;
char *uuid_str;
} conference_obj_t;
/* Relationship with another member */
@@ -404,7 +409,7 @@ static switch_status_t conference_local_play_file(conference_obj_t *conference,
static switch_status_t conference_member_play_file(conference_member_t *member, char *file, uint32_t leadin);
static switch_status_t conference_member_say(conference_member_t *member, char *text, uint32_t leadin);
static uint32_t conference_member_stop_file(conference_member_t *member, file_stop_t stop);
static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_memory_pool_t *pool);
static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_core_session_t *session, switch_memory_pool_t *pool);
static switch_status_t chat_send(const char *proto, const char *from, const char *to, const char *subject,
const char *body, const char *type, const char *hint);
@@ -436,6 +441,7 @@ static switch_status_t conference_add_event_data(conference_obj_t *conference, s
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Conference-Name", conference->name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Conference-Size", "%u", conference->count);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Conference-Profile-Name", conference->profile_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Conference-Unique-ID", conference->uuid_str);
return status;
}
@@ -468,6 +474,7 @@ static switch_status_t conference_add_event_member_data(conference_member_t *mem
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Hear", "%s", switch_test_flag(member, MFLAG_CAN_HEAR) ? "true" : "false" );
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Speak", "%s", switch_test_flag(member, MFLAG_CAN_SPEAK) ? "true" : "false" );
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Talking", "%s", switch_test_flag(member, MFLAG_TALKING) ? "true" : "false" );
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Mute-Detect", "%s", switch_test_flag(member, MFLAG_MUTE_DETECT) ? "true" : "false" );
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-Type", "%s", switch_test_flag(member, MFLAG_MOD) ? "moderator" : "member");
@@ -563,6 +570,7 @@ static switch_status_t conference_record_stop(conference_obj_t *conference, char
return count;
}
/* Add a custom relationship to a member */
static conference_relationship_t *member_add_relationship(conference_member_t *member, uint32_t id)
{
@@ -684,8 +692,14 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
}
if (!switch_channel_test_app_flag_key("conf_silent", channel, CONF_SILENT_REQ) && !zstr(conference->enter_sound)) {
conference_play_file(conference, conference->enter_sound, CONF_DEFAULT_LEADIN, switch_core_session_get_channel(member->session),
switch_test_flag(conference, CFLAG_WAIT_MOD) ? 0 : 1);
const char * enter_sound = switch_channel_get_variable(channel, "conference_enter_sound");
if (!zstr(enter_sound)) {
conference_play_file(conference, (char *)enter_sound, CONF_DEFAULT_LEADIN,
switch_core_session_get_channel(member->session), !switch_test_flag(conference, CFLAG_WAIT_MOD) ? 0 : 1);
} else {
conference_play_file(conference, conference->enter_sound, CONF_DEFAULT_LEADIN, switch_core_session_get_channel(member->session),
!switch_test_flag(conference, CFLAG_WAIT_MOD) ? 0 : 1);
}
}
}
@@ -1035,6 +1049,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
switch_mutex_unlock(globals.hash_mutex);
conference->is_recording = 0;
conference->record_count = 0;
while (globals.running && !switch_test_flag(conference, CFLAG_DESTRUCT)) {
switch_size_t file_sample_len = samples;
@@ -1099,6 +1114,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
/* Start recording if there's more than one participant. */
if (conference->auto_record && !conference->is_recording && conference->count > 1) {
conference->is_recording = 1;
conference->record_count++;
imember = conference->members;
if (imember) {
switch_channel_t *channel = switch_core_session_get_channel(imember->session);
@@ -2456,7 +2472,7 @@ static void conference_loop_output(conference_member_t *member)
switch_event_destroy(&event);
}
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
/* test to see if outbound channel has answered */
if (switch_channel_test_flag(channel, CF_ANSWERED) && !switch_test_flag(member->conference, CFLAG_ANSWERED)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG,
@@ -2485,7 +2501,9 @@ static void conference_loop_output(conference_member_t *member)
use_buffer = NULL;
mux_used = (uint32_t) switch_buffer_inuse(member->mux_buffer);
use_timer = 1;
if (mux_used) {
if (mux_used < bytes) {
if (++low_count >= 5) {
@@ -2498,10 +2516,7 @@ static void conference_loop_output(conference_member_t *member)
}
}
use_timer = 1;
if (mux_used) {
if (mux_used >= bytes) {
/* Flush the output buffer and write all the data (presumably muxed) back to the channel */
switch_mutex_lock(member->audio_out_mutex);
write_frame.data = data;
@@ -2509,7 +2524,7 @@ static void conference_loop_output(conference_member_t *member)
low_count = 0;
if ((write_frame.datalen = (uint32_t) switch_buffer_read(use_buffer, write_frame.data, bytes))) {
if (write_frame.datalen) {
write_frame.samples = write_frame.datalen / 2;
write_frame.samples = write_frame.datalen / 2;
if( !switch_test_flag(member, MFLAG_CAN_HEAR)) {
memset(write_frame.data, 255, write_frame.datalen);
@@ -2537,6 +2552,7 @@ static void conference_loop_output(conference_member_t *member)
write_frame.datalen = bytes;
write_frame.samples = samples;
memset(write_frame.data, 255, write_frame.datalen);
write_frame.timestamp = timer.samplecount;
member_add_file_data(member, write_frame.data, write_frame.datalen);
if (switch_core_session_write_frame(member->session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
@@ -2599,7 +2615,7 @@ static void conference_loop_output(conference_member_t *member)
switch_channel_cause2str(switch_channel_get_cause(channel)));
/* if it's an outbound channel, store the release cause in the conference struct, we might need it */
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
member->conference->bridge_hangup_cause = switch_channel_get_cause(channel);
}
@@ -2623,6 +2639,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
switch_timer_t timer = { 0 };
uint32_t rlen;
switch_size_t data_buf_len;
switch_event_t *event;
data_buf_len = samples * sizeof(int16_t);
@@ -2701,6 +2718,15 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
switch_core_file_set_string(&fh, SWITCH_AUDIO_COL_STR_ARTIST, "FreeSWITCH mod_conference Software Conference Module");
if (test_eflag(conference, EFLAG_RECORD) &&
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_add_event_data(conference, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "start-recording");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Path", rec->path);
switch_event_fire(&event);
}
while (switch_test_flag(member, MFLAG_RUNNING) && switch_test_flag(conference, CFLAG_RUNNING) && conference->count) {
switch_size_t len = 0;
mux_used = (uint32_t) switch_buffer_inuse(member->mux_buffer);
@@ -2755,6 +2781,12 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
switch_core_file_close(&fh);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Recording of %s Stopped\n", rec->path);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_add_event_data(conference, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "stop-recording");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Path", rec->path);
switch_event_fire(&event);
}
if (rec->pool) {
switch_memory_pool_t *pool = rec->pool;
@@ -3759,6 +3791,13 @@ static void conference_xlist(conference_obj_t *conference, switch_xml_t x_confer
switch_xml_set_attr_d(x_conference, "dynamic", "true");
}
if (conference->record_count > 0) {
switch_xml_set_attr_d(x_conference, "recording", "true");
}
switch_snprintf(i, sizeof(i), "%d", switch_epoch_time_now(NULL) - conference->run_time);
switch_xml_set_attr_d(x_conference, "run_time", ival);
if (conference->agc_level) {
char tmp[30] = "";
switch_snprintf(tmp, sizeof(tmp), "%d", conference->agc_level);
@@ -3825,6 +3864,9 @@ static void conference_xlist(conference_obj_t *conference, switch_xml_t x_confer
x_tag = switch_xml_add_child_d(x_flags, "can_speak", count++);
switch_xml_set_txt_d(x_tag, switch_test_flag(member, MFLAG_CAN_SPEAK) ? "true" : "false");
x_tag = switch_xml_add_child_d(x_flags, "mute_detect", count++);
switch_xml_set_txt_d(x_tag, switch_test_flag(member, MFLAG_MUTE_DETECT) ? "true" : "false");
x_tag = switch_xml_add_child_d(x_flags, "talking", count++);
switch_xml_set_txt_d(x_tag, switch_test_flag(member, MFLAG_TALKING) ? "true" : "false");
@@ -4243,6 +4285,7 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc
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);
@@ -4313,7 +4356,7 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc
}
/* Create the conference object. */
new_conference = conference_new(conf_name, xml_cfg, pool);
new_conference = conference_new(conf_name, xml_cfg, member->session, pool);
/* Release the config registry handle */
if (cxml) {
@@ -4366,6 +4409,13 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc
}
}
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);
stream->write_function(stream, "OK Member '%d' sent to conference %s.\n", member->id, argv[2]);
@@ -4412,6 +4462,7 @@ static switch_status_t conf_api_sub_record(conference_obj_t *conference, switch_
return SWITCH_STATUS_GENERR;
stream->write_function(stream, "Record file %s\n", argv[2]);
conference->record_count++;
launch_conference_record_thread(conference, argv[2]);
return SWITCH_STATUS_SUCCESS;
}
@@ -4419,6 +4470,7 @@ static switch_status_t conf_api_sub_record(conference_obj_t *conference, switch_
static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv)
{
int all;
switch_event_t *event;
switch_assert(conference != NULL);
switch_assert(stream != NULL);
@@ -4430,6 +4482,20 @@ static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switc
stream->write_function(stream, "Stop recording file %s\n", argv[2]);
if (!conference_record_stop(conference, all ? NULL : argv[2]) && !all) {
stream->write_function(stream, "non-existant recording '%s'\n", argv[2]);
} else {
if (all) {
conference->record_count = 0;
} else {
conference->record_count--;
}
if (test_eflag(conference, EFLAG_RECORD) &&
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_add_event_data(conference, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "stop-recording");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Path", all ? "all" : argv[2]);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Other-Recordings", conference->record_count ? "true" : "false");
switch_event_fire(&event);
}
}
return SWITCH_STATUS_SUCCESS;
@@ -5136,6 +5202,8 @@ static void clear_eflags(char *events, uint32_t *f)
*f &= ~EFLAG_BGDIAL_RESULT;
} else if (!strcmp(event, "floor-change")) {
*f &= ~EFLAG_FLOOR_CHANGE;
} else if (!strcmp(event, "record")) {
*f &= ~EFLAG_RECORD;
}
event = next;
@@ -5374,6 +5442,14 @@ SWITCH_STANDARD_APP(conference_function)
}
#endif
if (switch_channel_test_flag(channel, CF_RECOVERED)) {
const char *check = switch_channel_get_variable(channel, "last_transfered_conference");
if (!zstr(check)) {
conf_name = (char *) check;
}
}
switch_event_create(&params, SWITCH_EVENT_COMMAND);
switch_assert(params);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "conf_name", conf_name);
@@ -5410,7 +5486,7 @@ SWITCH_STANDARD_APP(conference_function)
}
/* Create the conference object. */
conference = conference_new(conf_name, xml_cfg, NULL);
conference = conference_new(conf_name, xml_cfg, session, NULL);
if (!conference) {
goto done;
@@ -5436,7 +5512,7 @@ SWITCH_STANDARD_APP(conference_function)
launch_conference_thread(conference);
} else {
int enforce_security = !switch_channel_test_flag(channel, CF_OUTBOUND);
int enforce_security = switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND;
const char *pvar = switch_channel_get_variable(channel, "conference_enforce_security");
if (pvar) {
@@ -5455,7 +5531,7 @@ SWITCH_STANDARD_APP(conference_function)
const char *max_members_str;
/* couldn't find the conference, create one */
conference = conference_new(conf_name, xml_cfg, NULL);
conference = conference_new(conf_name, xml_cfg, session, NULL);
if (!conference) {
goto done;
@@ -5645,7 +5721,7 @@ SWITCH_STANDARD_APP(conference_function)
} else {
/* if we're not using "bridge:" set the conference answered flag */
/* and this isn't an outbound channel, answer the call */
if (!switch_channel_test_flag(channel, CF_OUTBOUND))
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND)
switch_set_flag(conference, CFLAG_ANSWERED);
}
@@ -5737,22 +5813,29 @@ SWITCH_STANDARD_APP(conference_function)
if (conference && switch_test_flag(&member, MFLAG_KICKED) && conference->kicked_sound) {
char *toplay = NULL;
char *dfile = NULL;
char *expanded = NULL;
if (!strncasecmp(conference->kicked_sound, "say:", 4)) {
if (conference->tts_engine && conference->tts_voice) {
switch_ivr_speak_text(session, conference->tts_engine, conference->tts_voice, conference->kicked_sound + 4, NULL);
}
} else {
if ((expanded = switch_channel_expand_variables(switch_core_session_get_channel(session), conference->kicked_sound)) != conference->kicked_sound) {
toplay = expanded;
} else {
expanded = NULL;
toplay = conference->kicked_sound;
}
if (conference->sound_prefix) {
dfile = switch_mprintf("%s%s%s", conference->sound_prefix, SWITCH_PATH_SEPARATOR, conference->kicked_sound);
dfile = switch_mprintf("%s%s%s", conference->sound_prefix, SWITCH_PATH_SEPARATOR, toplay);
switch_assert(dfile);
toplay = dfile;
} else {
toplay = conference->kicked_sound;
}
switch_ivr_play_file(session, NULL, toplay, NULL);
switch_safe_free(dfile);
switch_safe_free(expanded);
}
}
@@ -5880,7 +5963,7 @@ static conference_obj_t *conference_find(char *name)
}
/* create a new conferene with a specific profile */
static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_memory_pool_t *pool)
static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_core_session_t *session, switch_memory_pool_t *pool)
{
conference_obj_t *conference;
switch_xml_t xml_kvp;
@@ -5923,13 +6006,50 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_m
char *verbose_events = NULL;
char *auto_record = NULL;
char *terminate_on_silence = NULL;
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH+1];
switch_uuid_t uuid;
switch_codec_implementation_t read_impl = { 0 };
switch_channel_t *channel = NULL;
const char *force_rate = NULL, *force_interval = NULL;
uint32_t force_rate_i = 0, force_interval_i = 0;
/* Validate the conference name */
if (zstr(name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Record! no name.\n");
return NULL;
}
if (session) {
uint32_t tmp;
switch_core_session_get_read_impl(session, &read_impl);
channel = switch_core_session_get_channel(session);
if ((force_rate = switch_channel_get_variable(channel, "conference_force_rate"))) {
if (!strcasecmp(force_rate, "auto")) {
force_rate_i = read_impl.actual_samples_per_second;
} else {
tmp = atoi(force_rate);
if (tmp == 8000 || tmp == 12000 || tmp == 16000 || tmp == 24000 || tmp == 32000 || tmp == 48000) {
force_rate_i = rate = tmp;
}
}
}
if ((force_interval = switch_channel_get_variable(channel, "conference_force_interval"))) {
if (!strcasecmp(force_interval, "auto")) {
force_interval_i = read_impl.microseconds_per_packet / 1000;
} else {
tmp = atoi(force_interval);
if (SWITCH_ACCEPTABLE_INTERVAL(tmp)) {
force_interval_i = interval = tmp;
}
}
}
}
switch_mutex_lock(globals.hash_mutex);
/* parse the profile tree for param values */
@@ -5950,20 +6070,33 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_m
var = buf;
}
if (!strcasecmp(var, "rate") && !zstr(val)) {
if (!force_rate_i && !strcasecmp(var, "rate") && !zstr(val)) {
uint32_t tmp = atoi(val);
if (tmp == 8000 || tmp == 12000 || tmp == 16000 || tmp == 24000 || tmp == 32000 || tmp == 48000) {
rate = tmp;
if (session && tmp == 0) {
if (!strcasecmp(val, "auto")) {
rate = read_impl.actual_samples_per_second;
}
} else {
if (tmp == 8000 || tmp == 12000 || tmp == 16000 || tmp == 24000 || tmp == 32000 || tmp == 48000) {
rate = tmp;
}
}
} else if (!strcasecmp(var, "domain") && !zstr(val)) {
domain = val;
} else if (!strcasecmp(var, "interval") && !zstr(val)) {
} else if (!force_interval_i && !strcasecmp(var, "interval") && !zstr(val)) {
uint32_t tmp = atoi(val);
if (SWITCH_ACCEPTABLE_INTERVAL(tmp)) {
interval = tmp;
if (session && tmp == 0) {
if (!strcasecmp(val, "auto")) {
interval = read_impl.microseconds_per_packet / 1000;
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Interval must be multipe of 10 and less than %d, Using default of 20\n", SWITCH_MAX_INTERVAL);
if (SWITCH_ACCEPTABLE_INTERVAL(tmp)) {
interval = tmp;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Interval must be multipe of 10 and less than %d, Using default of 20\n", SWITCH_MAX_INTERVAL);
}
}
} else if (!strcasecmp(var, "timer-name") && !zstr(val)) {
timer_name = val;
@@ -6111,6 +6244,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_m
conference->caller_id_name = switch_core_strdup(conference->pool, caller_id_name);
conference->caller_id_number = switch_core_strdup(conference->pool, caller_id_number);
conference->caller_controls = switch_core_strdup(conference->pool, caller_controls);
conference->run_time = switch_epoch_time_now(NULL);
if (!zstr(perpetual_sound)) {
@@ -6233,6 +6367,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_m
} else {
conference->domain = "cluecon.com";
}
conference->rate = rate;
conference->interval = interval;
@@ -6252,6 +6387,12 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_m
conference->verbose_events = 1;
}
/* Create the conference unique identifier */
switch_uuid_get(&uuid);
switch_uuid_format(uuid_str, &uuid);
conference->uuid_str = switch_core_strdup(conference->pool, uuid_str);
/* Activate the conference mutex for exclusivity */
switch_mutex_init(&conference->mutex, SWITCH_MUTEX_NESTED, conference->pool);
switch_mutex_init(&conference->flag_mutex, SWITCH_MUTEX_NESTED, conference->pool);
+44 -3
View File
@@ -269,7 +269,7 @@ SWITCH_STANDARD_APP(bind_digit_action_function)
}
#define DETECT_SPEECH_SYNTAX "<mod_name> <gram_name> <gram_path> [<addr>] OR grammar <gram_name> [<path>] OR pause OR resume"
#define DETECT_SPEECH_SYNTAX "<mod_name> <gram_name> <gram_path> [<addr>] OR grammar <gram_name> [<path>] OR nogrammar <gram_name> OR pause OR resume OR stop OR param <name> <value>"
SWITCH_STANDARD_APP(detect_speech_function)
{
char *argv[4];
@@ -957,6 +957,17 @@ SWITCH_STANDARD_APP(redirect_function)
switch_core_session_receive_message(session, &msg);
}
SWITCH_STANDARD_APP(jitterbuffer_function)
{
switch_core_session_message_t msg = { 0 };
/* Tell the channel to change the jitter buffer */
msg.from = __FILE__;
msg.string_arg = data;
msg.message_id = SWITCH_MESSAGE_INDICATE_JITTER_BUFFER;
switch_core_session_receive_message(session, &msg);
}
SWITCH_STANDARD_APP(display_function)
{
switch_core_session_message_t msg = { 0 };
@@ -990,6 +1001,17 @@ SWITCH_STANDARD_APP(deflect_function)
switch_core_session_receive_message(session, &msg);
}
SWITCH_STANDARD_APP(recovery_refresh_function)
{
switch_core_session_message_t msg = { 0 };
/* Tell the channel to recovery_refresh the call */
msg.from = __FILE__;
msg.string_arg = data;
msg.message_id = SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH;
switch_core_session_receive_message(session, &msg);
}
SWITCH_STANDARD_APP(sched_cancel_function)
{
@@ -1303,13 +1325,22 @@ SWITCH_STANDARD_API(strftime_api_function)
char date[80] = "";
switch_time_t thetime;
char *p;
if (!zstr(cmd) && (p = strchr(cmd, '|'))) {
thetime = switch_time_make(atoi(cmd), 0);
char *mycmd = NULL;
if (!zstr(cmd)) {
mycmd = strdup(cmd);
}
if (!zstr(mycmd) && (p = strchr(cmd, '|'))) {
*p++ = '\0';
thetime = switch_time_make(atol(cmd), 0);
cmd = p + 1;
} else {
thetime = switch_micro_time_now();
}
switch_time_exp_lt(&tm, thetime);
if (zstr(cmd)) {
switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
} else {
@@ -3092,6 +3123,11 @@ SWITCH_STANDARD_APP(verbose_events_function)
switch_channel_set_flag(switch_core_session_get_channel(session), CF_VERBOSE_EVENTS);
}
SWITCH_STANDARD_APP(cng_plc_function)
{
switch_channel_set_flag(switch_core_session_get_channel(session), CF_CNG_PLC);
}
SWITCH_STANDARD_APP(early_hangup_function)
{
switch_channel_set_flag(switch_core_session_get_channel(session), CF_EARLY_HANGUP);
@@ -3477,6 +3513,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
"<ip> <acl | cidr> [<hangup_cause>]", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "verbose_events", "Make ALL Events verbose.", "Make ALL Events verbose.", verbose_events_function, "",
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "cng_plc", "Do PLC on CNG frames", "", cng_plc_function, "",
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "early_hangup", "Enable early hangup", "", early_hangup_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "sleep", "Pause a channel", SLEEP_LONG_DESC, sleep_function, "<pausemilliseconds>", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "delay_echo", "echo audio at a specified delay", "Delay n ms", delay_function, "<delay ms>", SAF_NONE);
@@ -3513,11 +3551,14 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SWITCH_ADD_APP(app_interface, "ivr", "Run an ivr menu", "Run an ivr menu.", ivr_application_function, "<menu_name>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "redirect", "Send session redirect", "Send a redirect message to a session.", redirect_function, "<redirect_data>",
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "jitterbuffer", "Send session jitterbuffer", "Send a jitterbuffer message to a session.",
jitterbuffer_function, "<jitterbuffer_data>", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "send_display", "Send session a new display", "Send session a new display.", display_function, "<text>",
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "respond", "Send session respond", "Send a respond message to a session.", respond_function, "<respond_data>",
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "deflect", "Send call deflect", "Send a call deflect.", deflect_function, "<deflect_data>", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "recovery_refresh", "Send call recovery_refresh", "Send a call recovery_refresh.", recovery_refresh_function, "", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "queue_dtmf", "Queue dtmf to be sent", "Queue dtmf to be sent from a session", queue_dtmf_function, "<dtmf_data>",
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "send_dtmf", "Send dtmf to be sent", "Send dtmf to be sent from a session", send_dtmf_function, "<dtmf_data>",
+70 -43
View File
@@ -291,6 +291,7 @@ static switch_status_t fifo_queue_popfly(fifo_queue_t *queue, const char *uuid)
struct fifo_node {
char *name;
switch_mutex_t *mutex;
switch_mutex_t *update_mutex;
fifo_queue_t *fifo_list[MAX_PRI];
switch_hash_t *consumer_hash;
int outbound_priority;
@@ -801,6 +802,7 @@ static fifo_node_t *create_node(const char *name, uint32_t importance, switch_mu
switch_core_hash_init(&node->consumer_hash, node->pool);
switch_thread_rwlock_create(&node->rwlock, node->pool);
switch_mutex_init(&node->mutex, SWITCH_MUTEX_NESTED, node->pool);
switch_mutex_init(&node->update_mutex, SWITCH_MUTEX_NESTED, node->pool);
cbt.buf = outbound_count;
cbt.len = sizeof(outbound_count);
sql = switch_mprintf("select count(*) from fifo_outbound where fifo_name = '%q'", name);
@@ -1193,10 +1195,10 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
if (node) {
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
node->busy = 0;
node->ring_consumer_count = 1;
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
} else {
goto end;
}
@@ -1437,10 +1439,10 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
cbh->ready = 1;
if (node) {
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
node->ring_consumer_count = 0;
node->busy = 0;
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
}
@@ -1501,10 +1503,10 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
switch_mutex_unlock(globals.mutex);
if (node) {
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
node->ring_consumer_count++;
node->busy = 0;
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
}
switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS);
@@ -1601,12 +1603,12 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
switch_event_destroy(&ovars);
if (node) {
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
if (node->ring_consumer_count-- < 0) {
node->ring_consumer_count = 0;
}
node->busy = 0;
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
}
switch_core_destroy_memory_pool(&h->pool);
@@ -1754,9 +1756,36 @@ static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *o
if (globals.debug) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Trying priority: %d\n", cur_priority);
restart:
for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
if ((node = (fifo_node_t *) val)) {
int x = 0;
switch_event_t *pop;
if (node->ready == FIFO_DELAY_DESTROY) {
if (switch_thread_rwlock_trywrlock(node->rwlock) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s removed.\n", node->name);
switch_core_hash_delete(globals.fifo_hash, node->name);
for (x = 0; x < MAX_PRI; x++) {
while (fifo_queue_pop(node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
switch_event_destroy(&pop);
}
}
node->ready = 0;
switch_core_hash_destroy(&node->consumer_hash);
switch_mutex_unlock(node->mutex);
switch_mutex_unlock(node->update_mutex);
switch_thread_rwlock_unlock(node->rwlock);
switch_core_destroy_memory_pool(&node->pool);
goto restart;
}
}
if (node->outbound_priority == 0) node->outbound_priority = 5;
if (node->has_outbound && node->ready && !node->busy && node->outbound_priority == cur_priority) {
ppl_waiting = node_caller_count(node);
@@ -2144,7 +2173,7 @@ SWITCH_STANDARD_APP(fifo_function)
char *mydata = NULL, *argv[5] = { 0 };
fifo_node_t *node = NULL, *node_list[MAX_NODES_PER_CONSUMER + 1] = { 0 };
switch_channel_t *channel = switch_core_session_get_channel(session);
int do_wait = 1, node_count = 0, i = 0;
int do_destroy = 0, do_wait = 1, node_count = 0, i = 0;
const char *moh = NULL;
const char *announce = NULL;
switch_event_t *event = NULL;
@@ -2220,11 +2249,9 @@ SWITCH_STANDARD_APP(fifo_function)
node = create_node(nlist[i], importance, globals.sql_mutex);
node->ready = 1;
}
node_list[node_count++] = node;
}
if (switch_true(switch_channel_get_variable(channel, "fifo_destroy_after_use")) && node->ready == 1) {
node->ready = FIFO_DELAY_DESTROY;
switch_thread_rwlock_rdlock(node->rwlock);
node_list[node_count++] = node;
}
switch_mutex_unlock(globals.mutex);
@@ -2306,7 +2333,7 @@ SWITCH_STANDARD_APP(fifo_function)
switch_channel_answer(channel);
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
if ((pri = switch_channel_get_variable(channel, "fifo_priority"))) {
p = atoi(pri);
@@ -2344,7 +2371,7 @@ SWITCH_STANDARD_APP(fifo_function)
switch_channel_set_variable(channel, "fifo_priority", tmp);
}
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
ts = switch_micro_time_now();
switch_time_exp_lt(&tm, ts);
@@ -2450,9 +2477,9 @@ SWITCH_STANDARD_APP(fifo_function)
}
switch_mutex_lock(globals.mutex);
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
node_remove_uuid(node, uuid);
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
send_presence(node);
check_cancel(node);
switch_mutex_unlock(globals.mutex);
@@ -2682,9 +2709,9 @@ SWITCH_STANDARD_APP(fifo_function)
}
if (pop && !node_caller_count(node)) {
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
node->start_waiting = 0;
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
}
}
@@ -3074,22 +3101,22 @@ SWITCH_STANDARD_APP(fifo_function)
done:
switch_mutex_lock(globals.mutex);
if (node && node->ready == FIFO_DELAY_DESTROY && node->consumer_count == 0 && node_caller_count(node) == 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "%s removed.\n", node->name);
switch_core_hash_delete(globals.fifo_hash, node->name);
switch_thread_rwlock_wrlock(node->rwlock);
node->ready = 0;
switch_mutex_lock(node->mutex);
switch_core_hash_destroy(&node->consumer_hash);
switch_mutex_unlock(node->mutex);
switch_thread_rwlock_unlock(node->rwlock);
switch_core_destroy_memory_pool(&node->pool);
if (switch_true(switch_channel_get_variable(channel, "fifo_destroy_after_use"))) {
do_destroy = 1;
}
switch_mutex_lock(globals.mutex);
for (i = 0; i < node_count; i++) {
if (!(node = node_list[i])) {
continue;
}
switch_thread_rwlock_unlock(node->rwlock);
if (node->ready == 1 && do_destroy) {
node->ready = FIFO_DELAY_DESTROY;
}
}
switch_mutex_unlock(globals.mutex);
switch_channel_clear_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_BRIDGE_TAG);
switch_core_media_bug_resume(session);
@@ -3699,9 +3726,9 @@ SWITCH_STANDARD_API(fifo_api_function)
switch_hash_this(hi, &var, NULL, &val);
node = (fifo_node_t *) val;
len = node_caller_count(node);
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
stream->write_function(stream, "%s:%d:%d:%d\n", (char *) var, node->consumer_count, node_caller_count(node), len);
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
x++;
}
@@ -3710,9 +3737,9 @@ SWITCH_STANDARD_API(fifo_api_function)
}
} else if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
len = node_caller_count(node);
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
stream->write_function(stream, "%s:%d:%d:%d\n", argv[1], node->consumer_count, node_caller_count(node), len);
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
} else {
stream->write_function(stream, "none\n");
}
@@ -3722,9 +3749,9 @@ SWITCH_STANDARD_API(fifo_api_function)
switch_hash_this(hi, &var, NULL, &val);
node = (fifo_node_t *) val;
len = node_caller_count(node);
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
stream->write_function(stream, "%s:%d\n", (char *) var, node->has_outbound);
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
x++;
}
@@ -3733,9 +3760,9 @@ SWITCH_STANDARD_API(fifo_api_function)
}
} else if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
len = node_caller_count(node);
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
stream->write_function(stream, "%s:%d\n", argv[1], node->has_outbound);
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
} else {
stream->write_function(stream, "none\n");
}
@@ -4108,7 +4135,7 @@ static switch_status_t load_config(int reload, int del_all)
node->ready = FIFO_DELAY_DESTROY;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s removed.\n", node->name);
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
for (x = 0; x < MAX_PRI; x++) {
while (fifo_queue_pop(node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
switch_event_destroy(&pop);
@@ -4117,7 +4144,7 @@ static switch_status_t load_config(int reload, int del_all)
switch_core_hash_delete(globals.fifo_hash, node->name);
switch_core_hash_destroy(&node->consumer_hash);
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
switch_core_destroy_memory_pool(&node->pool);
goto top;
}
@@ -4393,7 +4420,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown)
switch_hash_this(hi, NULL, NULL, &val);
node = (fifo_node_t *) val;
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
switch_mutex_lock(node->mutex);
for (x = 0; x < MAX_PRI; x++) {
while (fifo_queue_pop(node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
@@ -4403,7 +4430,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown)
switch_mutex_unlock(node->mutex);
switch_core_hash_delete(globals.fifo_hash, node->name);
switch_core_hash_destroy(&node->consumer_hash);
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
switch_core_destroy_memory_pool(&node->pool);
}
@@ -188,10 +188,12 @@ static switch_status_t do_snap(switch_core_session_t *session)
switch_core_file_close(&fh);
switch_core_set_variable("file", file);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Wrote %s\n", file);
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_SUCCESS;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s Bug is not attached.\n", switch_channel_get_name(channel));
return SWITCH_STATUS_FALSE;
}
#define SNAP_SYNTAX "start <sec> <read|write>"
@@ -249,7 +251,7 @@ SWITCH_STANDARD_APP(snapshot_app_function)
}
#define SNAP_API_SYNTAX "<uuid> <warning>"
#define SNAP_API_SYNTAX "<uuid> snap|start [<sec> read|write <base>]"
SWITCH_STANDARD_API(snapshot_function)
{
char *mycmd = NULL, *argv[5] = { 0 };
@@ -260,7 +262,7 @@ SWITCH_STANDARD_API(snapshot_function)
argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
}
if (zstr(cmd) || argc < 1 || zstr(argv[0])) {
if (zstr(cmd) || argc < 2 || zstr(argv[0])) {
stream->write_function(stream, "-USAGE: %s\n", SNAP_API_SYNTAX);
goto done;
} else {
@@ -270,9 +272,9 @@ SWITCH_STANDARD_API(snapshot_function)
if (!strcasecmp(argv[1], "snap")) {
status = do_snap(lsession);
} else if (!strcasecmp(argv[1], "start")) {
char *sec = argv[1];
char *fl = argv[2];
const char *base = argv[3];
char *sec = argv[2];
char *fl = argv[3];
const char *base = argv[4];
int seconds = 5;
switch_media_bug_flag_t flags = SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_READ_PING;
@@ -325,10 +327,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_snapshot_load)
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hello World!\n");
SWITCH_ADD_API(api_interface, "uuid_snapshot", "Snapshot API", snapshot_function, SNAP_API_SYNTAX);
SWITCH_ADD_APP(app_interface, "snapshot", "", "", snapshot_app_function, SNAP_SYNTAX, SAF_SUPPORT_NOMEDIA);
switch_console_set_complete("add uuid_snapshot ::console::list_uuid");
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
+9 -9
View File
@@ -131,7 +131,6 @@ SWITCH_STANDARD_API(dump_hash)
static switch_status_t process_event(switch_event_t *event)
{
switch_core_session_t *session = NULL;
switch_channel_t *channel;
char *username[3] = { 0 };
char *domain[3] = { 0 };
char key[512];
@@ -172,18 +171,19 @@ static switch_status_t process_event(switch_event_t *event)
return SWITCH_STATUS_FALSE;
}
session = switch_core_session_locate(uuid);
channel = switch_core_session_get_channel(session);
if ((session = switch_core_session_locate(uuid))) {
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop \n", uuid, key);
my_uuid = switch_event_get_header(event, "Unique-ID");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop \n", uuid, key);
my_uuid = switch_event_get_header(event, "Unique-ID");
switch_channel_set_variable(channel, "spy_uuid", my_uuid);
switch_channel_set_variable(channel, "spy_uuid", my_uuid);
switch_channel_set_state(channel, CS_EXCHANGE_MEDIA);
switch_channel_set_flag(channel, CF_BREAK);
switch_channel_set_state(channel, CS_EXCHANGE_MEDIA);
switch_channel_set_flag(channel, CF_BREAK);
switch_core_session_rwunlock(session);
switch_core_session_rwunlock(session);
}
return SWITCH_STATUS_SUCCESS;
}
@@ -1324,7 +1324,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
caller_profile = tech_pvt->caller_profile;
caller_profile->destination_number = rdest;
switch_channel_set_flag(channel, CF_OUTBOUND);
switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
switch_channel_set_state(channel, CS_INIT);
gsmopen_call(tech_pvt, rdest, 30);
+2 -3
View File
@@ -589,7 +589,7 @@ FSH323EndPoint::FSH323EndPoint()
,m_fax_old_asn(false)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"======>FSH323EndPoint::FSH323EndPoint [%p]\n",this);
terminalType = e_GatewayOnly;
terminalType = e_GatewayAndMC;
}
FSH323EndPoint::~FSH323EndPoint()
@@ -725,7 +725,6 @@ FSH323Connection::FSH323Connection(FSH323EndPoint& endpoint, H323Transport* tran
name += outbound_profile->destination_number;
switch_channel_set_name(m_fsChannel, name);
switch_channel_set_flag(m_fsChannel, CF_OUTBOUND);
switch_channel_set_state(m_fsChannel, CS_INIT);
}
@@ -1508,7 +1507,7 @@ switch_status_t FSH323Connection::receive_message(switch_core_session_message_t
break;
}
case SWITCH_MESSAGE_INDICATE_ANSWER: {
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_FALSE;
}
AnsweringCall(H323Connection::AnswerCallNow);
@@ -868,7 +868,6 @@ switch_status_t Board::KhompPvt::justStart(switch_caller_profile_t *profile)
_caller_profile = switch_caller_profile_clone(_session, profile);
switch_channel_set_caller_profile(channel, _caller_profile);
switch_channel_set_flag(channel, CF_OUTBOUND);
switch_channel_set_state(channel, CS_INIT);
}
else
+2 -3
View File
@@ -580,7 +580,6 @@ FSConnection::FSConnection(OpalCall & call, FSEndPoint & endpoint, void* userDat
name += outbound_profile->destination_number;
switch_channel_set_name(m_fsChannel, name);
switch_channel_set_flag(m_fsChannel, CF_OUTBOUND);
switch_channel_set_state(m_fsChannel, CS_INIT);
}
}
@@ -966,7 +965,7 @@ switch_status_t FSConnection::receive_message(switch_core_session_message_t *msg
It would only happen if someone called switch_channel_answer() instead of switch_channel_mark_answered() on an outbound call.
it should not do anything if someone does it by accident somewhere hense this in both cases:
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_FALSE;
}
@@ -1025,7 +1024,7 @@ switch_status_t FSConnection::receive_message(switch_core_session_message_t *msg
{
int fixed = 0;
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_FALSE;
}
@@ -48,7 +48,7 @@ sub _find {
my ($name, $value) = ($1,hex($2));
$sub{$name} = sub () { $value };
$const{$name} = $value;
} elsif(/^\s*struct\s+([a-z_]+)\s*\{\s*$/) {
} elsif(/^\s*struct\s+PACKED\s+([a-z_]+)\s*\{\s*$/) {
my $struct_name = $1;
$struct{$struct_name} = [];
while(<$fh>) {
@@ -1080,8 +1080,6 @@ switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, swi
switch_channel_set_caller_profile(nchannel, caller_profile);
tech_pvt->caller_profile = caller_profile;
switch_channel_set_flag(nchannel, CF_OUTBOUND);
if ((sql = switch_mprintf(
"INSERT INTO skinny_active_lines "
"(device_name, device_instance, line_instance, channel_uuid, call_id, call_state) "
@@ -42,6 +42,7 @@
#define SKINNY_EVENT_UNREGISTER "skinny::unregister"
#define SKINNY_EVENT_EXPIRE "skinny::expire"
#define SKINNY_EVENT_ALARM "skinny::alarm"
#define SKINNY_EVENT_XML_ALARM "skinny::xml_alarm"
#define SKINNY_EVENT_CALL_STATE "skinny::call_state"
#define SKINNY_EVENT_USER_TO_DEVICE "skinny::user_to_device"
#define SKINNY_EVENT_DEVICE_TO_USER "skinny::device_to_user"
@@ -547,12 +547,15 @@ struct PACKED service_url_stat_res_message {
#define USER_TO_DEVICE_DATA_VERSION1_MESSAGE 0x013F
/* See struct PACKED extended_data_message */
/* XMLAlarmMessage */
#define XML_ALARM_MESSAGE 0x015A
/*****************************************************************************/
/* SKINNY MESSAGE */
/*****************************************************************************/
#define SKINNY_MESSAGE_FIELD_SIZE 4 /* 4-bytes field */
#define SKINNY_MESSAGE_HEADERSIZE 12 /* three 4-bytes fields */
#define SKINNY_MESSAGE_MAXSIZE 1000
#define SKINNY_MESSAGE_MAXSIZE 2048
union skinny_data {
/* no data for KEEP_ALIVE_MESSAGE */
@@ -624,8 +627,7 @@ union skinny_data {
struct extended_data_message extended_data;
uint16_t as_uint16;
char as_char;
void *raw;
char as_char[1];
};
/*
+25 -3
View File
@@ -343,7 +343,7 @@ switch_status_t skinny_session_send_call_info(switch_core_session_t *session, li
zstr((called_party_number = switch_channel_get_variable(channel, "destination_number")))) {
called_party_number = "0000000000";
}
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
call_type = SKINNY_INBOUND_CALL;
} else {
call_type = SKINNY_OUTBOUND_CALL;
@@ -1674,7 +1674,7 @@ switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *liste
);
switch_set_flag_locked(tech_pvt, TFLAG_IO);
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
switch_channel_mark_answered(channel);
}
if (switch_channel_test_flag(channel, CF_HOLD)) {
@@ -1963,6 +1963,26 @@ switch_status_t skinny_handle_extended_data_message(listener_t *listener, skinny
return SWITCH_STATUS_SUCCESS;
}
switch_status_t skinny_handle_xml_alarm(listener_t *listener, skinny_message_t *request)
{
switch_event_t *event = NULL;
char *tmp = NULL;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
"Received XML alarm.\n");
/* skinny::xml_alarm event */
skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_XML_ALARM);
/* Ensure that the body is null-terminated */
tmp = malloc(request->length - 4 + 1);
memcpy(tmp, request->data.as_char, request->length - 4);
tmp[request->length - 4] = '\0';
switch_event_add_body(event, "%s", tmp);
switch_safe_free(tmp);
switch_event_fire(&event);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *request)
{
if (listener->profile->debug >= 10 || request->type != KEEP_ALIVE_MESSAGE) {
@@ -1970,7 +1990,7 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re
"Received %s (type=%x,length=%d) from %s:%d.\n", skinny_message_type2str(request->type), request->type, request->length,
listener->device_name, listener->device_instance);
}
if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE) {
if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE && request->type != XML_ALARM_MESSAGE) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Device should send a register message first.\n");
return SWITCH_STATUS_FALSE;
@@ -2032,6 +2052,8 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re
return skinny_handle_extended_data_message(listener, request);
case DEVICE_TO_USER_DATA_RESPONSE_VERSION1_MESSAGE:
return skinny_handle_extended_data_message(listener, request);
case XML_ALARM_MESSAGE:
return skinny_handle_xml_alarm(listener, request);
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Unhandled request %s (type=%x,length=%d).\n", skinny_message_type2str(request->type), request->type, request->length);
@@ -99,6 +99,7 @@ struct skinny_table SKINNY_MESSAGE_TYPES[] = {
{"DisplayPriNotifyMessage", DISPLAY_PRI_NOTIFY_MESSAGE},
{"ServiceUrlStatMessage", SERVICE_URL_STAT_RES_MESSAGE},
{"UserToDeviceDataVersion1Message", USER_TO_DEVICE_DATA_VERSION1_MESSAGE},
{"XMLAlarmMessage", XML_ALARM_MESSAGE},
{NULL, 0}
};
SKINNY_DECLARE_ID2STR(skinny_message_type2str, SKINNY_MESSAGE_TYPES, "UnknownMessage")
+1 -1
View File
@@ -87,7 +87,7 @@ uint32_t func(const char *str)\
}
extern struct skinny_table SKINNY_MESSAGE_TYPES[65];
extern struct skinny_table SKINNY_MESSAGE_TYPES[66];
const char *skinny_message_type2str(uint32_t id);
uint32_t skinny_str2message_type(const char *str);
#define SKINNY_PUSH_MESSAGE_TYPES SKINNY_DECLARE_PUSH_MATCH(SKINNY_MESSAGE_TYPES)
@@ -1364,7 +1364,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
caller_profile = tech_pvt->caller_profile;
caller_profile->destination_number = rdest;
switch_channel_set_flag(channel, CF_OUTBOUND);
switch_mutex_lock(tech_pvt->flag_mutex);
switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
switch_mutex_unlock(tech_pvt->flag_mutex);
@@ -0,0 +1,43 @@
# Comment/uncomment the following line to disable/enable debugging
#DEBUG = y
#LDDINC=/usr/src/linux-headers-2.6.32-26-server/include
# Add your debugging flag (or not) to CFLAGS
ifeq ($(DEBUG),y)
DEBFLAGS = -O -g -DSKYPOPEN_DEBUG # "-O" is needed to expand inlines
else
DEBFLAGS = -O2 -Wall
endif
EXTRA_CFLAGS += $(DEBFLAGS)
EXTRA_CFLAGS += -I$(LDDINC)
ifneq ($(KERNELRELEASE),)
# call from kernel build system
skypopen-objs := main.o
obj-m := skypopen.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) LDDINC=$(PWD)/../include modules
endif
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
depend .depend dep:
$(CC) $(EXTRA_CFLAGS) -M *.c > .depend
ifeq (.depend,$(wildcard .depend))
include .depend
endif
+494
View File
@@ -0,0 +1,494 @@
/*
* main.c -- the bare skypopen char module
*
* Copyright (C) 2010 Giovanni Maruzzelli
* Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
* Copyright (C) 2001 O'Reilly & Associates
*
* The source code in this file can be freely used, adapted,
* and redistributed in source or binary form, so long as an
* acknowledgment appears in derived source files. The citation
* should list that the code comes from the book "Linux Device
* Drivers" by Alessandro Rubini and Jonathan Corbet, published
* by O'Reilly & Associates. No warranty is attached;
* we cannot take responsibility for errors or fitness for use.
*
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/seq_file.h>
#include <linux/cdev.h>
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* copy_*_user */
#include <linux/soundcard.h>
#include <linux/delay.h>
#include <linux/hrtimer.h>
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/jiffies.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#include "skypopen.h" /* local definitions */
/*
* Our parameters which can be set at load time.
*/
int skypopen_major = SKYPOPEN_MAJOR;
int skypopen_minor = 3;
int skypopen_nr_devs = SKYPOPEN_NR_DEVS; /* number of bare skypopen devices */
module_param(skypopen_major, int, S_IRUGO);
module_param(skypopen_minor, int, S_IRUGO);
module_param(skypopen_nr_devs, int, S_IRUGO);
MODULE_AUTHOR("Original: Alessandro Rubini, Jonathan Corbet. Modified by: Giovanni Maruzzelli for FreeSWITCH skypopen");
MODULE_LICENSE("Dual BSD/GPL");
static struct skypopen_dev *skypopen_devices; /* allocated in skypopen_init_module */
static int unload = 0;
#ifdef CENTOS
#define HRTIMER_MODE_REL HRTIMER_REL
#endif// CENTOS
#ifndef WANT_HRTIMER
void my_timer_callback_inq( unsigned long data )
{
struct skypopen_dev *dev = (void *)data;
wake_up_interruptible(&dev->inq);
mod_timer( &dev->timer_inq, jiffies + msecs_to_jiffies(SKYPOPEN_SLEEP) );
}
void my_timer_callback_outq( unsigned long data )
{
struct skypopen_dev *dev = (void *)data;
wake_up_interruptible(&dev->outq);
mod_timer( &dev->timer_outq, jiffies + msecs_to_jiffies(SKYPOPEN_SLEEP) );
}
#else// WANT_HRTIMER
#ifndef CENTOS
static enum hrtimer_restart my_hrtimer_callback_inq( struct hrtimer *timer_inq )
{
struct skypopen_dev *dev = container_of(timer_inq, struct skypopen_dev, timer_inq);
ktime_t now;
if(unload)
return HRTIMER_NORESTART;
now = ktime_get();
hrtimer_forward(&dev->timer_inq, now, ktime_set(0, SKYPOPEN_SLEEP * 1000000));
wake_up_interruptible(&dev->inq);
return HRTIMER_RESTART;
}
static enum hrtimer_restart my_hrtimer_callback_outq( struct hrtimer *timer_outq )
{
struct skypopen_dev *dev = container_of(timer_outq, struct skypopen_dev, timer_outq);
ktime_t now;
if(unload)
return HRTIMER_NORESTART;
now = ktime_get();
hrtimer_forward(&dev->timer_outq, now, ktime_set(0, SKYPOPEN_SLEEP * 1000000));
wake_up_interruptible(&dev->outq);
return HRTIMER_RESTART;
}
#else// CENTOS
static int my_hrtimer_callback_inq( struct hrtimer *timer_inq )
{
struct skypopen_dev *dev = container_of(timer_inq, struct skypopen_dev, timer_inq);
if(unload)
return HRTIMER_NORESTART;
hrtimer_forward(&dev->timer_inq, timer_inq->expires, ktime_set(0, SKYPOPEN_SLEEP * 1000000));
wake_up_interruptible(&dev->inq);
return HRTIMER_RESTART;
}
static int my_hrtimer_callback_outq( struct hrtimer *timer_outq )
{
struct skypopen_dev *dev = container_of(timer_outq, struct skypopen_dev, timer_outq);
if(unload)
return HRTIMER_NORESTART;
hrtimer_forward(&dev->timer_outq, timer_outq->expires, ktime_set(0, SKYPOPEN_SLEEP * 1000000));
wake_up_interruptible(&dev->outq);
return HRTIMER_RESTART;
}
#endif// CENTOS
#endif// WANT_HRTIMER
/* The clone-specific data structure includes a key field */
struct skypopen_listitem {
struct skypopen_dev device;
dev_t key;
struct list_head list;
};
/* The list of devices, and a lock to protect it */
static LIST_HEAD(skypopen_c_list);
static spinlock_t skypopen_c_lock = SPIN_LOCK_UNLOCKED;
/* Look for a device or create one if missing */
static struct skypopen_dev *skypopen_c_lookfor_device(dev_t key)
{
struct skypopen_listitem *lptr;
#ifdef WANT_HRTIMER
#if 0
ktime_t ktime_inq;
ktime_t ktime_outq;
#endif //0
#endif// WANT_HRTIMER
list_for_each_entry(lptr, &skypopen_c_list, list) {
if (lptr->key == key)
return &(lptr->device);
}
/* not found */
lptr = kmalloc(sizeof(struct skypopen_listitem), GFP_KERNEL);
if (!lptr)
return NULL;
/* initialize the device */
memset(lptr, 0, sizeof(struct skypopen_listitem));
lptr->key = key;
init_waitqueue_head(&lptr->device.inq);
init_waitqueue_head(&lptr->device.outq);
#ifndef WANT_HRTIMER
setup_timer( &lptr->device.timer_inq, my_timer_callback_inq, (long int)lptr );
setup_timer( &lptr->device.timer_outq, my_timer_callback_outq, (long int)lptr );
printk( "Starting skypopen OSS driver read timer (%dms) skype client:(%d)\n", SKYPOPEN_SLEEP, current->tgid );
mod_timer( &lptr->device.timer_inq, jiffies + msecs_to_jiffies(SKYPOPEN_SLEEP) );
printk( "Starting skypopen OSS driver write timer (%dms) skype client:(%d)\n", SKYPOPEN_SLEEP, current->tgid );
mod_timer( &lptr->device.timer_outq, jiffies + msecs_to_jiffies(SKYPOPEN_SLEEP) );
#else// WANT_HRTIMER
#if 0
ktime_inq = ktime_set( 0, SKYPOPEN_SLEEP * 1000000);
hrtimer_init( &lptr->device.timer_inq, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
lptr->device.timer_inq.function = &my_hrtimer_callback_inq;
hrtimer_start( &lptr->device.timer_inq, ktime_inq, HRTIMER_MODE_REL );
ktime_outq = ktime_set( 0, SKYPOPEN_SLEEP * 1000000);
hrtimer_init( &lptr->device.timer_outq, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
lptr->device.timer_outq.function = &my_hrtimer_callback_outq;
hrtimer_start( &lptr->device.timer_outq, ktime_outq, HRTIMER_MODE_REL );
#endif
#endif// WANT_HRTIMER
/* place it in the list */
list_add(&lptr->list, &skypopen_c_list);
return &(lptr->device);
}
/*
* Open and close
*/
static int skypopen_c_open(struct inode *inode, struct file *filp)
{
struct skypopen_dev *dev;
dev_t key;
key = current->tgid;
/* look for a skypopenc device in the list */
spin_lock(&skypopen_c_lock);
dev = skypopen_c_lookfor_device(key);
spin_unlock(&skypopen_c_lock);
if (!dev)
return -ENOMEM;
/* then, everything else is copied from the bare skypopen device */
filp->private_data = dev;
return 0; /* success */
}
static int skypopen_c_release(struct inode *inode, struct file *filp)
{
/*
* Nothing to do, because the device is persistent.
* A `real' cloned device should be freed on last close
*/
return 0;
}
/*************************************************************/
static ssize_t skypopen_read(struct file *filp, char __user *buf, size_t count,
loff_t *f_pos)
{
DEFINE_WAIT(wait);
size_t written;
struct skypopen_dev *dev = filp->private_data;
if(unload)
return -1;
#ifdef WANT_HRTIMER
#if 1
if(dev->timer_inq_started == 0){
ktime_t ktime_inq;
ktime_inq = ktime_set( 0, SKYPOPEN_SLEEP * 1000000);
hrtimer_init( &dev->timer_inq, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
dev->timer_inq.function = &my_hrtimer_callback_inq;
hrtimer_start( &dev->timer_inq, ktime_inq, HRTIMER_MODE_REL );
dev->timer_inq_started = 1;
}
#endif
#endif// WANT_HRTIMER
//printk("READ\n");
prepare_to_wait(&dev->inq, &wait, TASK_INTERRUPTIBLE);
schedule();
finish_wait(&dev->inq, &wait);
if (!count)
return 0;
if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT;
written = 0;
while (count) {
unsigned long unwritten;
size_t chunk = count;
if (chunk > PAGE_SIZE)
chunk = PAGE_SIZE; /* Just for latency reasons */
unwritten = __clear_user(buf, chunk);
written += chunk - unwritten;
if (unwritten)
break;
if (signal_pending(current))
return written ? written : -ERESTARTSYS;
buf += chunk;
count -= chunk;
cond_resched();
}
return written ? written : -EFAULT;
}
static ssize_t skypopen_write(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos)
{
DEFINE_WAIT(wait);
struct skypopen_dev *dev = filp->private_data;
if(unload)
return -1;
#ifdef WANT_HRTIMER
#if 1
if(dev->timer_outq_started == 0){
ktime_t ktime_outq;
ktime_outq = ktime_set( 0, SKYPOPEN_SLEEP * 1000000);
hrtimer_init( &dev->timer_outq, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
dev->timer_outq.function = &my_hrtimer_callback_outq;
hrtimer_start( &dev->timer_outq, ktime_outq, HRTIMER_MODE_REL );
dev->timer_outq_started = 1;
}
#endif
#endif// WANT_HRTIMER
//printk("WRITE\n");
prepare_to_wait(&dev->outq, &wait, TASK_INTERRUPTIBLE);
schedule();
finish_wait(&dev->outq, &wait);
return count;
}
/*
* The ioctl() implementation
*/
static int skypopen_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
int __user *p = argp;
switch (cmd) {
case OSS_GETVERSION:
return put_user(SOUND_VERSION, p);
case SNDCTL_DSP_GETBLKSIZE:
return put_user(SKYPOPEN_BLK, p);
case SNDCTL_DSP_GETFMTS:
return put_user(28731, p);
default:
return 0;
}
}
struct file_operations skypopen_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = skypopen_read,
.write = skypopen_write,
.ioctl = skypopen_ioctl,
.open = skypopen_c_open,
.release = skypopen_c_release,
};
/*
* Finally, the module stuff
*/
/*
* The cleanup function is used to handle initialization failures as well.
* Thefore, it must be careful to work correctly even if some of the items
* have not been initialized
*/
void skypopen_cleanup_module(void)
{
int i;
int ret;
struct skypopen_listitem *lptr, *next;
dev_t devno = MKDEV(skypopen_major, skypopen_minor);
unload = 1;
msleep(100);
/* Get rid of our char dev entries */
if (skypopen_devices) {
for (i = 0; i < skypopen_nr_devs; i++) {
cdev_del(&skypopen_devices[i].cdev);
}
kfree(skypopen_devices);
}
/* And all the cloned devices */
list_for_each_entry_safe(lptr, next, &skypopen_c_list, list) {
#ifndef WANT_HRTIMER
ret= del_timer( &lptr->device.timer_inq );
printk( "Stopped skypopen OSS driver read timer\n");
ret= del_timer( &lptr->device.timer_outq );
printk( "Stopped skypopen OSS driver write timer\n");
#else// WANT_HRTIMER
if(lptr->device.timer_inq_started){
ret = hrtimer_cancel( &lptr->device.timer_inq );
printk( "Stopped skypopen OSS driver read HRtimer\n");
}
if(lptr->device.timer_outq_started){
ret = hrtimer_cancel( &lptr->device.timer_outq );
printk( "Stopped skypopen OSS driver write HRtimer\n");
}
#endif// WANT_HRTIMER
list_del(&lptr->list);
kfree(lptr);
}
/* cleanup_module is never called if registering failed */
unregister_chrdev_region(devno, skypopen_nr_devs);
printk("skypopen OSS driver unloaded\n");
}
/*
* Set up the char_dev structure for this device.
*/
static void skypopen_setup_cdev(struct skypopen_dev *dev, int index)
{
int err, devno = MKDEV(skypopen_major, skypopen_minor + index);
cdev_init(&dev->cdev, &skypopen_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &skypopen_fops;
err = cdev_add (&dev->cdev, devno, 1);
/* Fail gracefully if need be */
if (err)
printk(KERN_NOTICE "Error %d adding skypopen%d", err, index);
}
int skypopen_init_module(void)
{
int result, i;
dev_t dev = 0;
printk("skypopen OSS driver loading (www.freeswitch.org)\n");
/*
* Get a range of minor numbers to work with, asking for a dynamic
* major unless directed otherwise at load time.
*/
if (skypopen_major) {
dev = MKDEV(skypopen_major, skypopen_minor);
result = register_chrdev_region(dev, skypopen_nr_devs, "dsp");
} else {
result = alloc_chrdev_region(&dev, skypopen_minor, skypopen_nr_devs,
"dsp");
skypopen_major = MAJOR(dev);
}
if (result < 0) {
printk(KERN_WARNING "skypopen OSS driver: can't get major %d\n", skypopen_major);
return result;
}
/*
* allocate the devices -- we can't have them static, as the number
* can be specified at load time
*/
skypopen_devices = kmalloc(skypopen_nr_devs * sizeof(struct skypopen_dev), GFP_KERNEL);
if (!skypopen_devices) {
result = -ENOMEM;
goto fail; /* Make this more graceful */
}
memset(skypopen_devices, 0, skypopen_nr_devs * sizeof(struct skypopen_dev));
/* Initialize each device. */
for (i = 0; i < skypopen_nr_devs; i++) {
skypopen_setup_cdev(&skypopen_devices[i], i);
}
/* At this point call the init function for any friend device */
dev = MKDEV(skypopen_major, skypopen_minor + skypopen_nr_devs);
return 0; /* succeed */
fail:
skypopen_cleanup_module();
return result;
}
module_init(skypopen_init_module);
module_exit(skypopen_cleanup_module);
@@ -0,0 +1,71 @@
/*
* skypopen.h -- definitions for the char module
*
* Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
* Copyright (C) 2001 O'Reilly & Associates
*
* The source code in this file can be freely used, adapted,
* and redistributed in source or binary form, so long as an
* acknowledgment appears in derived source files. The citation
* should list that the code comes from the book "Linux Device
* Drivers" by Alessandro Rubini and Jonathan Corbet, published
* by O'Reilly & Associates. No warranty is attached;
* we cannot take responsibility for errors or fitness for use.
*
* $Id: skypopen.h,v 1.15 2004/11/04 17:51:18 rubini Exp $
*/
#ifndef _SKYPOPEN_H_
#define _SKYPOPEN_H_
#include <linux/ioctl.h> /* needed for the _IOW etc stuff used later */
#define SKYPOPEN_BLK 960
#define SKYPOPEN_SLEEP 10
#define CENTOS
#ifndef SKYPOPEN_MAJOR
#define SKYPOPEN_MAJOR 14 /* dynamic major by default */
#endif
#ifndef SKYPOPEN_NR_DEVS
#define SKYPOPEN_NR_DEVS 1 /* skypopen0 through skypopen3 */
#endif
#define WANT_HRTIMER
struct skypopen_dev {
struct cdev cdev; /* Char device structure */
wait_queue_head_t inq; /* read and write queues */
wait_queue_head_t outq; /* read and write queues */
#ifndef WANT_HRTIMER
struct timer_list timer_inq;
struct timer_list timer_outq;
#else// WANT_HRTIMER
struct hrtimer timer_inq;
struct hrtimer timer_outq;
#endif// WANT_HRTIMER
int timer_inq_started;
int timer_outq_started;
};
/*
* The different configurable parameters
*/
extern int skypopen_major; /* main.c */
extern int skypopen_nr_devs;
/*
* Prototypes for shared functions
*/
//ssize_t skypopen_read(struct file *filp, char __user *buf, size_t count,
//loff_t *f_pos);
//ssize_t skypopen_write(struct file *filp, const char __user *buf, size_t count,
//loff_t *f_pos);
//int skypopen_ioctl(struct inode *inode, struct file *filp,
//unsigned int cmd, unsigned long arg);
#endif /* _SKYPOPEN_H_ */
+154 -60
View File
@@ -508,7 +508,7 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
TAG_IF(!zstr(bye_headers), SIPTAG_HEADER_STR(bye_headers)), TAG_END());
}
} else {
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sending CANCEL to %s\n", switch_channel_get_name(channel));
if (!tech_pvt->got_bye) {
switch_channel_set_variable(channel, "sip_hangup_disposition", "send_cancel");
@@ -573,7 +573,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
char *sticky = NULL;
const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full");
if (sofia_test_flag(tech_pvt, TFLAG_ANS) || switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (sofia_test_flag(tech_pvt, TFLAG_ANS) || switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_SUCCESS;
}
@@ -653,7 +653,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
switch_channel_clear_flag(channel, CF_PROXY_MODE);
}
if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
tech_pvt->num_codecs = 0;
sofia_glue_tech_prepare_codecs(tech_pvt);
@@ -723,7 +723,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route)),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
NUTAG_SESSION_TIMER(session_timeout),
TAG_IF(session_timeout, NUTAG_SESSION_REFRESHER(nua_remote_refresher)),
NUTAG_SESSION_REFRESHER(session_timeout ? nua_local_refresher : nua_no_refresher),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info")),
SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
@@ -739,7 +739,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route)),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
NUTAG_SESSION_TIMER(session_timeout),
TAG_IF(session_timeout, NUTAG_SESSION_REFRESHER(nua_remote_refresher)),
NUTAG_SESSION_REFRESHER(session_timeout ? nua_local_refresher : nua_no_refresher),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info")),
SIPTAG_CONTENT_TYPE_STR("application/sdp"),
@@ -906,7 +906,7 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
tech_pvt->read_frame.flags = SFF_NONE;
status = switch_rtp_zerocopy_read_frame(tech_pvt->rtp_session, &tech_pvt->read_frame, flags);
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
if (status == SWITCH_STATUS_TIMEOUT) {
@@ -1084,7 +1084,7 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
tech_pvt->last_ts = 0;
/* inform them of the codec they are actually sending */
#if 0
if (++tech_pvt->codec_reinvites > 2) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"Ok, some devices *cough* X-lite *cough*\n"
@@ -1093,7 +1093,10 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
} else {
sofia_glue_do_invite(session);
}
#endif
*frame = &silence_frame;
return SWITCH_STATUS_SUCCESS;
}
}
@@ -1316,6 +1319,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
/* ones that do not need to lock sofia mutex */
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH:
case SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC:
{
sofia_glue_tech_track(tech_pvt->profile, session);
@@ -1332,6 +1336,61 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
}
}
break;
case SWITCH_MESSAGE_INDICATE_JITTER_BUFFER:
{
if (switch_rtp_ready(tech_pvt->rtp_session)) {
int len, maxlen = 0, qlen = 0, maxqlen = 50;
if (msg->string_arg) {
char *p;
const char *s;
if (!strncasecmp(msg->string_arg, "debug:", 6)) {
s = msg->string_arg + 6;
if (s && !strcmp(s, "off")) {
s = NULL;
}
switch_rtp_debug_jitter_buffer(tech_pvt->rtp_session, s);
goto end;
}
if ((len = atoi(msg->string_arg))) {
qlen = len / (tech_pvt->read_impl.microseconds_per_packet / 1000);
}
if (qlen) {
if ((p = strchr(msg->string_arg, ':'))) {
p++;
maxlen = atol(p);
}
}
if (maxlen) {
maxqlen = maxlen / (tech_pvt->read_impl.microseconds_per_packet / 1000);
}
}
if (qlen) {
if (switch_rtp_activate_jitter_buffer(tech_pvt->rtp_session, qlen, maxqlen,
tech_pvt->read_impl.samples_per_packet,
tech_pvt->read_impl.samples_per_second) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames) (%d max frames)\n", len, qlen, maxqlen);
switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", len, qlen);
}
} else {
switch_rtp_deactivate_jitter_buffer(tech_pvt->rtp_session);
}
}
}
break;
case SWITCH_MESSAGE_INDICATE_DEBUG_AUDIO:
{
if (switch_rtp_ready(tech_pvt->rtp_session) && !zstr(msg->string_array_arg[0]) && !zstr(msg->string_array_arg[1])) {
@@ -1629,7 +1688,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
sofia_glue_tech_set_local_sdp(tech_pvt, NULL, SWITCH_FALSE);
if (!(switch_channel_test_flag(channel, CF_ANSWERED) || switch_channel_test_flag(channel, CF_EARLY_MEDIA))) {
if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
tech_pvt->num_codecs = 0;
@@ -2144,7 +2203,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
} else {
if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) || !tech_pvt->iananame) {
sofia_clear_flag_locked(tech_pvt, TFLAG_LATE_NEGOTIATION);
if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
tech_pvt->num_codecs = 0;
@@ -3338,6 +3397,36 @@ SWITCH_STANDARD_API(sofia_count_reg_function)
return SWITCH_STATUS_SUCCESS;
}
static void select_from_profile(sofia_profile_t *profile,
const char *user,
const char *domain,
const char *concat,
const char *exclude_contact,
switch_stream_handle_t *stream)
{
struct cb_helper cb;
char *sql;
cb.row_process = 0;
cb.profile = profile;
cb.stream = stream;
if (exclude_contact) {
sql = switch_mprintf("select contact, profile_name, '%q' "
"from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%') "
"and contact not like '%%%s%%'", (concat != NULL) ? concat : "", user, domain, domain, exclude_contact);
} else {
sql = switch_mprintf("select contact, profile_name, '%q' "
"from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
(concat != NULL) ? concat : "", user, domain, domain);
}
switch_assert(sql);
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, contact_callback, &cb);
switch_safe_free(sql);
}
SWITCH_STANDARD_API(sofia_contact_function)
{
char *data;
@@ -3350,6 +3439,7 @@ SWITCH_STANDARD_API(sofia_contact_function)
const char *exclude_contact = NULL;
const char *user_replacement = NULL;
char *reply = "error/facility_not_subscribed";
switch_stream_handle_t mystream = { 0 };
if (!cmd) {
stream->write_function(stream, "%s", "");
@@ -3385,57 +3475,52 @@ SWITCH_STANDARD_API(sofia_contact_function)
}
}
if (!profile_name && domain) {
profile_name = domain;
if (zstr(domain)) {
domain = switch_core_get_variable("domain");
}
if (user && profile_name) {
char *sql;
if (!user) goto end;
if (!(profile = sofia_glue_find_profile(profile_name))) {
profile_name = domain;
domain = NULL;
}
if (!profile && profile_name) {
if (zstr(profile_name) || strcmp(profile_name, "*") || zstr(domain)) {
if (!zstr(profile_name)) {
profile = sofia_glue_find_profile(profile_name);
}
if (!profile) {
profile = sofia_glue_find_profile(domain);
}
}
if (profile) {
struct cb_helper cb;
switch_stream_handle_t mystream = { 0 };
if (profile || !zstr(domain)) {
SWITCH_STANDARD_STREAM(mystream);
switch_assert(mystream.data);
}
cb.row_process = 0;
if (profile) {
if (zstr(domain)) {
domain = profile->name;
}
if (!domain || (!strchr(domain, '.') && strcmp(profile_name, domain))) {
domain = profile->name;
}
SWITCH_STANDARD_STREAM(mystream);
switch_assert(mystream.data);
cb.profile = profile;
cb.stream = &mystream;
if (exclude_contact) {
sql = switch_mprintf("select contact, profile_name, '%q' "
"from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%') "
"and contact not like '%%%s%%'", (concat != NULL) ? concat : "", user, domain, domain, exclude_contact);
} else {
sql = switch_mprintf("select contact, profile_name, '%q' "
"from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
(concat != NULL) ? concat : "", user, domain, domain);
}
switch_assert(sql);
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, contact_callback, &cb);
switch_safe_free(sql);
reply = (char *) mystream.data;
if (!zstr(reply) && end_of(reply) == ',') {
end_of(reply) = '\0';
}
if (zstr(reply)) {
reply = "error/user_not_registered";
if (!zstr(profile->domain_name) && !zstr(profile_name) && !strcmp(profile_name, profile->name)) {
domain = profile->domain_name;
}
select_from_profile(profile, user, domain, concat, exclude_contact, &mystream);
sofia_glue_release_profile(profile);
} else if (!zstr(domain)) {
switch_mutex_lock(mod_sofia_globals.hash_mutex);
if (mod_sofia_globals.profile_hash) {
switch_hash_index_t *hi;
const void *var;
void *val;
for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
if ((profile = (sofia_profile_t *) val) && !strcmp((char *)var, profile->name)) {
select_from_profile(profile, user, domain, concat, exclude_contact, &mystream);
profile = NULL;
}
}
if (user_replacement) {
@@ -3530,18 +3615,27 @@ copydone:
switch_safe_free(mystream.data);
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
}
reply = (char *) mystream.data;
end:
if (zstr(reply)) {
reply = "error/user_not_registered";
} else if (end_of(reply) == ',') {
end_of(reply) = '\0';
}
if (reply) {
stream->write_function(stream, "%s", reply);
}
stream->write_function(stream, "%s", reply);
reply = NULL;
switch_safe_free(mystream.data);
switch_safe_free(data);
if (profile) {
sofia_glue_release_profile(profile);
}
return SWITCH_STATUS_SUCCESS;
}
@@ -3942,7 +4036,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
goto error;
}
if (profile->domain_name && profile->domain_name != profile->name) {
if (profile->domain_name && strcmp(profile->domain_name, profile->name)) {
profile_name = profile->domain_name;
}
+11
View File
@@ -225,6 +225,7 @@ typedef enum {
PFLAG_DEL_SUBS_ON_REG,
PFLAG_IGNORE_183NOSDP,
PFLAG_PRESENCE_PROBE_ON_REGISTER,
PFLAG_NO_CONNECTION_REUSE,
/* No new flags below this line */
PFLAG_MAX
} PFLAGS;
@@ -744,6 +745,14 @@ typedef struct {
char *route_uri;
} sofia_destination_t;
typedef struct {
char network_ip[80];
int network_port;
const char *is_nat;
int is_auto_nat;
} sofia_nat_parse_t;
#define sofia_test_pflag(obj, flag) ((obj)->pflags[flag] ? 1 : 0)
#define sofia_set_pflag(obj, flag) (obj)->pflags[flag] = 1
#define sofia_set_pflag_locked(obj, flag) assert(obj->flag_mutex != NULL);\
@@ -1026,6 +1035,7 @@ void sofia_profile_destroy(sofia_profile_t *profile);
switch_status_t sip_dig_function(_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session, _In_ switch_stream_handle_t *stream);
const char *sofia_gateway_status_name(sofia_gateway_status_t status);
void sofia_reg_fire_custom_gateway_state_event(sofia_gateway_t *gateway, int status, const char *phrase);
uint32_t sofia_reg_reg_count(sofia_profile_t *profile, const char *user, const char *host);
void sofia_glue_copy_t38_options(switch_t38_options_t *t38_options, switch_core_session_t *session);
switch_t38_options_t *sofia_glue_extract_t38_options(switch_core_session_t *session, const char *r_sdp);
char *sofia_glue_get_multipart(switch_core_session_t *session, const char *prefix, const char *sdp, char **mp_type);
@@ -1039,3 +1049,4 @@ switch_status_t sofia_glue_sdp_map(const char *r_sdp, switch_event_t **fmtp, swi
void sofia_glue_build_vid_refresh_message(switch_core_session_t *session, const char *pl);
void sofia_glue_check_dtmf_type(private_object_t *tech_pvt);
void sofia_glue_parse_rtp_bugs(uint32_t *flag_pole, const char *str);
char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_nat_parse_t *np);
+53 -19
View File
@@ -357,7 +357,7 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status,
goto error;
}
if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
switch_channel_answer(channel);
switch_channel_set_variable(channel, "auto_answer_destination", switch_channel_get_variable(channel, "destination_number"));
switch_ivr_session_transfer(session, "auto_answer", NULL, NULL);
@@ -1486,6 +1486,8 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
TAG_IF(profile->timer_t2, NTATAG_SIP_T2(profile->timer_t2)),
TAG_IF(profile->timer_t4, NTATAG_SIP_T4(profile->timer_t4)),
SIPTAG_ACCEPT_STR("application/sdp, multipart/mixed"),
TAG_IF(sofia_test_pflag(profile, PFLAG_NO_CONNECTION_REUSE),
TPTAG_REUSE(0)),
TAG_END()); /* Last tag should always finish the sequence */
if (!profile->nua) {
@@ -1715,16 +1717,9 @@ void launch_sofia_profile_thread(sofia_profile_t *profile)
static void logger(void *logarg, char const *fmt, va_list ap)
{
/* gcc 4.4 gets mad at us for testing if (ap) so let's try to work around it....*/
void *ap_ptr = (void *) (intptr_t) ap;
if (!fmt) return;
if (ap_ptr) {
switch_log_vprintf(SWITCH_CHANNEL_LOG_CLEAN, mod_sofia_globals.tracelevel, fmt, ap);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, mod_sofia_globals.tracelevel, "%s", fmt);
}
switch_log_vprintf(SWITCH_CHANNEL_LOG_CLEAN, mod_sofia_globals.tracelevel, fmt, ap);
}
static su_log_t *sofia_get_logger(const char *name)
@@ -3673,6 +3668,13 @@ switch_status_t config_sofia(int reload, char *profile_name)
} else {
profile->timer_t4 = 4000;
}
} else if (!strcasecmp(var, "reuse-connections")) {
switch_bool_t value = switch_true(val);
if (!value) {
sofia_set_pflag(profile, PFLAG_NO_CONNECTION_REUSE);
} else {
sofia_clear_pflag(profile, PFLAG_NO_CONNECTION_REUSE);
}
}
}
@@ -4112,7 +4114,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
}
if (channel && sip && (status == 300 || status == 301 || status == 302 || status == 305) && switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (channel && sip && (status == 300 || status == 301 || status == 302 || status == 305) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
sip_contact_t *p_contact = sip->sip_contact;
int i = 0;
char var_name[80];
@@ -4643,7 +4645,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
status = 183;
}
if (channel && (status == 180 || status == 183) && switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (channel && (status == 180 || status == 183) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
const char *val;
if ((val = switch_channel_get_variable(channel, "sip_auto_answer")) && switch_true(val)) {
nua_notify(nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active), SIPTAG_EVENT_STR("talk"), TAG_END());
@@ -4690,7 +4692,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
if (r_sdp) {
if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) && !switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) && switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "PROXY MEDIA");
}
sofia_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
@@ -4713,7 +4715,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
}
goto done;
} else {
if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) && !switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) && switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "DELAYED NEGOTIATION");
} else {
if (sofia_glue_tech_media(tech_pvt, (char *) r_sdp) != SWITCH_STATUS_SUCCESS) {
@@ -4908,7 +4910,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
sofia_glue_tech_set_local_sdp(tech_pvt, NULL, SWITCH_FALSE);
if (!switch_channel_media_ready(channel)) {
if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
//const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
tech_pvt->num_codecs = 0;
@@ -6253,7 +6255,8 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
if (!is_nat && profile->nat_acl_count) {
uint32_t x = 0;
int ok = 1;
int contact_private_ip = 1;
int network_private_ip = 0;
char *last_acl = NULL;
const char *contact_host = NULL;
@@ -6262,14 +6265,37 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
}
if (!zstr(contact_host)) {
/* NAT mode double check logic and examples.
Example 1: the contact_host is 192.168.1.100 and the network_ip is also 192.168.1.100 the end point
is most likely behind nat with us so we need to veto that decision to turn on nat processing.
Example 2: the contact_host is 192.168.1.100 and the network_ip is 192.0.2.100 which is a public internet ip
the remote endpoint is likely behind a remote nat traversing the public internet.
This secondary check is here to double check the conclusion of nat settigs to ensure we don't set net
in cases where we don't really need to be doing this.
Why would you want to do this? Well if your FreeSWITCH is behind nat and you want to talk to endpoints behind
remote NAT over the public internet in addition to endpoints behind nat with you. This simplifies that process.
*/
for (x = 0; x < profile->nat_acl_count; x++) {
last_acl = profile->nat_acl[x];
if (!(ok = switch_check_network_list_ip(contact_host, last_acl))) {
if ((contact_private_ip = switch_check_network_list_ip(contact_host, last_acl))) {
break;
}
}
if (contact_private_ip) {
for (x = 0; x < profile->nat_acl_count; x++) {
if ((network_private_ip = switch_check_network_list_ip(network_ip, profile->nat_acl[x]))) {
break;
}
}
}
if (ok) {
if (contact_private_ip && !network_private_ip) {
is_nat = last_acl;
}
}
@@ -6818,11 +6844,19 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
if (sip->sip_request->rq_url->url_params) {
gw_name = sofia_glue_find_parameter(sip->sip_request->rq_url->url_params, "gw=");
gw_name = sofia_glue_find_parameter_value(session, sip->sip_request->rq_url->url_params, "gw=");
}
if (strstr(destination_number, "gw+")) {
gw_name = destination_number + 3;
if (sofia_test_pflag(profile, PFLAG_FULL_ID)) {
char *tmp;
gw_name = switch_core_session_strdup(session, destination_number + 3);
if ((tmp = strchr(gw_name, '@'))) {
*tmp = '\0';
}
} else {
gw_name = destination_number + 3;
}
}
if (gw_name) {
+165 -11
View File
@@ -2342,7 +2342,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
nua_invite(tech_pvt->nh,
NUTAG_AUTOANSWER(0),
NUTAG_SESSION_TIMER(session_timeout),
TAG_IF(session_timeout, NUTAG_SESSION_REFRESHER(nua_remote_refresher)),
NUTAG_SESSION_REFRESHER(session_timeout ? nua_local_refresher : nua_no_refresher),
TAG_IF(sofia_test_flag(tech_pvt, TFLAG_RECOVERED), NUTAG_INVITE_TIMER(UINT_MAX)),
TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)),
TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
@@ -2669,7 +2669,8 @@ switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force)
tech_pvt->rm_encoding,
tech_pvt->codec_ms,
tech_pvt->rm_rate);
switch_yield(tech_pvt->read_impl.microseconds_per_packet);
switch_core_session_lock_codec_write(tech_pvt->session);
switch_core_session_lock_codec_read(tech_pvt->session);
resetting = 1;
@@ -3153,18 +3154,37 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
if ((val = switch_channel_get_variable(tech_pvt->channel, "jitterbuffer_msec"))) {
int len = atoi(val);
int maxlen = 0;
char *p;
if (len < 100 || len > 1000) {
if ((p = strchr(val, ':'))) {
p++;
maxlen = atoi(p);
}
if (len < 20 || len > 10000) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR,
"Invalid Jitterbuffer spec [%d] must be between 100 and 1000\n", len);
"Invalid Jitterbuffer spec [%d] must be between 20 and 10000\n", len);
} else {
int qlen;
int qlen, maxqlen = 50;
qlen = len / (tech_pvt->read_impl.microseconds_per_packet / 1000);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames)\n", len,
qlen);
switch_rtp_activate_jitter_buffer(tech_pvt->rtp_session, qlen);
if (maxlen) {
maxqlen = maxlen / (tech_pvt->read_impl.microseconds_per_packet / 1000);
}
if (switch_rtp_activate_jitter_buffer(tech_pvt->rtp_session, qlen, maxqlen,
tech_pvt->read_impl.samples_per_packet,
tech_pvt->read_impl.samples_per_second) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames)\n", len, qlen);
switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", len, qlen);
}
}
}
@@ -4668,8 +4688,8 @@ void sofia_glue_pass_sdp(private_object_t *tech_pvt, char *sdp)
switch_channel_set_variable(other_channel, SWITCH_B_SDP_VARIABLE, sdp);
if (!sofia_test_flag(tech_pvt, TFLAG_CHANGE_MEDIA) && !sofia_test_flag(tech_pvt, TFLAG_RECOVERING) &&
(switch_channel_test_flag(other_channel, CF_OUTBOUND) &&
switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND) && switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE))) {
(switch_channel_direction(other_channel) == SWITCH_CALL_DIRECTION_OUTBOUND &&
switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE))) {
switch_ivr_nomedia(val, SMF_FORCE);
sofia_set_flag_locked(tech_pvt, TFLAG_CHANGE_MEDIA);
}
@@ -5041,9 +5061,20 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName
const char *port = switch_channel_get_variable(channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
const char *r_ip = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE);
const char *r_port = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE);
const char *use_uuid;
sofia_set_flag(tech_pvt, TFLAG_RECOVERING);
if ((use_uuid = switch_channel_get_variable(channel, "origination_uuid"))) {
if (switch_core_session_set_uuid(session, use_uuid) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s set UUID=%s\n", switch_channel_get_name(channel),
use_uuid);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "%s set UUID=%s FAILED\n",
switch_channel_get_name(channel), use_uuid);
}
}
if (!switch_channel_test_flag(channel, CF_PROXY_MODE) && ip && port) {
const char *tmp;
tech_pvt->iananame = tech_pvt->rm_encoding = (char *) switch_channel_get_variable(channel, "sip_use_codec_name");
@@ -6105,6 +6136,129 @@ void sofia_glue_parse_rtp_bugs(uint32_t *flag_pole, const char *str)
}
}
char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_nat_parse_t *np)
{
char *contact_str = NULL;
const char *contact_host, *contact_user;
sip_contact_t const *contact;
char *port;
const char *display = "\"user\"";
char new_port[25] = "";
sofia_nat_parse_t lnp = { { 0 } };
const char *ipv6;
sip_from_t const *from;
if (!sip || !sip->sip_contact || !sip->sip_contact->m_url) {
return NULL;
}
from = sip->sip_from;
contact = sip->sip_contact;
if (!np) {
np = &lnp;
}
sofia_glue_get_addr(nua_current_request(profile->nua), np->network_ip, sizeof(np->network_ip), &np->network_port);
if (sofia_glue_check_nat(profile, np->network_ip)) {
np->is_auto_nat = 1;
}
port = (char *) contact->m_url->url_port;
contact_host = sip->sip_contact->m_url->url_host;
contact_user = sip->sip_contact->m_url->url_user;
display = contact->m_display;
if (zstr(display)) {
if (from) {
display = from->a_display;
if (zstr(display)) {
display = "\"user\"";
}
}
} else {
display = "\"user\"";
}
if (sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION)) {
if (sip->sip_via) {
const char *v_port = sip->sip_via->v_port;
const char *v_host = sip->sip_via->v_host;
if (v_host && sip->sip_via->v_received) {
np->is_nat = "via received";
} else if (v_host && strcmp(np->network_ip, v_host)) {
np->is_nat = "via host";
} else if (v_port && atoi(v_port) != np->network_port) {
np->is_nat = "via port";
}
}
}
if (!np->is_nat && sip && sip->sip_via && sip->sip_via->v_port &&
atoi(sip->sip_via->v_port) == 5060 && np->network_port != 5060 ) {
np->is_nat = "via port";
}
if (!np->is_nat && profile->nat_acl_count) {
uint32_t x = 0;
int ok = 1;
char *last_acl = NULL;
if (!zstr(contact_host)) {
for (x = 0; x < profile->nat_acl_count; x++) {
last_acl = profile->nat_acl[x];
if (!(ok = switch_check_network_list_ip(contact_host, last_acl))) {
break;
}
}
if (ok) {
np->is_nat = last_acl;
}
}
}
if (np->is_nat && profile->local_network && switch_check_network_list_ip(np->network_ip, profile->local_network)) {
if (profile->debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IP %s is on local network, not seting NAT mode.\n", np->network_ip);
}
np->is_nat = NULL;
}
if (zstr(contact_host)) {
np->is_nat = "No contact host";
}
if (np->is_nat) {
contact_host = np->network_ip;
switch_snprintf(new_port, sizeof(new_port), ":%d", np->network_port);
port = NULL;
}
if (port) {
switch_snprintf(new_port, sizeof(new_port), ":%s", port);
}
ipv6 = strchr(contact_host, ':');
if (contact->m_url->url_params) {
contact_str = switch_mprintf("%s <sip:%s@%s%s%s%s;%s>%s",
display, contact->m_url->url_user,
ipv6 ? "[" : "",
contact_host, ipv6 ? "]" : "", new_port, contact->m_url->url_params, np->is_nat ? ";fs_nat=yes" : "");
} else {
contact_str = switch_mprintf("%s <sip:%s@%s%s%s%s>%s",
display,
contact->m_url->url_user, ipv6 ? "[" : "", contact_host, ipv6 ? "]" : "", new_port, np->is_nat ? ";fs_nat=yes" : "");
}
return contact_str;
}
File diff suppressed because it is too large. Load diff
+58 -27
View File
@@ -817,6 +817,19 @@ void sofia_reg_auth_challenge(nua_t *nua, sofia_profile_t *profile, nua_handle_t
switch_safe_free(auth_str);
}
uint32_t sofia_reg_reg_count(sofia_profile_t *profile, const char *user, const char *host)
{
char buf[32] = "";
char *sql;
sql = switch_mprintf("select count(*) from sip_registrations where profile_name='%q' and "
"sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')", profile->name, user, host, host);
sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, buf, sizeof(buf));
switch_safe_free(sql);
return atoi(buf);
}
uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip, sofia_regtype_t regtype, char *key,
uint32_t keylen, switch_event_t **v_event, const char *is_nat)
{
@@ -1065,6 +1078,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
if (exptime && v_event && *v_event) {
char *exp_var;
char *allow_multireg = NULL;
int force_connectile = 0;
allow_multireg = switch_event_get_header(*v_event, "sip-allow-multiple-registrations");
if (allow_multireg && switch_false(allow_multireg)) {
@@ -1081,8 +1095,13 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
to_user = force_user;
}
if ((v_contact_str = switch_event_get_header(*v_event, "sip-force-contact"))) {
if (!strcasecmp(v_contact_str, "NDLB-connectile-dysfunction-2.0")) {
if (profile->rport_level == 3 && sip->sip_user_agent &&
sip->sip_user_agent->g_string && !strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7)) {
force_connectile = 1;
}
if ((v_contact_str = switch_event_get_header(*v_event, "sip-force-contact")) || force_connectile) {
if ((!strcasecmp(v_contact_str, "NDLB-connectile-dysfunction-2.0")) || force_connectile) {
char *path_encoded;
size_t path_encoded_len;
char my_contact_str[1024];
@@ -1139,30 +1158,24 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
}
if (auth_res != AUTH_OK && !stale) {
if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) {
if (regtype == REG_REGISTER) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SIP auth %s (REGISTER) on sofia profile '%s' "
"for [%s@%s] from ip %s\n", forbidden ? "failure" : "challenge", profile->name, to_user, to_host, network_ip);
}
if (auth_res == AUTH_FORBIDDEN) {
nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS(nua), TAG_END());
forbidden = 1;
} else {
nua_respond(nh, SIP_401_UNAUTHORIZED, NUTAG_WITH_THIS(nua), TAG_END());
}
if (profile->debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send %s for [%s@%s]\n",
forbidden ? "forbidden" : "challenge", to_user, to_host);
}
if (auth_res == AUTH_FORBIDDEN) {
nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS(nua), TAG_END());
/* Log line added to support Fail2Ban */
if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) {
if (regtype == REG_INVITE) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth failure (INVITE) on sofia profile '%s' "
"for [%s@%s] from ip %s\n", profile->name, to_user, to_host, network_ip);
}
}
} else {
nua_respond(nh, SIP_401_UNAUTHORIZED, NUTAG_WITH_THIS(nua), TAG_END());
/* Log line added to support Fail2Ban */
if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth %s (%s) on sofia profile '%s' "
"for [%s@%s] from ip %s\n", forbidden ? "failure" : "challenge",
(regtype == REG_INVITE) ? "INVITE" : "REGISTER", profile->name, to_user, to_host, network_ip);
}
switch_goto_int(r, 1, end);
}
}
@@ -1193,14 +1206,18 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
realm = from_host;
}
if (regtype == REG_REGISTER) {
sofia_reg_auth_challenge(nua, profile, nh, regtype, realm, stale);
if (profile->debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Requesting Registration from: [%s@%s]\n", to_user, to_host);
}
} else {
sofia_reg_auth_challenge(nua, profile, nh, regtype, realm, stale);
sofia_reg_auth_challenge(nua, profile, nh, regtype, realm, stale);
if (profile->debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send challenge for [%s@%s]\n", to_user, to_host);
}
/* Log line added to support Fail2Ban */
if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth challenge (%s) on sofia profile '%s' "
"for [%s@%s] from ip %s\n", (regtype == REG_INVITE) ? "INVITE" : "REGISTER",
profile->name, to_user, to_host, network_ip);
}
switch_goto_int(r, 1, end);
}
reg:
@@ -1294,6 +1311,12 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
if (sofia_reg_reg_count(profile, to_user, reg_host) == 1) {
sql = switch_mprintf("delete from sip_presence where sip_user='%q' and sip_host='%q' and profile_name='%q' and open_closed='closed'",
to_user, reg_host, profile->name);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DELETE PRESENCE SQL: %s\n", sql);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
switch_mutex_unlock(profile->ireg_mutex);
@@ -1357,8 +1380,16 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
} else {
int send = 1;
if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
if (multi_reg) {
if (sofia_reg_reg_count(profile, to_user, sub_host) > 0) {
send = 0;
}
}
if (send && switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
@@ -346,8 +346,8 @@ static switch_status_t load_config(switch_memory_pool_t *pool)
} else if (!strcasecmp(var, "default-template")) {
globals.default_template = switch_core_strdup(pool, val);
} else if (!strcasecmp(var, "master-file-only")) {
globals.masterfileonly = switch_true(val);
}
globals.masterfileonly = switch_true(val);
}
}
}
@@ -405,8 +405,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_csv_load)
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
return status;
}
@@ -8,6 +8,7 @@ else
LOCAL_LDFLAGS=-L/usr/postgres/8.3/lib -R/usr/postgres/8.3/lib -lpq -static
endif
else
LOCAL_CFLAGS=-I/usr/include/postgresql
LOCAL_LDFLAGS=-lpq -static
endif
include ../../../../build/modmake.rules
@@ -1,5 +1,6 @@
-- Sample CDR table schema
create table a (
create table cdr (
id serial primary key,
local_ip_v4 inet not null,
caller_id_name varchar,
@@ -20,26 +21,3 @@ create table a (
sip_hangup_disposition varchar,
ani varchar
);
create table g (
id serial primary key,
local_ip_v4 inet not null,
caller_id_name varchar,
caller_id_number varchar,
destination_number varchar not null,
context varchar not null,
start_stamp timestamp with time zone not null,
answer_stamp timestamp with time zone,
end_stamp timestamp with time zone not null,
duration int not null,
billsec int not null,
hangup_cause varchar not null,
uuid uuid not null,
bleg_uuid uuid,
accountcode varchar,
read_codec varchar,
write_codec varchar,
sip_hangup_disposition varchar,
ani varchar
);
@@ -52,8 +52,8 @@ typedef struct cdr_fd cdr_fd_t;
const char *default_template =
"\"${local_ip_v4}\",\"${caller_id_name}\",\"${caller_id_number}\",\"${destination_number}\",\"${context}\",\"${start_stamp}\","
"\"${answer_stamp}\",\"${end_stamp}\",\"${duration}\",\"${billsec}\",\"${hangup_cause}\",\"${uuid}\",\"${bleg_uuid}\", \"${accountcode}\","
"\"${read_codec}\", \"${write_codec}\"\n";
"\"${answer_stamp}\",\"${end_stamp}\",\"${duration}\",\"${billsec}\",\"${hangup_cause}\",\"${uuid}\",\"${bleg_uuid}\",\"${accountcode}\","
"\"${read_codec}\",\"${write_codec}\"";
static struct {
switch_memory_pool_t *pool;
@@ -65,9 +65,9 @@ static struct {
int rotate;
int debug;
cdr_leg_t legs;
char *a_table;
char *g_table;
char *db_info;
char *db_table;
char *spool_format;
PGconn *db_connection;
int db_online;
switch_mutex_t *db_mutex;
@@ -115,13 +115,13 @@ static void do_rotate(cdr_fd_t *fd)
if (globals.rotate) {
switch_time_exp_lt(&tm, switch_micro_time_now());
switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d-%H-%M-%S", &tm);
switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d-%H-%M-%S", &tm);
len = strlen(fd->path) + strlen(date) + 2;
p = switch_mprintf("%s.%s", fd->path, date);
assert(p);
switch_file_rename(fd->path, p, globals.pool);
free(p);
switch_safe_free(p);
}
do_reopen(fd);
@@ -139,10 +139,12 @@ static void do_rotate(cdr_fd_t *fd)
}
static void write_cdr(const char *path, const char *log_line)
static void spool_cdr(const char *path, const char *log_line)
{
cdr_fd_t *fd = NULL;
char *log_line_lf = NULL;
unsigned int bytes_in, bytes_out;
int loops = 0;
if (!(fd = switch_core_hash_find(globals.fd_hash, path))) {
fd = switch_core_alloc(globals.pool, sizeof(*fd));
@@ -154,8 +156,15 @@ static void write_cdr(const char *path, const char *log_line)
switch_core_hash_insert(globals.fd_hash, path, fd);
}
if (end_of(log_line) != '\n') {
log_line_lf = switch_mprintf("%s\n", log_line);
} else {
switch_strdup(log_line_lf, log_line);
}
assert(log_line_lf);
switch_mutex_lock(fd->mutex);
bytes_out = (unsigned) strlen(log_line);
bytes_out = (unsigned) strlen(log_line_lf);
if (fd->fd < 0) {
do_reopen(fd);
@@ -169,167 +178,154 @@ static void write_cdr(const char *path, const char *log_line)
do_rotate(fd);
}
if ((bytes_in = write(fd->fd, log_line, bytes_out)) != bytes_out) {
while ((bytes_in = write(fd->fd, log_line_lf, bytes_out)) != bytes_out && ++loops < 10) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Write error to file %s %d/%d\n", path, (int) bytes_in, (int) bytes_out);
do_rotate(fd);
switch_yield(250000);
}
fd->bytes += bytes_in;
if (bytes_in > 0) {
fd->bytes += bytes_in;
}
end:
switch_mutex_unlock(fd->mutex);
switch_safe_free(log_line_lf);
}
static int save_cdr(const char* const table, const char* const template, const char* const cdr)
static switch_status_t insert_cdr(const char * const template, const char * const cdr)
{
char* columns;
char* values;
char* p;
unsigned clen;
unsigned vlen;
char* query;
const char* const query_template = "INSERT INTO %s (%s) VALUES (%s);";
PGresult* res;
char *columns, *values;
char *p, *q;
unsigned vlen;
char *nullValues, *temp, *tp;
int nullCounter = 0, charCounter = 0;
char *sql = NULL, *path = NULL;
PGresult *res;
if (!table || !*table || !template || !*template || !cdr || !*cdr) {
if (!template || !*template || !cdr || !*cdr) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Bad parameter\n");
return 0;
return SWITCH_STATUS_FALSE;
}
columns = strdup(template);
for (p = columns; *p; ++p) {
/* Build comma-separated list of field names by dropping $ { } ; chars */
switch_strdup(columns, template);
for (p = columns, q = columns; *p; ++p) {
switch (*p) {
case '$': case '"': case '{': case '}': case ';':
*p = ' ';
break;
case '$': case '"': case '{': case '}': case ';':
break;
default:
*q++ = *p;
}
}
clen = p - columns;
*q = '\0';
values = strdup(cdr);
/*
* In the expanded vars, replace double quotes (") with single quotes (')
* for correct PostgreSQL syntax, and replace semi-colon with space to
* prevent SQL injection attacks
*/
switch_strdup(values, cdr);
for (p = values; *p; ++p) {
switch(*p) {
case '"':
*p = '\'';
break;
case ';':
*p = ' ';
break;
case '"':
*p = '\'';
break;
case ';':
*p = ' ';
break;
}
}
vlen = p - values;
/*
Patch for changing spaces (; ;) in the template paterns to NULL (ex.) ; ; --PACH--> null
- added new functionality - space removing
*/
char *spaceColumns;
int spaceCounter=0;
for (p=columns; *p; ++p)
{
if (*p==' ')
{
spaceCounter++;
}
}
spaceColumns = (char*)malloc(clen-spaceCounter+1);
char *pt=spaceColumns;
for (p=columns; *p; ++p)
{
if (*p!=' ')
{
*pt=*p;
pt++;
}
}
*pt=0;
pt=columns;
columns=spaceColumns;
free(pt);
char *nullValues;
int nullCounter=0;
int charCounter=0;
for (p=values; *p; ++p)
{
if (*p==',')
{
if (charCounter==0)
{
/*
* Patch for changing empty strings ('') in the expanded variables to
* PostgreSQL null
*/
for (p = values; *p; ++p) {
if (*p == ',') {
if (charCounter == 0) {
nullCounter++;
}
charCounter=0;
}
else if (*p!=' ' && *p!='\'')
{
charCounter = 0;
} else if (*p != ' ' && *p != '\'') {
charCounter++;
}
}
if (charCounter==0)
{
if (charCounter == 0) {
nullCounter++;
}
charCounter=0;
nullCounter*=4;
vlen+=nullCounter;
nullValues=(char*)malloc(strlen(values)+nullCounter+1);
charCounter=0;
char *temp=nullValues;
char *tp=nullValues;
for (p=values; *p; ++tp,++p)
{
if (*p==',')
{
if (charCounter==0)
{
nullCounter *= 4;
vlen += nullCounter;
switch_zmalloc(nullValues, strlen(values) + nullCounter + 1);
charCounter = 0;
temp = nullValues;
tp = nullValues;
for (p = values; *p; ++tp, ++p) {
if (*p == ',') {
if (charCounter == 0) {
temp++;
*temp='n';temp++;
if (temp==tp) tp++;
*temp='u';temp++;
if (temp==tp) tp++;
*temp='l';temp++;
if (temp==tp) tp++;
*temp='l';temp++;
while (temp!=tp)
{
*temp=' ';temp++;
*temp = 'n';
temp++;
if (temp == tp) tp++;
*temp = 'u';
temp++;
if (temp == tp) tp++;
*temp = 'l';
temp++;
if (temp == tp) tp++;
*temp = 'l';
temp++;
while (temp != tp) {
*temp = ' ';
temp++;
}
}
charCounter=0;
temp=tp;
}
else if (*p!=' ' && *p!='\'')
{
charCounter = 0;
temp = tp;
} else if (*p != ' ' && *p != '\'') {
charCounter++;
}
*tp=*p;
*tp = *p;
}
if (charCounter==0)
{
if (charCounter == 0) {
temp++;
*temp='n';temp++;
if (temp==tp) tp++;
*temp='u';temp++;
if (temp==tp) tp++;
*temp='l';temp++;
if (temp==tp) tp++;
*temp='l';temp++;
while (temp!=tp)
{
*temp=' ';temp++;
*temp = 'n';
temp++;
if (temp == tp) tp++;
*temp = 'u';
temp++;
if (temp == tp) tp++;
*temp = 'l';
temp++;
if (temp == tp) tp++;
*temp = 'l';
temp++;
while (temp != tp) {
*temp = ' ';
temp++;
}
}
charCounter=0;
temp=tp;
*tp=0;
tp=values;
values=nullValues;
free(tp);
//-----------------------------END_OF_PATCH----------------------------------------------------------------
query = malloc(strlen(query_template) - 6 + strlen(table) + clen + vlen + 1);
sprintf(query, query_template, table, columns, values);
free(columns);
free(values);
charCounter = 0;
temp = tp;
*tp = 0;
tp = values;
values = nullValues;
switch_safe_free(tp);
sql = switch_mprintf("INSERT INTO %s (%s) VALUES (%s);", globals.db_table, columns, values);
assert(sql);
switch_safe_free(columns);
switch_safe_free(values);
if (globals.debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Query: \"%s\"\n", query);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Query: \"%s\"\n", sql);
}
switch_mutex_lock(globals.db_mutex);
@@ -337,66 +333,58 @@ static int save_cdr(const char* const table, const char* const template, const c
if (!globals.db_online || PQstatus(globals.db_connection) != CONNECTION_OK) {
globals.db_connection = PQconnectdb(globals.db_info);
}
if (PQstatus(globals.db_connection) == CONNECTION_OK) {
globals.db_online = 1;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Connection to database failed: %s", PQerrorMessage(globals.db_connection));
PQfinish(globals.db_connection);
globals.db_online = 0;
switch_mutex_unlock(globals.db_mutex);
free(query);
return 0;
goto error;
}
res = PQexec(globals.db_connection, "BEGIN");
res = PQexec(globals.db_connection, sql);
if (PQresultStatus(res) != PGRES_COMMAND_OK) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "BEGIN command failed: %s", PQerrorMessage(globals.db_connection));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "INSERT command failed: %s", PQresultErrorMessage(res));
PQclear(res);
PQfinish(globals.db_connection);
globals.db_online = 0;
switch_mutex_unlock(globals.db_mutex);
free(query);
return 0;
goto error;
}
PQclear(res);
res = PQexec(globals.db_connection, query);
if (PQresultStatus(res) != PGRES_COMMAND_OK) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "INSERT command failed: %s", PQerrorMessage(globals.db_connection));
PQclear(res);
PQfinish(globals.db_connection);
globals.db_online = 0;
switch_mutex_unlock(globals.db_mutex);
free(query);
return 0;
}
PQclear(res);
free(query);
res = PQexec(globals.db_connection, "END");
if (PQresultStatus(res) != PGRES_COMMAND_OK) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "END command failed: %s", PQerrorMessage(globals.db_connection));
PQclear(res);
PQfinish(globals.db_connection);
globals.db_online = 0;
switch_mutex_unlock(globals.db_mutex);
return 0;
}
PQclear(res);
switch_safe_free(sql);
switch_mutex_unlock(globals.db_mutex);
return 1;
return SWITCH_STATUS_SUCCESS;
error:
PQfinish(globals.db_connection);
globals.db_online = 0;
switch_mutex_unlock(globals.db_mutex);
/* SQL INSERT failed for whatever reason. Spool the attempted query to disk */
if (!strcasecmp(globals.spool_format, "sql")) {
path = switch_mprintf("%s%scdr-spool.sql", globals.log_dir, SWITCH_PATH_SEPARATOR);
assert(path);
spool_cdr(path, sql);
} else {
path = switch_mprintf("%s%scdr-spool.csv", globals.log_dir, SWITCH_PATH_SEPARATOR);
assert(path);
spool_cdr(path, cdr);
}
switch_safe_free(path);
switch_safe_free(sql);
return SWITCH_STATUS_FALSE;
}
static switch_status_t my_on_hangup(switch_core_session_t *session)
static switch_status_t my_on_reporting(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_status_t status = SWITCH_STATUS_SUCCESS;
const char *log_dir = NULL, *accountcode = NULL, *a_template_str = NULL, *g_template_str = NULL;
char *log_line, *path = NULL;
int saved = 0;
const char *template_str = NULL;
char *expanded_vars = NULL;
if (globals.shutdown) {
return SWITCH_STATUS_SUCCESS;
@@ -414,12 +402,8 @@ static switch_status_t my_on_hangup(switch_core_session_t *session)
}
}
if (!(log_dir = switch_channel_get_variable(channel, "cdr_pg_csv_base"))) {
log_dir = globals.log_dir;
}
if (switch_dir_make_recursive(log_dir, SWITCH_DEFAULT_DIR_PERMS, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", log_dir);
if (switch_dir_make_recursive(globals.log_dir, SWITCH_DEFAULT_DIR_PERMS, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.log_dir);
return SWITCH_STATUS_FALSE;
}
@@ -432,58 +416,27 @@ static switch_status_t my_on_hangup(switch_core_session_t *session)
switch_assert(buf);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "CHANNEL_DATA:\n%s\n", buf);
switch_event_destroy(&event);
free(buf);
switch_safe_free(buf);
}
}
g_template_str = (const char *) switch_core_hash_find(globals.template_hash, globals.default_template);
template_str = (const char *) switch_core_hash_find(globals.template_hash, globals.default_template);
if ((accountcode = switch_channel_get_variable(channel, "ACCOUNTCODE"))) {
a_template_str = (const char *) switch_core_hash_find(globals.template_hash, accountcode);
if (!template_str) {
template_str = default_template;
}
if (!g_template_str) {
g_template_str = "\"${accountcode}\",\"${caller_id_number}\",\"${destination_number}\",\"${context}\",\"${caller_id}\",\"${channel_name}\",\"${bridge_channel}\",\"${last_app}\",\"${last_arg}\",\"${start_stamp}\",\"${answer_stamp}\",\"${end_stamp}\",\"${duration}\",\"${billsec}\",\"${hangup_cause}\",\"${amaflags}\",\"${uuid}\",\"${userfield}\";";
}
expanded_vars = switch_channel_expand_variables(channel, template_str);
if (!a_template_str) {
a_template_str = g_template_str;
}
log_line = switch_channel_expand_variables(channel, a_template_str);
saved = 1; // save_cdr(globals.a_table, a_template_str, log_line);
if (!saved && accountcode) {
path = switch_mprintf("%s%s%s.csv", log_dir, SWITCH_PATH_SEPARATOR, accountcode);
assert(path);
write_cdr(path, log_line);
free(path);
}
if (g_template_str != a_template_str) {
if (log_line != a_template_str) {
switch_safe_free(log_line);
}
log_line = switch_channel_expand_variables(channel, g_template_str);
}
if (!log_line) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating cdr\n");
if (!expanded_vars) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error expanding CDR variables.\n");
return SWITCH_STATUS_FALSE;
}
saved = save_cdr(globals.g_table, g_template_str, log_line);
insert_cdr(template_str, expanded_vars);
if (!saved) {
path = switch_mprintf("%s%sMaster.csv", log_dir, SWITCH_PATH_SEPARATOR);
assert(path);
write_cdr(path, log_line);
free(path);
}
if (log_line != g_template_str) {
free(log_line);
if (expanded_vars != template_str) {
switch_safe_free(expanded_vars);
}
return status;
@@ -513,7 +466,6 @@ static void event_handler(switch_event_t *event)
PQfinish(globals.db_connection);
globals.db_online = 0;
}
}
}
@@ -522,9 +474,14 @@ static switch_state_handler_table_t state_handlers = {
/*.on_init */ NULL,
/*.on_routing */ NULL,
/*.on_execute */ NULL,
/*.on_hangup */ my_on_hangup,
/*.on_hangup */ NULL,
/*.on_exchange_media */ NULL,
/*.on_soft_execute */ NULL
/*.on_soft_execute */ NULL,
/*.on_consume_media */ NULL,
/*.on_hibernate */ NULL,
/*.on_reset */ NULL,
/*.on_park */ NULL,
/*.on_reporting */ my_on_reporting
};
@@ -574,14 +531,14 @@ static switch_status_t load_config(switch_memory_pool_t *pool)
globals.log_dir = switch_core_sprintf(pool, "%s%scdr-pg-csv", val, SWITCH_PATH_SEPARATOR);
} else if (!strcasecmp(var, "rotate-on-hup")) {
globals.rotate = switch_true(val);
} else if (!strcasecmp(var, "default-template")) {
globals.default_template = switch_core_strdup(pool, val);
} else if (!strcasecmp(var, "a-table")) {
globals.a_table = switch_core_strdup(pool, val);
} else if (!strcasecmp(var, "g-table")) {
globals.g_table = switch_core_strdup(pool, val);
} else if (!strcasecmp(var, "db-info")) {
globals.db_info = switch_core_strdup(pool, val);
} else if (!strcasecmp(var, "db-table") || !strcasecmp(var, "g-table")) {
globals.db_table = switch_core_strdup(pool, val);
} else if (!strcasecmp(var, "default-template")) {
globals.default_template = switch_core_strdup(pool, val);
} else if (!strcasecmp(var, "spool-format")) {
globals.spool_format = switch_core_strdup(pool, val);
}
}
}
@@ -591,13 +548,7 @@ static switch_status_t load_config(switch_memory_pool_t *pool)
char *var = (char *) switch_xml_attr(param, "name");
if (var) {
char *tpl;
size_t len = strlen(param->txt) + 2;
if (end_of(param->txt) != '\n') {
tpl = switch_core_alloc(pool, len);
switch_snprintf(tpl, len, "%s\n", param->txt);
} else {
tpl = switch_core_strdup(pool, param->txt);
}
tpl = switch_core_strdup(pool, param->txt);
switch_core_hash_insert(globals.template_hash, var, tpl);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding template %s.\n", var);
@@ -607,25 +558,24 @@ static switch_status_t load_config(switch_memory_pool_t *pool)
switch_xml_free(xml);
}
if (!globals.log_dir) {
globals.log_dir = switch_core_sprintf(pool, "%s%scdr-pg-csv", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
}
if (zstr(globals.db_info)) {
globals.db_info = switch_core_strdup(pool, "dbname=cdr");
}
if (zstr(globals.db_table)) {
globals.db_table = switch_core_strdup(pool, "cdr");
}
if (zstr(globals.default_template)) {
globals.default_template = switch_core_strdup(pool, "default");
}
if (!globals.log_dir) {
globals.log_dir = switch_core_sprintf(pool, "%s%scdr-pg-csv", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
}
if (zstr(globals.a_table)) {
globals.a_table = switch_core_strdup(pool, "a");
}
if (zstr(globals.g_table)) {
globals.g_table = switch_core_strdup(pool, "g");
}
if (zstr(globals.db_info)) {
globals.db_info = switch_core_strdup(pool, "dbname = cdr");
if (zstr(globals.spool_format)) {
globals.spool_format = switch_core_strdup(pool, "csv");
}
return status;
@@ -636,19 +586,21 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_pg_csv_load)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
if (switch_event_bind(modname, SWITCH_EVENT_TRAP, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
load_config(pool);
if ((status = switch_dir_make_recursive(globals.log_dir, SWITCH_DEFAULT_DIR_PERMS, pool)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.log_dir);
return status;
}
if ((status = switch_event_bind(modname, SWITCH_EVENT_TRAP, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
return SWITCH_STATUS_GENERR;
return status;
}
switch_core_add_state_handler(&state_handlers);
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
load_config(pool);
if ((status = switch_dir_make_recursive(globals.log_dir, SWITCH_DEFAULT_DIR_PERMS, pool)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.log_dir);
}
return status;
}
@@ -0,0 +1 @@
include ../../../../build/modmake.rules
@@ -0,0 +1,309 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2010, 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):
* Daniel Swarbrick <daniel.swarbrick@seventhsignal.de>
*
* mod_cdr_sqlite.c -- SQLite CDR Module
*
* Derived from:
* mod_cdr_csv.c -- Asterisk Compatible CDR Module
*
*/
#include <switch.h>
typedef enum {
CDR_LEG_A = (1 << 0),
CDR_LEG_B = (1 << 1)
} cdr_leg_t;
static char default_create_sql[] =
"CREATE TABLE %s (\n"
" caller_id_name VARCHAR,\n"
" caller_id_number VARCHAR,\n"
" destination_number VARCHAR,\n"
" context VARCHAR,\n"
" start_stamp DATETIME,\n"
" answer_stamp DATETIME,\n"
" end_stamp DATETIME,\n"
" duration INTEGER,\n"
" billsec INTEGER,\n"
" hangup_cause VARCHAR,\n"
" uuid VARCHAR,\n"
" bleg_uuid VARCHAR,\n"
" account_code VARCHAR\n"
")\n";
const char *default_template =
"\"${caller_id_name}\",\"${caller_id_number}\",\"${destination_number}\",\"${context}\","
"\"${start_stamp}\",\"${answer_stamp}\",\"${end_stamp}\",${duration},${billsec},"
"\"${hangup_cause}\",\"${uuid}\",\"${bleg_uuid}\",\"${accountcode}\"";
static struct {
switch_memory_pool_t *pool;
char *db_name;
char *db_table;
cdr_leg_t legs;
int debug;
switch_hash_t *template_hash;
char *default_template;
int shutdown;
} globals;
SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_sqlite_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_cdr_sqlite_shutdown);
SWITCH_MODULE_DEFINITION(mod_cdr_sqlite, mod_cdr_sqlite_load, mod_cdr_sqlite_shutdown, NULL);
switch_cache_db_handle_t *cdr_get_db_handle(void)
{
switch_cache_db_connection_options_t options = { {0} };
switch_cache_db_handle_t *dbh = NULL;
options.core_db_options.db_path = globals.db_name;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_CORE_DB, &options) != SWITCH_STATUS_SUCCESS)
dbh = NULL;
return dbh;
}
static switch_status_t write_cdr(char *sql)
{
switch_cache_db_handle_t *dbh = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
if (!(dbh = cdr_get_db_handle())) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n");
goto end;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Writing SQL to DB: %s\n", sql);
status = switch_cache_db_execute_sql(dbh, sql, NULL);
end:
switch_cache_db_release_db_handle(&dbh);
return status;
}
static switch_status_t my_on_reporting(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_status_t status = SWITCH_STATUS_SUCCESS;
const char *template_str = NULL;
char *expanded_vars = NULL, *sql = NULL;
if (globals.shutdown) {
return SWITCH_STATUS_SUCCESS;
}
if (!((globals.legs & CDR_LEG_A) && (globals.legs & CDR_LEG_B))) {
if ((globals.legs & CDR_LEG_A)) {
if (switch_channel_get_originator_caller_profile(channel)) {
return SWITCH_STATUS_SUCCESS;
}
} else {
if (switch_channel_get_originatee_caller_profile(channel)) {
return SWITCH_STATUS_SUCCESS;
}
}
}
if (globals.debug) {
switch_event_t *event;
if (switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
char *buf;
switch_channel_event_set_data(channel, event);
switch_event_serialize(event, &buf, SWITCH_FALSE);
switch_assert(buf);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "CHANNEL_DATA:\n%s\n", buf);
switch_event_destroy(&event);
switch_safe_free(buf);
}
}
template_str = (const char *) switch_core_hash_find(globals.template_hash, globals.default_template);
if (!template_str) {
template_str = default_template;
}
expanded_vars = switch_channel_expand_variables(channel, template_str);
if (!expanded_vars) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error expanding CDR variables.\n");
return SWITCH_STATUS_FALSE;
}
sql = switch_mprintf("INSERT INTO %s VALUES (%s)", globals.db_table, expanded_vars);
assert(sql);
write_cdr(sql);
switch_safe_free(sql);
return status;
}
static switch_state_handler_table_t state_handlers = {
/*.on_init */ NULL,
/*.on_routing */ NULL,
/*.on_execute */ NULL,
/*.on_hangup */ NULL,
/*.on_exchange_media */ NULL,
/*.on_soft_execute */ NULL,
/*.on_consume_media */ NULL,
/*.on_hibernate */ NULL,
/*.on_reset */ NULL,
/*.on_park */ NULL,
/*.on_reporting */ my_on_reporting
};
static switch_status_t load_config(switch_memory_pool_t *pool)
{
char *cf = "cdr_sqlite.conf";
switch_xml_t cfg, xml, settings, param;
switch_cache_db_handle_t *dbh = NULL;
char *select_sql = NULL, *create_sql = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
memset(&globals, 0, sizeof(globals));
switch_core_hash_init(&globals.template_hash, pool);
globals.pool = pool;
switch_core_hash_insert(globals.template_hash, "default", default_template);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding default template.\n");
globals.legs = CDR_LEG_A;
if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
if ((settings = switch_xml_child(cfg, "settings"))) {
for (param = switch_xml_child(settings, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if (!strcasecmp(var, "debug")) {
globals.debug = switch_true(val);
} else if (!strcasecmp(var, "db-name")) {
globals.db_name = switch_core_strdup(pool, val);
} else if (!strcasecmp(var, "db-table")) {
globals.db_table = switch_core_strdup(pool, val);
} else if (!strcasecmp(var, "legs")) {
globals.legs = 0;
if (strchr(val, 'a')) {
globals.legs |= CDR_LEG_A;
}
if (strchr(val, 'b')) {
globals.legs |= CDR_LEG_B;
}
} else if (!strcasecmp(var, "default-template")) {
globals.default_template = switch_core_strdup(pool, val);
}
}
}
if ((settings = switch_xml_child(cfg, "templates"))) {
for (param = switch_xml_child(settings, "template"); param; param = param->next) {
char *var = (char *) switch_xml_attr(param, "name");
if (var) {
char *tpl;
tpl = switch_core_strdup(pool, param->txt);
switch_core_hash_insert(globals.template_hash, var, tpl);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding template %s.\n", var);
}
}
}
switch_xml_free(xml);
}
if (zstr(globals.db_name)) {
globals.db_name = switch_core_strdup(pool, "cdr");
}
if (zstr(globals.db_table)) {
globals.db_table = switch_core_strdup(pool, "cdr");
}
if (zstr(globals.default_template)) {
globals.default_template = switch_core_strdup(pool, "default");
}
dbh = cdr_get_db_handle();
if (dbh) {
select_sql = switch_mprintf("SELECT * FROM %s LIMIT 1", globals.db_table);
assert(select_sql);
create_sql = switch_mprintf(default_create_sql, globals.db_table);
assert(create_sql);
/* Check if table exists (try SELECT FROM ...) and create table if query fails */
switch_cache_db_test_reactive(dbh, select_sql, NULL, create_sql);
switch_safe_free(select_sql);
switch_safe_free(create_sql);
switch_cache_db_release_db_handle(&dbh);
}
return status;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_sqlite_load)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
load_config(pool);
switch_core_add_state_handler(&state_handlers);
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
return status;
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_cdr_sqlite_shutdown)
{
globals.shutdown = 1;
switch_core_remove_state_handler(&state_handlers);
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:
*/
@@ -31,8 +31,8 @@
*/
#include <switch.h>
#define CMD_BUFLEN 1024 * 1000
#define MAX_QUEUE_LEN 5000
#define MAX_MISSED 200
#define MAX_QUEUE_LEN 25000
#define MAX_MISSED 2000
SWITCH_MODULE_LOAD_FUNCTION(mod_event_socket_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_event_socket_shutdown);
SWITCH_MODULE_RUNTIME_FUNCTION(mod_event_socket_runtime);
@@ -170,7 +170,7 @@ static switch_status_t socket_logger(const switch_log_node_t *node, switch_log_l
if (switch_test_flag(l, LFLAG_LOG) && l->level >= node->level) {
switch_log_node_t *dnode = switch_log_node_dup(node);
if (switch_queue_trypush(l->log_queue, dnode) == SWITCH_STATUS_SUCCESS) {
if (switch_queue_push(l->log_queue, dnode) == SWITCH_STATUS_SUCCESS) {
if (l->lost_logs) {
int ll = l->lost_logs;
switch_event_t *event;
@@ -366,7 +366,7 @@ static void event_handler(switch_event_t *event)
if (send) {
if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) {
if (switch_queue_trypush(l->event_queue, clone) == SWITCH_STATUS_SUCCESS) {
if (switch_queue_push(l->event_queue, clone) == SWITCH_STATUS_SUCCESS) {
if (l->lost_events) {
int le = l->lost_events;
l->lost_events = 0;
@@ -1233,7 +1233,7 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event,
if (switch_channel_get_state(chan) < CS_HANGUP && switch_channel_test_flag(chan, CF_DIVERT_EVENTS)) {
switch_event_t *e = NULL;
while (switch_core_session_dequeue_event(listener->session, &e, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
if (switch_queue_trypush(listener->event_queue, e) != SWITCH_STATUS_SUCCESS) {
if (switch_queue_push(listener->event_queue, e) != SWITCH_STATUS_SUCCESS) {
switch_core_session_queue_event(listener->session, &e);
break;
}
@@ -1452,7 +1452,7 @@ static switch_bool_t auth_api_command(listener_t *listener, const char *api_cmd,
switch_bool_t ok = SWITCH_TRUE;
top:
if (!switch_core_hash_find(listener->allowed_api_hash, check_cmd)) {
ok = SWITCH_FALSE;
goto end;
@@ -1556,14 +1556,18 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t **even
user = cmd + 9;
if ((pass = strchr(user, ':'))) {
*pass++ = '\0';
}
if ((domain_name = strchr(user, '@'))) {
*domain_name++ = '\0';
}
if ((pass = strchr(domain_name, ':'))) {
*pass++ = '\0';
}
if ((pass = strchr(user, ':'))) {
*pass++ = '\0';
}
if (zstr(user) || zstr(domain_name)) {
switch_snprintf(reply, reply_len, "-ERR invalid");
switch_clear_flag_locked(listener, LFLAG_RUNNING);
@@ -2044,21 +2048,31 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t **even
char *arg = NULL;
strip_cr(api_cmd);
if (!(acs.console_execute = switch_true(console_execute))) {
if ((arg = strchr(api_cmd, ' '))) {
*arg++ = '\0';
}
}
if (listener->allowed_api_hash) {
if (!auth_api_command(listener, api_cmd, arg)) {
char *api_copy = strdup(api_cmd);
char *arg_copy = NULL;
int ok = 0;
if ((arg_copy = strchr(api_copy, ' '))) {
*arg_copy++ = '\0';
}
ok = auth_api_command(listener, api_copy, arg_copy);
free(api_copy);
if (!ok) {
switch_snprintf(reply, reply_len, "-ERR permission denied");
status = SWITCH_STATUS_SUCCESS;
goto done;
}
}
if (!(acs.console_execute = switch_true(console_execute))) {
if ((arg = strchr(api_cmd, ' '))) {
*arg++ = '\0';
}
}
acs.listener = listener;
acs.api_cmd = api_cmd;
acs.arg = arg;
@@ -116,6 +116,10 @@ public class CoreSession {
return freeswitchJNI.CoreSession_voice_name_get(swigCPtr, this);
}
public int insertFile(String file, String insert_file, int sample_point) {
return freeswitchJNI.CoreSession_insertFile(swigCPtr, this, file, insert_file, sample_point);
}
public int answer() {
return freeswitchJNI.CoreSession_answer(swigCPtr, this);
}
@@ -101,6 +101,7 @@ class freeswitchJNI {
public final static native String CoreSession_tts_name_get(long jarg1, CoreSession jarg1_);
public final static native void CoreSession_voice_name_set(long jarg1, CoreSession jarg1_, String jarg2);
public final static native String CoreSession_voice_name_get(long jarg1, CoreSession jarg1_);
public final static native int CoreSession_insertFile(long jarg1, CoreSession jarg1_, String jarg2, String jarg3, int jarg4);
public final static native int CoreSession_answer(long jarg1, CoreSession jarg1_);
public final static native int CoreSession_preAnswer(long jarg1, CoreSession jarg1_);
public final static native void CoreSession_hangup(long jarg1, CoreSession jarg1_, String jarg2);
@@ -1866,6 +1866,37 @@ SWIGEXPORT jstring JNICALL Java_org_freeswitch_swig_freeswitchJNI_CoreSession_1v
}
SWIGEXPORT jint JNICALL Java_org_freeswitch_swig_freeswitchJNI_CoreSession_1insertFile(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2, jstring jarg3, jint jarg4) {
jint jresult = 0 ;
CoreSession *arg1 = (CoreSession *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
int arg4 ;
int result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CoreSession **)&jarg1;
arg2 = 0;
if (jarg2) {
arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0);
if (!arg2) return 0;
}
arg3 = 0;
if (jarg3) {
arg3 = (char *)jenv->GetStringUTFChars(jarg3, 0);
if (!arg3) return 0;
}
arg4 = (int)jarg4;
result = (int)(arg1)->insertFile((char const *)arg2,(char const *)arg3,arg4);
jresult = (jint)result;
if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2);
if (arg3) jenv->ReleaseStringUTFChars(jarg3, (const char *)arg3);
return jresult;
}
SWIGEXPORT jint JNICALL Java_org_freeswitch_swig_freeswitchJNI_CoreSession_1answer(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
jint jresult = 0 ;
CoreSession *arg1 = (CoreSession *) 0 ;
+2 -1
View File
@@ -82,12 +82,13 @@ class Session : public CoreSession {
class Dbh {
private:
switch_cache_db_handle_t *dbh;
bool connected;
bool m_connected;
static int query_callback(void *pArg, int argc, char **argv, char **cargv);
public:
Dbh(char *dsn, char *user = NULL, char *pass = NULL);
~Dbh();
bool release();
bool connected();
bool query(char *sql, SWIGLUA_FN lua_fun);
};
+10 -5
View File
@@ -318,9 +318,9 @@ Dbh::Dbh(char *dsn, char *user, char *pass)
options.odbc_options.pass = pass;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) == SWITCH_STATUS_SUCCESS) {
connected = true;
m_connected = true;
} else {
connected = false;
m_connected = false;
}
}
@@ -331,14 +331,19 @@ Dbh::~Dbh()
bool Dbh::release()
{
if (connected) {
if (m_connected) {
switch_cache_db_release_db_handle(&dbh);
connected = false;
m_connected = false;
return true;
}
return false;
}
bool Dbh::connected()
{
return m_connected;
}
int Dbh::query_callback(void *pArg, int argc, char **argv, char **cargv)
{
SWIGLUA_FN *lua_fun = (SWIGLUA_FN *)pArg;
@@ -366,7 +371,7 @@ int Dbh::query_callback(void *pArg, int argc, char **argv, char **cargv)
bool Dbh::query(char *sql, SWIGLUA_FN lua_fun)
{
if (connected) {
if (m_connected) {
if (lua_fun.L) {
if (switch_cache_db_execute_sql_callback(dbh, sql, query_callback, &lua_fun, NULL) == SWITCH_STATUS_SUCCESS) {
return true;
+2 -1
View File
@@ -55,12 +55,13 @@ namespace LUA {
class Dbh {
protected:
switch_cache_db_handle_t *dbh;
bool connected;
bool m_connected;
static int query_callback(void *pArg, int argc, char **argv, char **cargv);
public:
Dbh(char *dsn, char *user = NULL, char *pass = NULL);
~Dbh();
bool release();
bool connected();
bool query(char *sql, SWIGLUA_FN lua_fun);
};
}
+1 -1
View File
@@ -450,7 +450,7 @@ SWITCH_STANDARD_API(lua_api_function)
if (switch_event_get_header(stream->param_event, "http-host")) {
stream->write_function(stream, "Content-Type: text/html\n\n<H2>Error Executing Script</H2>");
} else {
stream->write_function(stream, "-ERR encounterd\n");
stream->write_function(stream, "-ERR encountered\n");
}
}
lua_uninit(L);
@@ -4287,6 +4287,40 @@ fail:
}
static int _wrap_CoreSession_insertFile(lua_State* L) {
int SWIG_arg = -1;
CoreSession *arg1 = (CoreSession *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
int arg4 ;
int result;
SWIG_check_num_args("insertFile",4,4)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("insertFile",1,"CoreSession *");
if(!lua_isstring(L,2)) SWIG_fail_arg("insertFile",2,"char const *");
if(!lua_isstring(L,3)) SWIG_fail_arg("insertFile",3,"char const *");
if(!lua_isnumber(L,4)) SWIG_fail_arg("insertFile",4,"int");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_CoreSession,0))){
SWIG_fail_ptr("CoreSession_insertFile",1,SWIGTYPE_p_CoreSession);
}
arg2 = (char *)lua_tostring(L, 2);
arg3 = (char *)lua_tostring(L, 3);
arg4 = (int)lua_tonumber(L, 4);
result = (int)(arg1)->insertFile((char const *)arg2,(char const *)arg3,arg4);
SWIG_arg=0;
lua_pushnumber(L, (lua_Number) result); SWIG_arg++;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_CoreSession_answer(lua_State* L) {
int SWIG_arg = -1;
CoreSession *arg1 = (CoreSession *) 0 ;
@@ -5864,6 +5898,7 @@ CoreSession *arg1 = (CoreSession *) obj;
delete arg1;
}
static swig_lua_method swig_CoreSession_methods[] = {
{"insertFile", _wrap_CoreSession_insertFile},
{"answer", _wrap_CoreSession_answer},
{"preAnswer", _wrap_CoreSession_preAnswer},
{"hangup", _wrap_CoreSession_hangup},
@@ -7194,6 +7229,31 @@ fail:
}
static int _wrap_Dbh_connected(lua_State* L) {
int SWIG_arg = -1;
LUA::Dbh *arg1 = (LUA::Dbh *) 0 ;
bool result;
SWIG_check_num_args("connected",1,1)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("connected",1,"LUA::Dbh *");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,0))){
SWIG_fail_ptr("Dbh_connected",1,SWIGTYPE_p_LUA__Dbh);
}
result = (bool)(arg1)->connected();
SWIG_arg=0;
lua_pushboolean(L,(int)(result==true)); SWIG_arg++;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_Dbh_query(lua_State* L) {
int SWIG_arg = -1;
LUA::Dbh *arg1 = (LUA::Dbh *) 0 ;
@@ -7242,6 +7302,7 @@ delete arg1;
}
static swig_lua_method swig_LUA_Dbh_methods[] = {
{"release", _wrap_Dbh_release},
{"connected", _wrap_Dbh_connected},
{"query", _wrap_Dbh_query},
{0,0}
};
@@ -6298,6 +6298,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_media_bug_remove_all(void * jarg1)
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_media_bug_enumerate(void * jarg1, void * jarg2) {
int jresult ;
switch_core_session_t *arg1 = (switch_core_session_t *) 0 ;
switch_stream_handle_t *arg2 = (switch_stream_handle_t *) 0 ;
switch_status_t result;
arg1 = (switch_core_session_t *)jarg1;
arg2 = (switch_stream_handle_t *)jarg2;
result = (switch_status_t)switch_core_media_bug_enumerate(arg1,arg2);
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_media_bug_read(void * jarg1, void * jarg2, int jarg3) {
int jresult ;
switch_media_bug_t *arg1 = (switch_media_bug_t *) 0 ;
@@ -12406,13 +12420,15 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_is_number(char * jarg1) {
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_strip_spaces(char * jarg1) {
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_strip_spaces(char * jarg1, int jarg2) {
char * jresult ;
char *arg1 = (char *) 0 ;
switch_bool_t arg2 ;
char *result = 0 ;
arg1 = (char *)jarg1;
result = (char *)switch_strip_spaces((char const *)arg1);
arg2 = (switch_bool_t)jarg2;
result = (char *)switch_strip_spaces(arg1,arg2);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
@@ -22969,6 +22985,16 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_set_caller_extension(void * ja
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_sort_cid(void * jarg1, int jarg2) {
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
switch_bool_t arg2 ;
arg1 = (switch_channel_t *)jarg1;
arg2 = (switch_bool_t)jarg2;
switch_channel_sort_cid(arg1,arg2);
}
SWIGEXPORT void * SWIGSTDCALL CSharp_switch_channel_get_caller_extension(void * jarg1) {
void * jresult ;
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
@@ -28290,15 +28316,47 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_activate_rtcp(void * jarg1, int jar
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_activate_jitter_buffer(void * jarg1, unsigned long jarg2) {
SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_activate_jitter_buffer(void * jarg1, unsigned long jarg2, unsigned long jarg3, unsigned long jarg4, unsigned long jarg5) {
int jresult ;
switch_rtp_t *arg1 = (switch_rtp_t *) 0 ;
uint32_t arg2 ;
uint32_t arg3 ;
uint32_t arg4 ;
uint32_t arg5 ;
switch_status_t result;
arg1 = (switch_rtp_t *)jarg1;
arg2 = (uint32_t)jarg2;
result = (switch_status_t)switch_rtp_activate_jitter_buffer(arg1,arg2);
arg3 = (uint32_t)jarg3;
arg4 = (uint32_t)jarg4;
arg5 = (uint32_t)jarg5;
result = (switch_status_t)switch_rtp_activate_jitter_buffer(arg1,arg2,arg3,arg4,arg5);
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_debug_jitter_buffer(void * jarg1, char * jarg2) {
int jresult ;
switch_rtp_t *arg1 = (switch_rtp_t *) 0 ;
char *arg2 = (char *) 0 ;
switch_status_t result;
arg1 = (switch_rtp_t *)jarg1;
arg2 = (char *)jarg2;
result = (switch_status_t)switch_rtp_debug_jitter_buffer(arg1,(char const *)arg2);
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_deactivate_jitter_buffer(void * jarg1) {
int jresult ;
switch_rtp_t *arg1 = (switch_rtp_t *) 0 ;
switch_status_t result;
arg1 = (switch_rtp_t *)jarg1;
result = (switch_status_t)switch_rtp_deactivate_jitter_buffer(arg1);
jresult = result;
return jresult;
}
@@ -6588,6 +6588,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_media_bug_remove_all(void * jarg1)
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_media_bug_enumerate(void * jarg1, void * jarg2) {
int jresult ;
switch_core_session_t *arg1 = (switch_core_session_t *) 0 ;
switch_stream_handle_t *arg2 = (switch_stream_handle_t *) 0 ;
switch_status_t result;
arg1 = (switch_core_session_t *)jarg1;
arg2 = (switch_stream_handle_t *)jarg2;
result = (switch_status_t)switch_core_media_bug_enumerate(arg1,arg2);
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_media_bug_read(void * jarg1, void * jarg2, int jarg3) {
int jresult ;
switch_media_bug_t *arg1 = (switch_media_bug_t *) 0 ;
@@ -12726,13 +12740,15 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_is_number(char * jarg1) {
}
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_strip_spaces(char * jarg1) {
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_strip_spaces(char * jarg1, int jarg2) {
char * jresult ;
char *arg1 = (char *) 0 ;
switch_bool_t arg2 ;
char *result = 0 ;
arg1 = (char *)jarg1;
result = (char *)switch_strip_spaces((char const *)arg1);
arg2 = (switch_bool_t)jarg2;
result = (char *)switch_strip_spaces(arg1,arg2);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
@@ -23624,6 +23640,16 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_set_caller_extension(void * ja
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_sort_cid(void * jarg1, int jarg2) {
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
switch_bool_t arg2 ;
arg1 = (switch_channel_t *)jarg1;
arg2 = (switch_bool_t)jarg2;
switch_channel_sort_cid(arg1,arg2);
}
SWIGEXPORT void * SWIGSTDCALL CSharp_switch_channel_get_caller_extension(void * jarg1) {
void * jresult ;
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
@@ -28993,15 +29019,47 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_activate_rtcp(void * jarg1, int jar
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_activate_jitter_buffer(void * jarg1, unsigned long jarg2) {
SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_activate_jitter_buffer(void * jarg1, unsigned long jarg2, unsigned long jarg3, unsigned long jarg4, unsigned long jarg5) {
int jresult ;
switch_rtp_t *arg1 = (switch_rtp_t *) 0 ;
uint32_t arg2 ;
uint32_t arg3 ;
uint32_t arg4 ;
uint32_t arg5 ;
switch_status_t result;
arg1 = (switch_rtp_t *)jarg1;
arg2 = (uint32_t)jarg2;
result = (switch_status_t)switch_rtp_activate_jitter_buffer(arg1,arg2);
arg3 = (uint32_t)jarg3;
arg4 = (uint32_t)jarg4;
arg5 = (uint32_t)jarg5;
result = (switch_status_t)switch_rtp_activate_jitter_buffer(arg1,arg2,arg3,arg4,arg5);
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_debug_jitter_buffer(void * jarg1, char * jarg2) {
int jresult ;
switch_rtp_t *arg1 = (switch_rtp_t *) 0 ;
char *arg2 = (char *) 0 ;
switch_status_t result;
arg1 = (switch_rtp_t *)jarg1;
arg2 = (char *)jarg2;
result = (switch_status_t)switch_rtp_debug_jitter_buffer(arg1,(char const *)arg2);
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_deactivate_jitter_buffer(void * jarg1) {
int jresult ;
switch_rtp_t *arg1 = (switch_rtp_t *) 0 ;
switch_status_t result;
arg1 = (switch_rtp_t *)jarg1;
result = (switch_status_t)switch_rtp_deactivate_jitter_buffer(arg1);
jresult = result;
return jresult;
}
@@ -33979,6 +34037,24 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_CoreSession_voice_name_get(void * jarg1) {
}
SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_insertFile(void * jarg1, char * jarg2, char * jarg3, int jarg4) {
int jresult ;
CoreSession *arg1 = (CoreSession *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
int arg4 ;
int result;
arg1 = (CoreSession *)jarg1;
arg2 = (char *)jarg2;
arg3 = (char *)jarg3;
arg4 = (int)jarg4;
result = (int)(arg1)->insertFile((char const *)arg2,(char const *)arg3,arg4);
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_Answer(void * jarg1) {
int jresult ;
CoreSession *arg1 = (CoreSession *) 0 ;
@@ -1055,6 +1055,11 @@ public class freeswitch {
return ret;
}
public static switch_status_t switch_core_media_bug_enumerate(SWIGTYPE_p_switch_core_session session, switch_stream_handle stream) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_media_bug_enumerate(SWIGTYPE_p_switch_core_session.getCPtr(session), switch_stream_handle.getCPtr(stream));
return ret;
}
public static switch_status_t switch_core_media_bug_read(SWIGTYPE_p_switch_media_bug bug, switch_frame frame, switch_bool_t fill) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_media_bug_read(SWIGTYPE_p_switch_media_bug.getCPtr(bug), switch_frame.getCPtr(frame), (int)fill);
return ret;
@@ -2877,8 +2882,8 @@ public class freeswitch {
return ret;
}
public static string switch_strip_spaces(string str) {
string ret = freeswitchPINVOKE.switch_strip_spaces(str);
public static string switch_strip_spaces(string str, switch_bool_t dup) {
string ret = freeswitchPINVOKE.switch_strip_spaces(str, (int)dup);
return ret;
}
@@ -3328,6 +3333,10 @@ public class freeswitch {
freeswitchPINVOKE.switch_channel_set_caller_extension(SWIGTYPE_p_switch_channel.getCPtr(channel), switch_caller_extension.getCPtr(caller_extension));
}
public static void switch_channel_sort_cid(SWIGTYPE_p_switch_channel channel, switch_bool_t arg1) {
freeswitchPINVOKE.switch_channel_sort_cid(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)arg1);
}
public static switch_caller_extension switch_channel_get_caller_extension(SWIGTYPE_p_switch_channel channel) {
IntPtr cPtr = freeswitchPINVOKE.switch_channel_get_caller_extension(SWIGTYPE_p_switch_channel.getCPtr(channel));
switch_caller_extension ret = (cPtr == IntPtr.Zero) ? null : new switch_caller_extension(cPtr, false);
@@ -4640,8 +4649,18 @@ public class freeswitch {
return ret;
}
public static switch_status_t switch_rtp_activate_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session, uint queue_frames) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_activate_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), queue_frames);
public static switch_status_t switch_rtp_activate_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session, uint queue_frames, uint max_queue_frames, uint samples_per_packet, uint samples_per_second) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_activate_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), queue_frames, max_queue_frames, samples_per_packet, samples_per_second);
return ret;
}
public static switch_status_t switch_rtp_debug_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session, string name) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_debug_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), name);
return ret;
}
public static switch_status_t switch_rtp_deactivate_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_deactivate_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session));
return ret;
}
@@ -7269,6 +7288,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_media_bug_remove_all")]
public static extern int switch_core_media_bug_remove_all(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_media_bug_enumerate")]
public static extern int switch_core_media_bug_enumerate(HandleRef jarg1, HandleRef jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_media_bug_read")]
public static extern int switch_core_media_bug_read(HandleRef jarg1, HandleRef jarg2, int jarg3);
@@ -8656,7 +8678,7 @@ class freeswitchPINVOKE {
public static extern int switch_is_number(string jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_strip_spaces")]
public static extern string switch_strip_spaces(string jarg1);
public static extern string switch_strip_spaces(string jarg1, int jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_strip_whitespace")]
public static extern string switch_strip_whitespace(string jarg1);
@@ -11322,6 +11344,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_set_caller_extension")]
public static extern void switch_channel_set_caller_extension(HandleRef jarg1, HandleRef jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_sort_cid")]
public static extern void switch_channel_sort_cid(HandleRef jarg1, int jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_caller_extension")]
public static extern IntPtr switch_channel_get_caller_extension(HandleRef jarg1);
@@ -12448,7 +12473,13 @@ class freeswitchPINVOKE {
public static extern int switch_rtp_activate_rtcp(HandleRef jarg1, int jarg2, ushort jarg3);
[DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_activate_jitter_buffer")]
public static extern int switch_rtp_activate_jitter_buffer(HandleRef jarg1, uint jarg2);
public static extern int switch_rtp_activate_jitter_buffer(HandleRef jarg1, uint jarg2, uint jarg3, uint jarg4, uint jarg5);
[DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_debug_jitter_buffer")]
public static extern int switch_rtp_debug_jitter_buffer(HandleRef jarg1, string jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_deactivate_jitter_buffer")]
public static extern int switch_rtp_deactivate_jitter_buffer(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_set_flag")]
public static extern void switch_rtp_set_flag(HandleRef jarg1, uint jarg2);
@@ -21554,6 +21585,10 @@ public enum switch_channel_flag_t {
CF_PASSTHRU_PTIME_MISMATCH,
CF_BRIDGE_NOWRITE,
CF_RECOVERED,
CF_JITTERBUFFER,
CF_DIALPLAN,
CF_BLOCK_BROADCAST_UNTIL_MEDIA,
CF_CNG_PLC,
CF_FLAG_MAX
}
@@ -23243,6 +23278,8 @@ public enum switch_core_session_message_types_t {
SWITCH_MESSAGE_INDICATE_T38_DESCRIPTION,
SWITCH_MESSAGE_INDICATE_UDPTL_MODE,
SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS,
SWITCH_MESSAGE_INDICATE_JITTER_BUFFER,
SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH,
SWITCH_MESSAGE_INVALID
}
+51 -6
View File
@@ -220,6 +220,11 @@ public class CoreSession : IDisposable {
}
}
public int insertFile(string file, string insert_file, int sample_point) {
int ret = freeswitchPINVOKE.CoreSession_insertFile(swigCPtr, file, insert_file, sample_point);
return ret;
}
public int Answer() {
int ret = freeswitchPINVOKE.CoreSession_Answer(swigCPtr);
return ret;
@@ -1045,6 +1050,11 @@ public class freeswitch {
return ret;
}
public static switch_status_t switch_core_media_bug_enumerate(SWIGTYPE_p_switch_core_session session, switch_stream_handle stream) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_media_bug_enumerate(SWIGTYPE_p_switch_core_session.getCPtr(session), switch_stream_handle.getCPtr(stream));
return ret;
}
public static switch_status_t switch_core_media_bug_read(SWIGTYPE_p_switch_media_bug bug, switch_frame frame, switch_bool_t fill) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_media_bug_read(SWIGTYPE_p_switch_media_bug.getCPtr(bug), switch_frame.getCPtr(frame), (int)fill);
return ret;
@@ -2867,8 +2877,8 @@ public class freeswitch {
return ret;
}
public static string switch_strip_spaces(string str) {
string ret = freeswitchPINVOKE.switch_strip_spaces(str);
public static string switch_strip_spaces(string str, switch_bool_t dup) {
string ret = freeswitchPINVOKE.switch_strip_spaces(str, (int)dup);
return ret;
}
@@ -3318,6 +3328,10 @@ public class freeswitch {
freeswitchPINVOKE.switch_channel_set_caller_extension(SWIGTYPE_p_switch_channel.getCPtr(channel), switch_caller_extension.getCPtr(caller_extension));
}
public static void switch_channel_sort_cid(SWIGTYPE_p_switch_channel channel, switch_bool_t arg1) {
freeswitchPINVOKE.switch_channel_sort_cid(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)arg1);
}
public static switch_caller_extension switch_channel_get_caller_extension(SWIGTYPE_p_switch_channel channel) {
IntPtr cPtr = freeswitchPINVOKE.switch_channel_get_caller_extension(SWIGTYPE_p_switch_channel.getCPtr(channel));
switch_caller_extension ret = (cPtr == IntPtr.Zero) ? null : new switch_caller_extension(cPtr, false);
@@ -4630,8 +4644,18 @@ public class freeswitch {
return ret;
}
public static switch_status_t switch_rtp_activate_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session, uint queue_frames) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_activate_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), queue_frames);
public static switch_status_t switch_rtp_activate_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session, uint queue_frames, uint max_queue_frames, uint samples_per_packet, uint samples_per_second) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_activate_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), queue_frames, max_queue_frames, samples_per_packet, samples_per_second);
return ret;
}
public static switch_status_t switch_rtp_debug_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session, string name) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_debug_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), name);
return ret;
}
public static switch_status_t switch_rtp_deactivate_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_deactivate_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session));
return ret;
}
@@ -7255,6 +7279,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_media_bug_remove_all")]
public static extern int switch_core_media_bug_remove_all(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_media_bug_enumerate")]
public static extern int switch_core_media_bug_enumerate(HandleRef jarg1, HandleRef jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_media_bug_read")]
public static extern int switch_core_media_bug_read(HandleRef jarg1, HandleRef jarg2, int jarg3);
@@ -8642,7 +8669,7 @@ class freeswitchPINVOKE {
public static extern int switch_is_number(string jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_strip_spaces")]
public static extern string switch_strip_spaces(string jarg1);
public static extern string switch_strip_spaces(string jarg1, int jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_strip_whitespace")]
public static extern string switch_strip_whitespace(string jarg1);
@@ -11308,6 +11335,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_set_caller_extension")]
public static extern void switch_channel_set_caller_extension(HandleRef jarg1, HandleRef jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_sort_cid")]
public static extern void switch_channel_sort_cid(HandleRef jarg1, int jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_caller_extension")]
public static extern IntPtr switch_channel_get_caller_extension(HandleRef jarg1);
@@ -12434,7 +12464,13 @@ class freeswitchPINVOKE {
public static extern int switch_rtp_activate_rtcp(HandleRef jarg1, int jarg2, ushort jarg3);
[DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_activate_jitter_buffer")]
public static extern int switch_rtp_activate_jitter_buffer(HandleRef jarg1, uint jarg2);
public static extern int switch_rtp_activate_jitter_buffer(HandleRef jarg1, uint jarg2, uint jarg3, uint jarg4, uint jarg5);
[DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_debug_jitter_buffer")]
public static extern int switch_rtp_debug_jitter_buffer(HandleRef jarg1, string jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_deactivate_jitter_buffer")]
public static extern int switch_rtp_deactivate_jitter_buffer(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_set_flag")]
public static extern void switch_rtp_set_flag(HandleRef jarg1, uint jarg2);
@@ -13627,6 +13663,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_CoreSession_voice_name_get")]
public static extern string CoreSession_voice_name_get(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_CoreSession_insertFile")]
public static extern int CoreSession_insertFile(HandleRef jarg1, string jarg2, string jarg3, int jarg4);
[DllImport("mod_managed", EntryPoint="CSharp_CoreSession_Answer")]
public static extern int CoreSession_Answer(HandleRef jarg1);
@@ -21500,6 +21539,10 @@ public enum switch_channel_flag_t {
CF_PASSTHRU_PTIME_MISMATCH,
CF_BRIDGE_NOWRITE,
CF_RECOVERED,
CF_JITTERBUFFER,
CF_DIALPLAN,
CF_BLOCK_BROADCAST_UNTIL_MEDIA,
CF_CNG_PLC,
CF_FLAG_MAX
}
@@ -23167,6 +23210,8 @@ public enum switch_core_session_message_types_t {
SWITCH_MESSAGE_INDICATE_T38_DESCRIPTION,
SWITCH_MESSAGE_INDICATE_UDPTL_MODE,
SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS,
SWITCH_MESSAGE_INDICATE_JITTER_BUFFER,
SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH,
SWITCH_MESSAGE_INVALID
}
+1
View File
@@ -404,6 +404,7 @@ sub DESTROY {
*swig_tts_name_set = *freeswitchc::CoreSession_tts_name_set;
*swig_voice_name_get = *freeswitchc::CoreSession_voice_name_get;
*swig_voice_name_set = *freeswitchc::CoreSession_voice_name_set;
*insertFile = *freeswitchc::CoreSession_insertFile;
*answer = *freeswitchc::CoreSession_answer;
*preAnswer = *freeswitchc::CoreSession_preAnswer;
*hangup = *freeswitchc::CoreSession_hangup;
@@ -5282,6 +5282,66 @@ XS(_wrap_CoreSession_voice_name_get) {
}
XS(_wrap_CoreSession_insertFile) {
{
CoreSession *arg1 = (CoreSession *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
int arg4 ;
int result;
void *argp1 = 0 ;
int res1 = 0 ;
int res2 ;
char *buf2 = 0 ;
int alloc2 = 0 ;
int res3 ;
char *buf3 = 0 ;
int alloc3 = 0 ;
int val4 ;
int ecode4 = 0 ;
int argvi = 0;
dXSARGS;
if ((items < 4) || (items > 4)) {
SWIG_croak("Usage: CoreSession_insertFile(self,file,insert_file,sample_point);");
}
res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_CoreSession, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_insertFile" "', argument " "1"" of type '" "CoreSession *""'");
}
arg1 = reinterpret_cast< CoreSession * >(argp1);
res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "CoreSession_insertFile" "', argument " "2"" of type '" "char const *""'");
}
arg2 = reinterpret_cast< char * >(buf2);
res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
if (!SWIG_IsOK(res3)) {
SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "CoreSession_insertFile" "', argument " "3"" of type '" "char const *""'");
}
arg3 = reinterpret_cast< char * >(buf3);
ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
if (!SWIG_IsOK(ecode4)) {
SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "CoreSession_insertFile" "', argument " "4"" of type '" "int""'");
}
arg4 = static_cast< int >(val4);
result = (int)(arg1)->insertFile((char const *)arg2,(char const *)arg3,arg4);
ST(argvi) = SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
XSRETURN(argvi);
fail:
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
SWIG_croak_null();
}
}
XS(_wrap_CoreSession_answer) {
{
CoreSession *arg1 = (CoreSession *) 0 ;
@@ -9361,6 +9421,7 @@ static swig_command_info swig_commands[] = {
{"freeswitchc::CoreSession_tts_name_get", _wrap_CoreSession_tts_name_get},
{"freeswitchc::CoreSession_voice_name_set", _wrap_CoreSession_voice_name_set},
{"freeswitchc::CoreSession_voice_name_get", _wrap_CoreSession_voice_name_get},
{"freeswitchc::CoreSession_insertFile", _wrap_CoreSession_insertFile},
{"freeswitchc::CoreSession_answer", _wrap_CoreSession_answer},
{"freeswitchc::CoreSession_preAnswer", _wrap_CoreSession_preAnswer},
{"freeswitchc::CoreSession_hangup", _wrap_CoreSession_hangup},
@@ -263,6 +263,7 @@ class CoreSession(_object):
__swig_setmethods__["voice_name"] = _freeswitch.CoreSession_voice_name_set
__swig_getmethods__["voice_name"] = _freeswitch.CoreSession_voice_name_get
if _newclass:voice_name = _swig_property(_freeswitch.CoreSession_voice_name_get, _freeswitch.CoreSession_voice_name_set)
def insertFile(*args): return _freeswitch.CoreSession_insertFile(*args)
def answer(*args): return _freeswitch.CoreSession_answer(*args)
def preAnswer(*args): return _freeswitch.CoreSession_preAnswer(*args)
def hangup(*args): return _freeswitch.CoreSession_hangup(*args)
@@ -5892,6 +5892,61 @@ fail:
}
SWIGINTERN PyObject *_wrap_CoreSession_insertFile(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
CoreSession *arg1 = (CoreSession *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
int arg4 ;
int result;
void *argp1 = 0 ;
int res1 = 0 ;
int res2 ;
char *buf2 = 0 ;
int alloc2 = 0 ;
int res3 ;
char *buf3 = 0 ;
int alloc3 = 0 ;
int val4 ;
int ecode4 = 0 ;
PyObject * obj0 = 0 ;
PyObject * obj1 = 0 ;
PyObject * obj2 = 0 ;
PyObject * obj3 = 0 ;
if (!PyArg_ParseTuple(args,(char *)"OOOO:CoreSession_insertFile",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CoreSession, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_insertFile" "', argument " "1"" of type '" "CoreSession *""'");
}
arg1 = reinterpret_cast< CoreSession * >(argp1);
res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "CoreSession_insertFile" "', argument " "2"" of type '" "char const *""'");
}
arg2 = reinterpret_cast< char * >(buf2);
res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
if (!SWIG_IsOK(res3)) {
SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "CoreSession_insertFile" "', argument " "3"" of type '" "char const *""'");
}
arg3 = reinterpret_cast< char * >(buf3);
ecode4 = SWIG_AsVal_int(obj3, &val4);
if (!SWIG_IsOK(ecode4)) {
SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "CoreSession_insertFile" "', argument " "4"" of type '" "int""'");
}
arg4 = static_cast< int >(val4);
result = (int)(arg1)->insertFile((char const *)arg2,(char const *)arg3,arg4);
resultobj = SWIG_From_int(static_cast< int >(result));
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
return resultobj;
fail:
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
return NULL;
}
SWIGINTERN PyObject *_wrap_CoreSession_answer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
CoreSession *arg1 = (CoreSession *) 0 ;
@@ -8915,6 +8970,7 @@ static PyMethodDef SwigMethods[] = {
{ (char *)"CoreSession_tts_name_get", _wrap_CoreSession_tts_name_get, METH_VARARGS, NULL},
{ (char *)"CoreSession_voice_name_set", _wrap_CoreSession_voice_name_set, METH_VARARGS, NULL},
{ (char *)"CoreSession_voice_name_get", _wrap_CoreSession_voice_name_get, METH_VARARGS, NULL},
{ (char *)"CoreSession_insertFile", _wrap_CoreSession_insertFile, METH_VARARGS, NULL},
{ (char *)"CoreSession_answer", _wrap_CoreSession_answer, METH_VARARGS, NULL},
{ (char *)"CoreSession_preAnswer", _wrap_CoreSession_preAnswer, METH_VARARGS, NULL},
{ (char *)"CoreSession_hangup", _wrap_CoreSession_hangup, METH_VARARGS, NULL},
+9 -3
View File
@@ -39,8 +39,9 @@
*
* Anthony Minessale II <anthm@freeswitch.org>
* Michael B. Murdock <mike@mmurdock.org>
* François Delawarde <fdelawarde@wirelessmundi.com>
*
* mod_say_es.c -- Say for English
* mod_say_es.c -- Say for Spanish
*
*/
@@ -102,7 +103,7 @@ static switch_status_t play_group(switch_say_method_t method, int a, int b, int
break;
default:
say_file("digits/%d.wav", a);
say_file("digits/hundred.wav");
say_file("digits/hundreds.wav");
break;
}
}
@@ -175,7 +176,12 @@ static switch_status_t es_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) {
/* specific case, one million => un millón */
if (!places[8] && !places[7] && (places[6] == 1)) {
say_file("digits/un.wav");
say_file("digits/million.wav");
}
else if ((status = play_group(SSM_PRONOUNCED, places[8], places[7], places[6], "digits/millions.wav", session, args)) != 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) {
+2
View File
@@ -0,0 +1,2 @@
BASE=../../../..
include $(BASE)/build/modmake.rules
@@ -0,0 +1,283 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="mod_say_pt"
ProjectGUID="{7C22BDFF-CC09-400C-8A09-660733980028}"
RootNamespace="mod_say_pt"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
ConfigurationType="2"
InheritedPropertySheets="..\..\..\..\w32\module_debug.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
ConfigurationType="2"
InheritedPropertySheets="..\..\..\..\w32\module_debug.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(SolutionDir)$(PlatformName)\$(ConfigurationName)/mod/$(ProjectName).dll"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
ConfigurationType="2"
InheritedPropertySheets="..\..\..\..\w32\module_release.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
ConfigurationType="2"
InheritedPropertySheets="..\..\..\..\w32\module_release.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(SolutionDir)$(PlatformName)\$(ConfigurationName)/mod/$(ProjectName).dll"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\mod_say_pt.c"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>mod_say_pt</ProjectName>
<ProjectGuid>{7C22BDFF-CC09-400C-8A09-660733980028}</ProjectGuid>
<RootNamespace>mod_say_pt</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_release.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_debug.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_release.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_debug.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="mod_say_pt.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj">
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+548
View File
@@ -0,0 +1,548 @@
/*
* Copyright (c) 2007, Anthony Minessale II
* 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 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>
* Michael B. Murdock <mike@mmurdock.org>
* António Silva <asilva@wirelessmundi.com>
*
* mod_say_pt.c -- Say for Portuguese
*
*/
#include <switch.h>
#include <math.h>
#include <ctype.h>
SWITCH_MODULE_LOAD_FUNCTION(mod_say_pt_load);
SWITCH_MODULE_DEFINITION(mod_say_pt, mod_say_pt_load, NULL, NULL);
#define say_num(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 = \
pt_say_general_count(session, tmp, say_args, args)) \
!= SWITCH_STATUS_SUCCESS) { \
return tstatus; \
} \
say_args->method = smeth; say_args->type = stype; \
} \
#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)
{
/*a => 1xx-9xx*/
if (a) {
switch (a) {
case 1:
if (b || c) {
say_file("digits/hundred.wav");
} else {
say_file("digits/100.wav");
}
break;
case 2:
say_file("digits/200.wav");
break;
case 3:
say_file("digits/300.wav");
break;
case 5:
say_file("digits/500.wav");
break;
default:
say_file("digits/%d.wav", a);
say_file("digits/hundreds.wav");
break;
}
if (b || c) {
say_file("currency/and.wav");
}
}
/* b => 1x - 9x */
if (b) {
if (b > 1) {
if (method == SSM_COUNTED) {
say_file("digits/h-%d0.wav", b);
} else {
say_file("digits/%d0.wav", b);
if (c > 0) {
say_file("currency/and.wav");
}
}
} else {
say_file("digits/%d%d.wav", b, c);
c = 0;
}
}
/* c => 0 - 9*/
if (c) {
if (method == SSM_COUNTED) {
say_file("digits/h-%d.wav", c);
} else {
say_file("digits/%d.wav", c);
}
}
if (what && (a || b || c)) {
say_file(what);
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t pt_say_general_count(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
{
int in;
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)))) {
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))) || strlen(tosay) > 9) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
in = 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:
case SSM_PRONOUNCED:
/* specific case, one million => um milhão */
if (!places[8] && !places[7] && (places[6] == 1)) {
say_file("digits/1.wav");
say_file("digits/million.wav");
} else if ((status = play_group(SSM_PRONOUNCED, places[8], places[7], places[6], "digits/millions.wav", session, args)) != 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) {
return status;
}
if ((status = play_group(say_args->method, places[2], places[1], places[0], NULL, session, args)) != SWITCH_STATUS_SUCCESS) {
return status;
}
break;
default:
break;
}
} else {
say_file("digits/0.wav");
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t pt_say_time(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *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");
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 = switch_core_session_strdup(session, 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);
}
}
} 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;
}
}
if (hours) {
say_num(hours, SSM_PRONOUNCED);
if (hours == 1) {
say_file("time/hour.wav");
} else {
say_file("time/hours.wav");
}
} else {
say_file("digits/0.wav");
say_file("time/hours.wav");
}
if (minutes) {
say_num(minutes, SSM_PRONOUNCED);
if (minutes == 1) {
say_file("time/minute.wav");
} else {
say_file("time/minutes.wav");
}
} else {
say_file("digits/0.wav");
say_file("time/minutes.wav");
}
if (seconds) {
say_num(seconds, SSM_PRONOUNCED);
if (seconds == 1) {
say_file("time/second.wav");
} else {
say_file("time/seconds.wav");
}
} else {
say_file("digits/0.wav");
say_file("time/seconds.wav");
}
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_SESSION_LOG(session), 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) {
say_file("time/today.wav");
}
if (say_yesterday) {
say_file("time/yesterday.wav");
}
if (say_dow) {
say_file("time/day-%d.wav", tm.tm_wday);
}
if (say_date) {
say_year = say_month = say_day = say_dow = 1;
say_today = say_yesterday = 0;
}
if (say_month) {
say_file("time/mon-%d.wav", tm.tm_mon);
}
if (say_day) {
say_num(tm.tm_mday, SSM_COUNTED);
}
if (say_year) {
say_num(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) {
if (hour == 1) {
say_file("time/at.wav");
} else {
say_file("time/ats.wav");
}
}
if (hour > 12) {
hour -= 12;
pm = 1;
} else if (hour == 12) {
pm = 1;
} else if (hour == 0) {
hour = 12;
pm = 0;
}
say_num(hour, SSM_PRONOUNCED);
if (tm.tm_min) {
say_file("currency/and.wav");
say_num(tm.tm_min, SSM_PRONOUNCED);
} else {
say_file("time/oclock.wav");
}
say_file("time/%s.wav", pm ? "p-m" : "a-m");
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t pt_say_money(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *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)))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n");
return SWITCH_STATUS_GENERR;
}
dollars = sbuf;
if ((cents = strchr(sbuf, '.'))) {
*cents++ = '\0';
if (strlen(cents) > 2) {
cents[2] = '\0';
}
}
/* If positive sign - skip over" */
if (sbuf[0] == '+') {
dollars++;
}
/* If negative say "negative" */
if (sbuf[0] == '-') {
say_file("currency/negative.wav");
dollars++;
}
/* Say dollar amount */
pt_say_general_count(session, dollars, say_args, args);
if (atoi(dollars) == 1) {
say_file("currency/dollar.wav");
} else {
say_file("currency/dollars.wav");
}
/* Say "and" */
say_file("currency/and.wav");
/* Say cents */
if (cents) {
pt_say_general_count(session, cents, say_args, args);
if (atoi(cents) == 1) {
say_file("currency/cent.wav");
} else {
say_file("currency/cents.wav");
}
} else {
say_file("digits/0.wav");
say_file("currency/cents.wav");
}
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t pt_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;
switch (say_args->type) {
case SST_NUMBER:
case SST_ITEMS:
case SST_PERSONS:
case SST_MESSAGES:
say_cb = pt_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 = pt_say_time;
break;
case SST_IP_ADDRESS:
return switch_ivr_say_ip(session, tosay, pt_say_general_count, say_args, args);
break;
case SST_NAME_SPELLED:
case SST_NAME_PHONETIC:
return switch_ivr_say_spell(session, tosay, say_args, args);
break;
case SST_CURRENCY:
say_cb = pt_say_money;
break;
default:
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;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_say_pt_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 = "pt";
say_interface->say_function = pt_say;
/* 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:
*/
+51
View File
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="mod_say_pt"
ProjectGUID="{7C22BDFF-CC09-400C-8A09-660733980028}"
RootNamespace="mod_say_pt"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
ConfigurationType="2"
InheritedPropertySheets="..\..\..\..\w32\module_debug.vsprops"
CharacterSet="2"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</Configuration>
<Configuration
Name="Release|Win32"
ConfigurationType="2"
InheritedPropertySheets="..\..\..\..\w32\module_release.vsprops"
CharacterSet="2"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\mod_say_pt.c"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
+22
View File
@@ -742,6 +742,28 @@ SWITCH_DECLARE(switch_status_t) switch_socket_recv(switch_socket_t *sock, char *
return apr_socket_recv(sock, buf, len);
}
SWITCH_DECLARE(switch_status_t) switch_sockaddr_create(switch_sockaddr_t **sa, switch_memory_pool_t *pool)
{
switch_sockaddr_t *new_sa;
unsigned short family = APR_INET;
new_sa = apr_pcalloc(pool, sizeof(apr_sockaddr_t));
switch_assert(new_sa);
new_sa->pool = pool;
memset(new_sa, 0, sizeof(new_sa));
new_sa->family = family;
new_sa->sa.sin.sin_family = family;
new_sa->salen = sizeof(struct sockaddr_in);
new_sa->addr_str_len = 16;
new_sa->ipaddr_ptr = &(new_sa->sa.sin.sin_addr);
new_sa->ipaddr_len = sizeof(struct in_addr);
*sa = new_sa;
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_sockaddr_info_get(switch_sockaddr_t ** sa, const char *hostname, int32_t family,
switch_port_t port, int32_t flags, switch_memory_pool_t *pool)
{
+41 -3
View File
@@ -2382,10 +2382,48 @@ SWITCH_DECLARE(switch_status_t) switch_channel_caller_extension_masquerade(switc
return status;
}
SWITCH_DECLARE(void) switch_channel_sort_cid(switch_channel_t *channel, switch_bool_t in)
{
if (in) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !switch_channel_test_flag(channel, CF_DIALPLAN)) {
switch_channel_set_flag(channel, CF_DIALPLAN);
switch_mutex_lock(channel->profile_mutex);
if (channel->caller_profile->callee_id_name) {
switch_channel_set_variable(channel, "pre_transfer_caller_id_name", channel->caller_profile->caller_id_name);
channel->caller_profile->caller_id_name = switch_core_strdup(channel->caller_profile->pool, channel->caller_profile->callee_id_name);
}
channel->caller_profile->callee_id_name = SWITCH_BLANK_STRING;
if (channel->caller_profile->callee_id_number) {
switch_channel_set_variable(channel, "pre_transfer_caller_id_number", channel->caller_profile->caller_id_number);
channel->caller_profile->caller_id_number = switch_core_strdup(channel->caller_profile->pool, channel->caller_profile->callee_id_number);
}
channel->caller_profile->callee_id_number = SWITCH_BLANK_STRING;
switch_mutex_unlock(channel->profile_mutex);
}
return;
}
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_test_flag(channel, CF_DIALPLAN)) {
switch_channel_clear_flag(channel, CF_DIALPLAN);
switch_mutex_lock(channel->profile_mutex);
channel->caller_profile->callee_id_name = SWITCH_BLANK_STRING;
channel->caller_profile->callee_id_number = SWITCH_BLANK_STRING;
switch_mutex_unlock(channel->profile_mutex);
}
}
SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension)
{
switch_assert(channel != NULL);
switch_channel_sort_cid(channel, SWITCH_TRUE);
switch_mutex_lock(channel->profile_mutex);
caller_extension->next = channel->caller_profile->caller_extension;
channel->caller_profile->caller_extension = caller_extension;
@@ -2622,7 +2660,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_pre_answer(switch_channel
return SWITCH_STATUS_SUCCESS;
}
if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
msg.message_id = SWITCH_MESSAGE_INDICATE_PROGRESS;
msg.from = channel->name;
status = switch_core_session_perform_receive_message(channel->session, &msg, file, func, line);
@@ -2657,7 +2695,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_ring_ready_value(switch_c
return SWITCH_STATUS_SUCCESS;
}
if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
msg.message_id = SWITCH_MESSAGE_INDICATE_RINGING;
msg.from = channel->name;
msg.numeric_arg = rv;
@@ -2800,7 +2838,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_answer(switch_channel_t *
switch_assert(channel != NULL);
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_SUCCESS;
}
+54 -11
View File
@@ -235,7 +235,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
if (switch_test_flag(*frame, SFF_CNG)) {
status = SWITCH_STATUS_SUCCESS;
if (!session->bugs) {
if (!session->bugs && !session->plc) {
goto done;
}
is_cng = 1;
@@ -303,7 +303,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
session->raw_read_frame.datalen = session->raw_read_frame.buflen;
if (is_cng) {
memset(session->raw_read_frame.data, 255, read_frame->codec->implementation->decoded_bytes_per_packet);
if (session->plc) {
plc_fillin(session->plc, session->raw_read_frame.data, read_frame->codec->implementation->decoded_bytes_per_packet / 2);
is_cng = 0;
flag &= !SFF_CNG;
} else {
memset(session->raw_read_frame.data, 255, read_frame->codec->implementation->decoded_bytes_per_packet);
}
session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet;
session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t);
read_frame = &session->raw_read_frame;
@@ -319,13 +325,38 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
switch_thread_rwlock_unlock(session->bug_rwlock);
}
status = switch_core_codec_decode(use_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);
if (switch_test_flag(read_frame, SFF_PLC)) {
session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet;
session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t);
memset(session->raw_read_frame.data, 255, session->raw_read_frame.datalen);
status = SWITCH_STATUS_SUCCESS;
} else {
status = switch_core_codec_decode(use_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);
}
if (status == SWITCH_STATUS_SUCCESS) {
if ((switch_channel_test_flag(session->channel, CF_JITTERBUFFER) || switch_channel_test_flag(session->channel, CF_CNG_PLC))
&& !session->plc) {
session->plc = plc_init(NULL);
}
if (session->plc) {
if (switch_test_flag(read_frame, SFF_PLC)) {
plc_fillin(session->plc, session->raw_read_frame.data, session->raw_read_frame.datalen / 2);
switch_clear_flag(read_frame, SFF_PLC);
} else {
plc_rx(session->plc, session->raw_read_frame.data, session->raw_read_frame.datalen / 2);
}
}
}
}
if (do_resample && ((status == SWITCH_STATUS_SUCCESS) || is_cng)) {
@@ -361,6 +392,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
session->raw_read_frame.seq = read_frame->seq;
session->raw_read_frame.m = read_frame->m;
session->raw_read_frame.payload = read_frame->payload;
session->raw_read_frame.flags = 0;
if (switch_test_flag(read_frame, SFF_PLC)) {
session->raw_read_frame.flags |= SFF_PLC;
}
read_frame = &session->raw_read_frame;
break;
case SWITCH_STATUS_NOOP:
@@ -383,6 +418,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
session->raw_read_frame.seq = read_frame->seq;
session->raw_read_frame.m = read_frame->m;
session->raw_read_frame.payload = read_frame->payload;
session->raw_read_frame.flags = 0;
if (switch_test_flag(read_frame, SFF_PLC)) {
session->raw_read_frame.flags |= SFF_PLC;
}
read_frame = &session->raw_read_frame;
status = SWITCH_STATUS_SUCCESS;
break;
@@ -462,7 +502,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
read_frame->datalen = session->read_resampler->to_len * 2;
read_frame->rate = session->read_resampler->to_rate;
switch_mutex_unlock(session->resample_mutex);
}
if (read_frame->datalen == session->read_impl.decoded_bytes_per_packet) {
@@ -481,7 +520,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
}
}
if (perfect || switch_buffer_inuse(session->raw_read_buffer) >= session->read_impl.decoded_bytes_per_packet) {
if (perfect) {
enc_frame = read_frame;
@@ -810,6 +848,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
session->raw_write_frame.ssrc = frame->ssrc;
session->raw_write_frame.seq = frame->seq;
session->raw_write_frame.payload = frame->payload;
session->raw_write_frame.flags = 0;
if (switch_test_flag(frame, SFF_PLC)) {
session->raw_write_frame.flags |= SFF_PLC;
}
write_frame = &session->raw_write_frame;
break;
case SWITCH_STATUS_BREAK:
+26
View File
@@ -392,6 +392,32 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_flush_all(switch_core_sess
return SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_enumerate(switch_core_session_t *session, switch_stream_handle_t *stream)
{
switch_media_bug_t *bp;
stream->write_function(stream, "<media-bugs>\n");
if (session->bugs) {
switch_thread_rwlock_wrlock(session->bug_rwlock);
for (bp = session->bugs; bp; bp = bp->next) {
int thread_locked = (bp->thread_id && bp->thread_id == switch_thread_self());
stream->write_function(stream,
" <media-bug>\n"
" <function>%s</function>\n"
" <target>%s</target>\n"
" <thread-locked>%d</thread-locked>\n"
" </media-bug>\n",
bp->function, bp->target, thread_locked);
}
switch_thread_rwlock_unlock(session->bug_rwlock);
}
stream->write_function(stream, "</media-bugs>\n");
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_all(switch_core_session_t *session)
{
+22 -3
View File
@@ -1118,6 +1118,11 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t *
}
switch_mutex_unlock(runtime.session_hash_mutex);
if ((*session)->plc) {
plc_free((*session)->plc);
(*session)->plc = NULL;
}
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DESTROY) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data((*session)->channel, event);
switch_event_fire(&event);
@@ -1836,6 +1841,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_async(sw
switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", arg);
}
if (!switch_channel_test_flag(session->channel, CF_PROXY_MODE)) {
switch_channel_set_flag(session->channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA);
}
switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true");
switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE);
@@ -1886,9 +1895,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flag
switch_goto_status(SWITCH_STATUS_FALSE, done);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"Cannot execute app '%s' media required on an outbound channel that does not have media established\n", app);
switch_goto_status(SWITCH_STATUS_FALSE, done);
uint32_t ready = 0, sanity = 2000;
do {
sanity--;
ready = switch_channel_media_ready(session->channel);
switch_cond_next();
} while(!ready && sanity);
if (!ready) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"Cannot execute app '%s' media required on an outbound channel that does not have media established\n", app);
switch_goto_status(SWITCH_STATUS_FALSE, done);
}
}
}
+1
View File
@@ -1624,6 +1624,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_
runtime.odbc_dsn = NULL;
runtime.odbc_user = NULL;
runtime.odbc_pass = NULL;
runtime.odbc_dbtype = DBTYPE_DEFAULT;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Falling back to core_db.\n");
goto top;
}
+1 -1
View File
@@ -124,7 +124,7 @@ static void switch_core_standard_on_routing(switch_core_session_t *session)
}
if (!count) {
if (switch_channel_test_flag(session->channel, CF_OUTBOUND)) {
if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
if (switch_channel_test_flag(session->channel, CF_ANSWERED)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"No Dialplan on answered channel, changing state to HANGUP\n");
+10 -1
View File
@@ -576,6 +576,15 @@ SWITCH_DECLARE(int) CoreSession::answer()
return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
}
SWITCH_DECLARE(int) CoreSession::insertFile(const char *file, const char *insert_file, int sample_point)
{
switch_status_t status;
this_check(-1);
sanity_check(-1);
status = switch_ivr_insert_file(session, file, insert_file, (switch_size_t)sample_point);
return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
}
SWITCH_DECLARE(int) CoreSession::preAnswer()
{
switch_status_t status;
@@ -1206,7 +1215,7 @@ SWITCH_DECLARE(void) bridge(CoreSession &session_a, CoreSession &session_b)
if (switch_channel_ready(channel_a) && switch_channel_ready(channel_b)) {
session_a.begin_allow_threads();
if (!switch_channel_test_flag(channel_a, CF_OUTBOUND) && !switch_channel_media_ready(channel_a)) {
if (switch_channel_direction(channel_a) == SWITCH_CALL_DIRECTION_INBOUND && !switch_channel_media_ready(channel_a)) {
switch_channel_pre_answer(channel_a);
}
+1 -1
View File
@@ -339,7 +339,7 @@ static void *SWITCH_THREAD_FUNC switch_event_thread(switch_thread_t *thread, voi
launch_dispatch_threads(SOFT_MAX_DISPATCH + 1, DISPATCH_QUEUE_LEN, RUNTIME_POOL);
switch_mutex_unlock(EVENT_QUEUE_MUTEX);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Out of threads!\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Out of event dispatch threads! Slowing things down.\n");
switch_yield(1000000);
}
}
+16 -20
View File
@@ -140,7 +140,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session,
const char *var;
/*
if (!switch_channel_test_flag(channel, CF_OUTBOUND) && !switch_channel_test_flag(channel, CF_PROXY_MODE) &&
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND && !switch_channel_test_flag(channel, CF_PROXY_MODE) &&
!switch_channel_media_ready(channel) && !switch_channel_test_flag(channel, CF_SERVICE)) {
if ((status = switch_channel_pre_answer(channel)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot establish media.\n");
@@ -698,12 +698,23 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_all_messages(switch_core_sessio
SWITCH_DECLARE(switch_status_t) switch_ivr_parse_all_events(switch_core_session_t *session)
{
int x = 0;
switch_channel_t *channel;
switch_ivr_parse_all_messages(session);
while (switch_ivr_parse_next_event(session) == SWITCH_STATUS_SUCCESS)
channel = switch_core_session_get_channel(session);
if (!switch_channel_test_flag(channel, CF_PROXY_MODE) && switch_channel_test_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA)) {
if (switch_channel_media_ready(channel)) {
switch_channel_clear_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA);
} else {
return SWITCH_STATUS_SUCCESS;
}
}
while (switch_ivr_parse_next_event(session) == SWITCH_STATUS_SUCCESS) {
x++;
}
if (x) {
switch_ivr_sleep(session, 0, SWITCH_TRUE, NULL);
@@ -1544,21 +1555,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_session_transfer(switch_core_session_
new_profile->destination_number = switch_core_strdup(new_profile->pool, extension);
new_profile->rdnis = switch_core_strdup(new_profile->pool, profile->destination_number);
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
if (profile->callee_id_name) {
switch_channel_set_variable(channel, "pre_transfer_caller_id_name", new_profile->caller_id_name);
new_profile->caller_id_name = switch_core_strdup(new_profile->pool, profile->callee_id_name);
profile->callee_id_name = SWITCH_BLANK_STRING;
}
if (profile->callee_id_number) {
switch_channel_set_variable(channel, "pre_transfer_caller_id_number", new_profile->caller_id_number);
new_profile->caller_id_number = switch_core_strdup(new_profile->pool, profile->callee_id_number);
profile->callee_id_number = SWITCH_BLANK_STRING;
}
}
switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, NULL);
/* If HANGUP_AFTER_BRIDGE is set to 'true', SWITCH_SIGNAL_BRIDGE_VARIABLE
@@ -2290,7 +2286,7 @@ SWITCH_DECLARE(void) switch_ivr_delay_echo(switch_core_session_t *session, uint3
qlen = delay_ms / (interval);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setting delay to %dms (%d frames)\n", delay_ms, qlen);
jb = stfu_n_init(qlen, 0);
jb = stfu_n_init(qlen, qlen, read_impl.samples_per_packet, read_impl.samples_per_second);
write_frame.codec = switch_core_session_get_read_codec(session);
@@ -2300,7 +2296,7 @@ SWITCH_DECLARE(void) switch_ivr_delay_echo(switch_core_session_t *session, uint3
break;
}
stfu_n_eat(jb, ts, read_frame->payload, read_frame->data, read_frame->datalen);
stfu_n_eat(jb, ts, read_frame->payload, read_frame->data, read_frame->datalen, 0);
ts += interval;
if ((jb_frame = stfu_n_read_a_frame(jb))) {
+3 -4
View File
@@ -282,9 +282,10 @@ static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachin
best = DM_MATCH_EXACT;
exact_bp = bp;
if (dmachine->cur_digit_len == dmachine->max_digit_len) break;
}
}
if (!(both_bp && partial_bp) && !strncmp(dmachine->digits, bp->digits, strlen(dmachine->digits))) {
if (!(both_bp && partial_bp) && strlen(bp->digits) != strlen(dmachine->digits) &&
!strncmp(dmachine->digits, bp->digits, strlen(dmachine->digits))) {
if (exact_bp) {
best = DM_MATCH_BOTH;
both_bp = bp;
@@ -303,8 +304,6 @@ static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachin
if (is_timeout) {
if (both_bp) {
r_bp = exact_bp ? exact_bp : both_bp;
} else if (partial_bp) {
r_bp = partial_bp;
}
}
+3 -3
View File
@@ -100,7 +100,7 @@ static void send_display(switch_core_session_t *session, switch_core_session_t *
caller_channel = switch_core_session_get_channel(session);
caller_profile = switch_channel_get_caller_profile(caller_channel);
if (switch_channel_direction(caller_channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
if (switch_channel_direction(caller_channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !switch_channel_test_flag(caller_channel, CF_DIALPLAN)) {
name = caller_profile->callee_id_name;
number = caller_profile->callee_id_number;
@@ -435,8 +435,8 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
switch_channel_t *un = ans_a ? chan_b : chan_a;
switch_channel_t *a = un == chan_b ? chan_a : chan_b;
if (!switch_channel_test_flag(un, CF_OUTBOUND)) {
if (switch_channel_test_flag(a, CF_OUTBOUND) || (un == chan_a && !originator)) {
if (switch_channel_direction(un) == SWITCH_CALL_DIRECTION_INBOUND) {
if (switch_channel_direction(a) == SWITCH_CALL_DIRECTION_OUTBOUND || (un == chan_a && !originator)) {
switch_channel_pass_callee_id(a, un);
}
+18 -24
View File
@@ -384,8 +384,9 @@ static void inherit_codec(switch_channel_t *caller_channel, switch_core_session_
switch_codec_implementation_t video_impl = { 0 };
char tmp[128] = "";
if (switch_core_session_get_read_impl(session, &impl) == SWITCH_STATUS_SUCCESS) {
const char *ep = switch_channel_get_variable(caller_channel, "ep_codec_string");
if (switch_core_session_get_video_read_impl(session, &video_impl) == SWITCH_STATUS_SUCCESS) {
switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui,%s",
impl.iananame, impl.samples_per_second, impl.microseconds_per_packet / 1000,
@@ -394,9 +395,15 @@ static void inherit_codec(switch_channel_t *caller_channel, switch_core_session_
switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui",
impl.iananame, impl.samples_per_second, impl.microseconds_per_packet / 1000);
}
switch_channel_set_variable(caller_channel, "absolute_codec_string", tmp);
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(caller_channel), SWITCH_LOG_DEBUG, "Setting codec string on %s to %s\n",
switch_channel_get_name(caller_channel), tmp);
if (ep && switch_stristr(impl.iananame, ep)) {
switch_channel_set_variable(caller_channel, "absolute_codec_string", tmp);
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(caller_channel), SWITCH_LOG_DEBUG, "Setting codec string on %s to %s\n",
switch_channel_get_name(caller_channel), tmp);
} else {
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(caller_channel), SWITCH_LOG_DEBUG, "Codec string %s not supported on %s, skipping inheritance\n",
tmp, switch_channel_get_name(caller_channel));
}
} else {
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(caller_channel), SWITCH_LOG_WARNING,
"Error inheriting codec. Channel %s has no read codec yet.\n",
@@ -488,7 +495,7 @@ static uint8_t check_channel_status(originate_global_t *oglobals, originate_stat
pindex = (uint32_t) i;
} else if (!oglobals->sent_ring && oglobals->ignore_early_media == 2 && len == 1 && caller_channel && !oglobals->ignore_ring_ready) {
switch_channel_pass_callee_id(originate_status[0].peer_channel, caller_channel);
//switch_channel_ring_ready(caller_channel);
switch_channel_ring_ready(caller_channel);
oglobals->sent_ring = 1;
}
@@ -1751,6 +1758,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
early_state_t early_state = { 0 };
int read_packet = 0;
int check_reject = 1;
switch_codec_implementation_t read_impl = { 0 };
if (strstr(bridgeto, SWITCH_ENT_ORIGINATE_DELIM)) {
return switch_ivr_enterprise_originate(session, bleg, cause, bridgeto, timelimit_sec, table, cid_name_override, cid_num_override,
@@ -1777,6 +1785,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
switch_channel_set_flag(caller_channel, CF_ORIGINATOR);
oglobals.session = session;
switch_core_session_get_read_impl(session, &read_impl);
if ((to_var = switch_channel_get_variable(caller_channel, SWITCH_CALL_TIMEOUT_VARIABLE))) {
timelimit_sec = atoi(to_var);
@@ -2381,24 +2390,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
new_profile->chan_name = SWITCH_BLANK_STRING;
new_profile->destination_number = switch_core_strdup(new_profile->pool, chan_data);
if (switch_channel_direction(caller_channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
const char *callee_id_name = new_profile->callee_id_name;
const char *callee_id_number = new_profile->callee_id_number;
if (zstr(callee_id_number)) {
callee_id_number = caller_caller_profile->destination_number;
}
if (zstr(callee_id_name)) {
callee_id_name = callee_id_number;
}
new_profile->caller_id_name = callee_id_name;
new_profile->caller_id_number = callee_id_number;
new_profile->callee_id_name = SWITCH_BLANK_STRING;
new_profile->callee_id_number = SWITCH_BLANK_STRING;
}
if (cid_name_override) {
new_profile->caller_id_name = switch_core_strdup(new_profile->pool, cid_name_override);
}
@@ -2426,6 +2417,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
}
}
new_profile->callee_id_name = switch_core_strdup(new_profile->pool, "Outbound Call");
new_profile->callee_id_number = switch_core_strdup(new_profile->pool, new_profile->destination_number);
originate_status[i].caller_profile = NULL;
originate_status[i].peer_channel = NULL;
originate_status[i].peer_session = NULL;
@@ -3066,7 +3060,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
if ((ringback.fh || silence || ringback.audio_buffer || oglobals.bridge_early_media > -1) && write_frame.codec && write_frame.datalen) {
if (silence) {
write_frame.datalen = write_frame.codec->implementation->decoded_bytes_per_packet;
write_frame.datalen = read_impl.decoded_bytes_per_packet;
switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.datalen / 2, silence);
}
+12 -3
View File
@@ -1573,10 +1573,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "done playing file\n");
if (read_impl.samples_per_second) {
switch_channel_set_variable_printf(channel, "playback_seconds", "%d", fh->samples_out / read_impl.samples_per_second);
switch_channel_set_variable_printf(channel, "playback_ms", "%d", fh->samples_out / (read_impl.samples_per_second / 1000));
switch_channel_set_variable_printf(channel, "playback_seconds", "%d", fh->samples_in / read_impl.samples_per_second);
switch_channel_set_variable_printf(channel, "playback_ms", "%d", fh->samples_in / (read_impl.samples_per_second / 1000));
}
switch_channel_set_variable_printf(channel, "playback_samples", "%d", fh->samples_out);
switch_channel_set_variable_printf(channel, "playback_samples", "%d", fh->samples_in);
switch_core_session_io_write_lock(session);
switch_channel_set_private(channel, "__fh", NULL);
@@ -1761,6 +1761,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_read(switch_core_session_t *session,
switch_assert(session);
if (!digit_timeout) {
digit_timeout = timeout;
}
if (max_digits < min_digits) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"Max digits %u is less than Min %u, forcing Max to %u\n", max_digits, min_digits, min_digits);
@@ -1870,6 +1874,11 @@ SWITCH_DECLARE(switch_status_t) switch_play_and_get_digits(switch_core_session_t
status = SWITCH_STATUS_SUCCESS;
}
if ((min_digits == 0) && (strlen(digit_buffer) == 0) && switch_channel_get_variable(channel, SWITCH_READ_TERMINATOR_USED_VARIABLE) != 0)
{
return SWITCH_STATUS_SUCCESS;
}
if (!(status == SWITCH_STATUS_TOO_SMALL && strlen(digit_buffer) == 0)) {
if (status == SWITCH_STATUS_SUCCESS) {
if (!zstr(digit_buffer)) {
+131 -18
View File
@@ -174,6 +174,8 @@ struct switch_rtp {
void *private_data;
uint32_t ts;
uint32_t last_write_ts;
uint32_t last_read_ts;
uint32_t last_cng_ts;
uint32_t last_write_samplecount;
uint32_t next_write_samplecount;
switch_time_t last_write_timestamp;
@@ -229,7 +231,7 @@ struct switch_rtp {
uint32_t sync_packets;
int rtcp_interval;
switch_bool_t rtcp_fresh_frame;
uint8_t checked_jb;
#ifdef ENABLE_ZRTP
zrtp_session_t *zrtp_session;
zrtp_profile_t *zrtp_profile;
@@ -1367,9 +1369,10 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
switch_rtp_set_flag(rtp_session, flags);
/* for from address on recvfrom calls */
switch_sockaddr_info_get(&rtp_session->from_addr, NULL, SWITCH_UNSPEC, 0, 0, pool);
switch_sockaddr_create(&rtp_session->from_addr, pool);
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP)) {
switch_sockaddr_info_get(&rtp_session->rtcp_from_addr, NULL, SWITCH_UNSPEC, 0, 0, pool);
switch_sockaddr_create(&rtp_session->rtcp_from_addr, pool);
}
rtp_session->seq = (uint16_t) rand();
rtp_session->ssrc = (uint32_t) ((intptr_t) rtp_session + (uint32_t) switch_epoch_time_now(NULL));
@@ -1618,14 +1621,94 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_stun_ping(switch_rtp_t *rtp_
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *rtp_session, uint32_t queue_frames)
static void jb_callback(stfu_instance_t *i, void *udata)
{
switch_core_session_t *session = (switch_core_session_t *) udata;
stfu_report_t r = { 0 };
stfu_n_report(i, &r);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1,
"%s JB REPORT:\nlen: %u\nin: %u\nclean: %u\ngood: %u\nbad: %u\n",
switch_core_session_get_name(session),
r.qlen,
r.packet_in_count,
r.clean_count,
r.consecutive_good_count,
r.consecutive_bad_count
);
}
SWITCH_DECLARE(switch_status_t) switch_rtp_deactivate_jitter_buffer(switch_rtp_t *rtp_session)
{
if (!switch_rtp_ready(rtp_session) || !rtp_session->jb) {
return SWITCH_STATUS_FALSE;
}
READ_INC(rtp_session);
stfu_n_destroy(&rtp_session->jb);
READ_DEC(rtp_session);
return SWITCH_STATUS_SUCCESS;
}
static void jb_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
{
int ret;
char *data;
va_list ap;
va_start(ap, fmt);
ret = switch_vasprintf(&data, fmt, ap);
if (ret != -1) {
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_CONSOLE, "%s", data);
free(data);
}
//switch_log_printf(SWITCH_CHANNEL_ID_LOG_CLEAN, file, func, line, NULL, level, fmt, ap);
va_end(ap);
}
SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name)
{
rtp_session->jb = stfu_n_init(queue_frames, 0);
stfu_n_debug(rtp_session->jb, name);
stfu_global_set_logger(jb_logger);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *rtp_session,
uint32_t queue_frames,
uint32_t max_queue_frames,
uint32_t samples_per_packet,
uint32_t samples_per_second)
{
if (!switch_rtp_ready(rtp_session)) {
return SWITCH_STATUS_FALSE;
}
READ_INC(rtp_session);
if (rtp_session->jb) {
stfu_n_resize(rtp_session->jb, queue_frames);
} else {
rtp_session->jb = stfu_n_init(queue_frames, max_queue_frames ? max_queue_frames : 50, samples_per_packet, samples_per_second);
}
READ_DEC(rtp_session);
if (rtp_session->jb) {
switch_core_session_t *session = switch_core_memory_pool_get_data(rtp_session->pool, "__session");
stfu_n_call_me(rtp_session->jb, jb_callback, session);
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(switch_status_t) switch_rtp_activate_rtcp(switch_rtp_t *rtp_session, int send_rate, switch_port_t remote_port)
{
const char *err = NULL;
@@ -2016,14 +2099,18 @@ static void do_flush(switch_rtp_t *rtp_session)
switch_size_t bytes;
switch_status_t status;
if (!switch_rtp_ready(rtp_session) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA)) {
if (!switch_rtp_ready(rtp_session) ||
switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) ||
switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)
) {
return;
}
READ_INC(rtp_session);
if (switch_rtp_ready(rtp_session)) {
uint32_t flushed = 0;
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_DEBUG_RTP_READ)) {
switch_core_session_t *session = switch_core_memory_pool_get_data(rtp_session->pool, "__session");
if (!session) {
@@ -2047,6 +2134,9 @@ static void do_flush(switch_rtp_t *rtp_session)
bytes = sizeof(rtp_msg_t);
status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, &bytes);
if (bytes) {
flushed++;
rtp_session->stats.inbound.raw_bytes += bytes;
rtp_session->stats.inbound.flush_packet_count++;
rtp_session->stats.inbound.packet_count++;
@@ -2056,6 +2146,10 @@ static void do_flush(switch_rtp_t *rtp_session)
}
} while (bytes > 0);
if (rtp_session->jb && flushed) {
stfu_n_sync(rtp_session->jb, flushed);
}
if (was_blocking && switch_rtp_ready(rtp_session)) {
switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
switch_socket_opt_set(rtp_session->sock_input, SWITCH_SO_NONBLOCK, FALSE);
@@ -2071,11 +2165,20 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
{
switch_status_t status = SWITCH_STATUS_FALSE;
stfu_frame_t *jb_frame;
uint32_t ts;
switch_assert(bytes);
*bytes = sizeof(rtp_msg_t);
status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, bytes);
ts = ntohl(rtp_session->recv_msg.header.ts);
if (*bytes && (!rtp_session->recv_te || rtp_session->recv_msg.header.pt != rtp_session->recv_te) &&
ts && !rtp_session->jb && ts == rtp_session->last_cng_ts) {
/* we already sent this frame..... */
*bytes = 0;
return SWITCH_STATUS_SUCCESS;
}
if (*bytes) {
rtp_session->stats.inbound.raw_bytes += *bytes;
@@ -2091,12 +2194,15 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
rtp_session->stats.inbound.packet_count++;
}
if ((rtp_session->recv_te && rtp_session->recv_msg.header.pt == rtp_session->recv_te) ||
*bytes < rtp_header_len ||
(*bytes < rtp_header_len && *bytes > 0) ||
switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL)) {
return SWITCH_STATUS_SUCCESS;
}
rtp_session->last_read_ts = ts;
if (rtp_session->jb && rtp_session->recv_msg.header.version == 2 && *bytes) {
if (rtp_session->recv_msg.header.m && rtp_session->recv_msg.header.pt != rtp_session->recv_te &&
@@ -2104,26 +2210,29 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
stfu_n_reset(rtp_session->jb);
}
stfu_n_eat(rtp_session->jb, ntohl(rtp_session->recv_msg.header.ts), rtp_session->recv_msg.header.pt,
rtp_session->recv_msg.body, *bytes - rtp_header_len);
stfu_n_eat(rtp_session->jb, rtp_session->last_read_ts,
rtp_session->recv_msg.header.pt,
rtp_session->recv_msg.body, *bytes - rtp_header_len, rtp_session->timer.samplecount);
*bytes = 0;
status = SWITCH_STATUS_FALSE;
}
if (rtp_session->jb) {
if (rtp_session->jb && !rtp_session->checked_jb) {
if ((jb_frame = stfu_n_read_a_frame(rtp_session->jb))) {
memcpy(rtp_session->recv_msg.body, jb_frame->data, jb_frame->dlen);
if (jb_frame->plc) {
*flags |= SFF_PLC;
(*flags) |= SFF_PLC;
} else {
rtp_session->stats.inbound.jb_packet_count++;
}
*bytes = jb_frame->dlen + rtp_header_len;
rtp_session->recv_msg.header.ts = htonl(jb_frame->ts);
rtp_session->recv_msg.header.pt = jb_frame->pt;
status = SWITCH_STATUS_SUCCESS;
}
rtp_session->checked_jb++;
}
return status;
@@ -2268,6 +2377,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
READ_INC(rtp_session);
rtp_session->checked_jb = 0;
while (switch_rtp_ready(rtp_session)) {
int do_cng = 0;
bytes = 0;
@@ -2277,7 +2388,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
rtp_session->read_pollfd) {
if (switch_poll(rtp_session->read_pollfd, 1, &fdr, 0) == SWITCH_STATUS_SUCCESS) {
rtp_session->hot_hits += rtp_session->samples_per_interval;
if (rtp_session->hot_hits >= rtp_session->samples_per_second * 5) {
switch_set_flag(rtp_session, SWITCH_RTP_FLAG_FLUSH);
hot_socket = 1;
@@ -2819,10 +2930,11 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
if (do_cng) {
uint8_t *data = (uint8_t *) rtp_session->recv_msg.body;
int fdr;
if ((poll_status = switch_poll(rtp_session->read_pollfd, 1, &fdr, 0)) == SWITCH_STATUS_SUCCESS) {
goto recvfrom;
if (rtp_session->last_cng_ts == rtp_session->last_read_ts + rtp_session->samples_per_interval) {
rtp_session->last_cng_ts = 0;
} else {
rtp_session->last_cng_ts = rtp_session->last_read_ts + rtp_session->samples_per_interval;
}
memset(data, 0, 2);
@@ -3053,6 +3165,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp
frame->packet = &rtp_session->recv_msg;
frame->packetlen = bytes;
frame->source = __FILE__;
switch_set_flag(frame, SFF_RAW_RTP);
if (frame->payload == rtp_session->recv_te) {
switch_set_flag(frame, SFF_RFC2833);
+5 -1
View File
@@ -213,9 +213,13 @@ SWITCH_DECLARE(void) switch_time_calibrate_clock(void)
}
if (res > 1500) {
STEP_MS = res / 1000;
STEP_MIC = res;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Timer resolution of %ld microseconds detected!\n"
"Do you have your kernel timer frequency set to lower than 1,000Hz? You may experience audio problems.\n", ts.tv_nsec / 1000);
"Do you have your kernel timer frequency set to lower than 1,000Hz? "
"You may experience audio problems. Step MS %d\n", ts.tv_nsec / 1000, STEP_MS);
do_sleep(5000000);
switch_time_set_cond_yield(SWITCH_TRUE);
return;
+7 -3
View File
@@ -831,9 +831,9 @@ SWITCH_DECLARE(char *) switch_strip_whitespace(const char *str)
return s;
}
SWITCH_DECLARE(char *) switch_strip_spaces(const char *str)
SWITCH_DECLARE(char *) switch_strip_spaces(char *str, switch_bool_t dup)
{
const char *sp = str;
char *sp = str;
char *p, *s = NULL;
if (!sp)
@@ -843,7 +843,11 @@ SWITCH_DECLARE(char *) switch_strip_spaces(const char *str)
sp++;
}
s = strdup(sp);
if (dup) {
s = strdup(sp);
} else {
s = sp;
}
if (!s)
return NULL;