diff --git a/Freeswitch.2008.sln b/Freeswitch.2008.sln index 4ffd66abac..d60de29e54 100644 --- a/Freeswitch.2008.sln +++ b/Freeswitch.2008.sln @@ -371,6 +371,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchCoreLib", "w32\Li ProjectSection(ProjectDependencies) = postProject {8D04B550-D240-4A44-8A18-35DA3F7038D9} = {8D04B550-D240-4A44-8A18-35DA3F7038D9} {89385C74-5860-4174-9CAF-A39E7C48909C} = {89385C74-5860-4174-9CAF-A39E7C48909C} + {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5} = {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5} {F057DA7F-79E5-4B00-845C-EF446EF055E3} = {F057DA7F-79E5-4B00-845C-EF446EF055E3} {03207781-0D1C-4DB3-A71D-45C608F28DBD} = {03207781-0D1C-4DB3-A71D-45C608F28DBD} {F6C55D93-B927-4483-BB69-15AEF3DD2DFF} = {F6C55D93-B927-4483-BB69-15AEF3DD2DFF} diff --git a/Makefile.am b/Makefile.am index e701494a2e..72ad3f718c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -102,6 +102,7 @@ CORE_CFLAGS += -I$(switch_srcdir)/libs/pcre CORE_CFLAGS += -I$(switch_srcdir)/libs/speex/include -Ilibs/speex/include CORE_CFLAGS += -I$(switch_srcdir)/libs/srtp/include CORE_CFLAGS += -I$(switch_srcdir)/libs/srtp/crypto/include -Ilibs/srtp/crypto/include +CORE_CFLAGS += -I$(switch_srcdir)/libs/spandsp/src CORE_LIBS = libs/apr-util/libaprutil-1.la libs/apr/libapr-1.la CORE_LIBS += libs/sqlite/libsqlite3.la libs/pcre/libpcre.la libs/speex/libspeex/libspeexdsp.la @@ -249,7 +250,8 @@ libfreeswitch_la_SOURCES = \ libs/miniupnpc/minissdpc.c \ libs/miniupnpc/upnperrors.c \ libs/libnatpmp/natpmp.c \ - libs/libnatpmp/getgateway.c + libs/libnatpmp/getgateway.c\ + libs/spandsp/src/plc.c if ENABLE_CPP libfreeswitch_la_SOURCES += src/switch_cpp.cpp diff --git a/libs/esl/src/esl.c b/libs/esl/src/esl.c index 4a02a8fe38..ce582d3837 100644 --- a/libs/esl/src/esl.c +++ b/libs/esl/src/esl.c @@ -1177,7 +1177,6 @@ ESL_DECLARE(esl_status_t) esl_send_recv_timed(esl_handle_t *handle, const char * return ESL_FAIL; } - esl_event_safe_destroy(&handle->last_event); esl_event_safe_destroy(&handle->last_sr_event); *handle->last_sr_reply = '\0'; diff --git a/libs/freetdm/configure.gnu b/libs/freetdm/configure.gnu index 5785ffc0e7..d00cd18473 100755 --- a/libs/freetdm/configure.gnu +++ b/libs/freetdm/configure.gnu @@ -1,3 +1,3 @@ #! /bin/sh -./configure "$@" --with-pic - +srcpath=$(dirname $0 2>/dev/null ) || srcpath="." +$srcpath/configure "$@" --with-pic diff --git a/libs/freetdm/freetdm.2010.sln b/libs/freetdm/freetdm.2010.sln index f4bd907a6d..44431d675a 100644 --- a/libs/freetdm/freetdm.2010.sln +++ b/libs/freetdm/freetdm.2010.sln @@ -119,10 +119,8 @@ Global {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.ActiveCfg = Release|x64 {0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.Build.0 = Release|x64 {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.ActiveCfg = Debug|Win32 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.Build.0 = Debug|Win32 {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|x64.ActiveCfg = Debug|x64 {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.ActiveCfg = Release|Win32 - {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.Build.0 = Release|Win32 {B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|x64.ActiveCfg = Release|x64 {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.ActiveCfg = Debug|Win32 {08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|x64.ActiveCfg = Debug|x64 diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj b/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj index ec69333410..9f01a3b1a1 100644 --- a/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj +++ b/libs/freetdm/mod_freetdm/mod_freetdm.2010.vcxproj @@ -103,7 +103,7 @@ ProgramDatabase - FreeSwitchCore.lib;%(AdditionalDependencies) + FreeSwitch.lib;%(AdditionalDependencies) ../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories) true $(OutDir)$(TargetName).pdb @@ -127,7 +127,7 @@ ProgramDatabase - FreeSwitchCore.lib;%(AdditionalDependencies) + FreeSwitch.lib;%(AdditionalDependencies) ../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories) true $(OutDir)$(TargetName).pdb diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 1461499d2d..b43ca8ad6f 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -57,11 +57,14 @@ struct tm *localtime_r(const time_t *clock, struct tm *result); #define SPAN_PENDING_SIGNALS_QUEUE_SIZE 1000 #define FTDM_READ_TRACE_INDEX 0 #define FTDM_WRITE_TRACE_INDEX 1 +#define MAX_CALLIDS 6000 ftdm_time_t time_last_throttle_log = 0; ftdm_time_t time_current_throttle_log = 0; static ftdm_iterator_t *get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t *iter); +static ftdm_status_t ftdm_call_set_call_id(ftdm_caller_data_t *caller_data); +static ftdm_status_t ftdm_call_clear_call_id(ftdm_caller_data_t *caller_data); static int time_is_init = 0; @@ -235,6 +238,10 @@ static struct { ftdm_span_t *spans; ftdm_group_t *groups; cpu_monitor_t cpu_monitor; + + ftdm_caller_data_t *call_ids[MAX_CALLIDS+1]; + ftdm_mutex_t *call_id_mutex; + uint32_t last_call_id; } globals; enum ftdm_enum_cpu_alarm_action_flags @@ -1896,8 +1903,6 @@ static ftdm_status_t ftdm_channel_reset(ftdm_channel_t *ftdmchan) ftdmchan->dtmf_off = FTDM_DEFAULT_DTMF_OFF; } - ftdm_call_clear_vars(&ftdmchan->caller_data); - memset(ftdmchan->dtmf_hangup_buf, '\0', ftdmchan->span->dtmf_hangup_len); if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE)) { @@ -2483,6 +2488,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 100); + ftdm_call_set_call_id(&ftdmchan->caller_data); ftdm_channel_unlock(ftdmchan); return status; @@ -2545,9 +2551,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan) ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel can't be done!\n"); ftdm_mutex_lock(ftdmchan->mutex); - - memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data)); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_INUSE); ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND); ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_WINK); @@ -2587,7 +2590,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan) sigmsg.channel = ftdmchan; sigmsg.event_id = FTDM_SIGEVENT_RELEASED; ftdm_span_send_signal(ftdmchan->span, &sigmsg); - } + ftdm_call_clear_call_id(&ftdmchan->caller_data); + } if (ftdmchan->txdrops || ftdmchan->rxdrops) { ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "channel dropped data: txdrops = %d, rxdrops = %d\n", @@ -2595,8 +2599,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan) } ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "channel done\n"); - - + memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data)); ftdm_mutex_unlock(ftdmchan->mutex); return FTDM_SUCCESS; @@ -3455,7 +3458,7 @@ static FIO_READ_FUNCTION(ftdm_raw_read) ftdm_status_t status = ftdmchan->fio->read(ftdmchan, data, datalen); if (status == FTDM_SUCCESS && ftdmchan->fds[FTDM_READ_TRACE_INDEX] > -1) { ftdm_size_t dlen = *datalen; - if ((ftdm_size_t)write(ftdmchan->fds[FTDM_READ_TRACE_INDEX], data, dlen) != dlen) { + if ((ftdm_size_t)write(ftdmchan->fds[FTDM_READ_TRACE_INDEX], data, (int)dlen) != dlen) { ftdm_log(FTDM_LOG_WARNING, "Raw input trace failed to write all of the %zd bytes\n", dlen); } } @@ -3468,7 +3471,7 @@ static FIO_READ_FUNCTION(ftdm_raw_read) ftdm_size_t dlen = *datalen; ftdm_size_t rc = 0; - write_chan_io_dump(&ftdmchan->rxdump, data, dlen); + write_chan_io_dump(&ftdmchan->rxdump, data, (int)dlen); /* if dtmf debug is enabled and initialized, write there too */ if (ftdmchan->dtmfdbg.file) { @@ -5336,7 +5339,7 @@ static void execute_safety_hangup(void *data) FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t *sigmsg) { if (sigmsg->channel) { - ftdm_mutex_lock(sigmsg->channel->mutex); + ftdm_mutex_lock(sigmsg->channel->mutex); } /* some core things to do on special events */ @@ -5355,6 +5358,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t case FTDM_SIGEVENT_START: { + ftdm_call_set_call_id(&sigmsg->channel->caller_data); ftdm_set_echocancel_call_begin(sigmsg->channel); if (sigmsg->channel->dtmfdbg.requested) { ftdm_channel_command(sigmsg->channel, FTDM_COMMAND_ENABLE_DEBUG_DTMF, NULL); @@ -5384,7 +5388,10 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t break; } - + + if (sigmsg->channel) { + sigmsg->call_id = sigmsg->channel->caller_data.call_id; + } /* if the signaling module uses a queue for signaling notifications, then enqueue it */ if (ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) { ftdm_span_queue_signal(span, sigmsg); @@ -5493,6 +5500,8 @@ FT_DECLARE(ftdm_status_t) ftdm_global_init(void) ftdm_mutex_create(&globals.mutex); ftdm_mutex_create(&globals.span_mutex); ftdm_mutex_create(&globals.group_mutex); + ftdm_mutex_create(&globals.call_id_mutex); + ftdm_sched_global_init(); if (ftdm_sched_create(&globals.timingsched, "freetdm-master") != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "Failed to create master timing schedule context\n"); @@ -5502,6 +5511,7 @@ FT_DECLARE(ftdm_status_t) ftdm_global_init(void) ftdm_log(FTDM_LOG_CRIT, "Failed to run master timing schedule context\n"); return FTDM_FAIL; } + globals.running = 1; return FTDM_SUCCESS; } @@ -5605,6 +5615,7 @@ FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void) ftdm_mutex_destroy(&globals.mutex); ftdm_mutex_destroy(&globals.span_mutex); ftdm_mutex_destroy(&globals.group_mutex); + ftdm_mutex_destroy(&globals.call_id_mutex); memset(&globals, 0, sizeof(globals)); return FTDM_SUCCESS; @@ -5963,6 +5974,47 @@ FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *fchan) return stream.data; } +static ftdm_status_t ftdm_call_set_call_id(ftdm_caller_data_t *caller_data) +{ + uint32_t current_call_id; + ftdm_assert_return(!caller_data->call_id, FTDM_FAIL, "Overwriting non-cleared call-id"); + + ftdm_mutex_lock(globals.call_id_mutex); + current_call_id = globals.last_call_id; + + do { + if (++current_call_id > MAX_CALLIDS) { + current_call_id = 1; + } + if (globals.call_ids[current_call_id] != NULL) { + continue; + } + } while (0); + + globals.last_call_id = current_call_id; + caller_data->call_id = current_call_id; + + globals.call_ids[current_call_id] = caller_data; + ftdm_mutex_unlock(globals.call_id_mutex); + return FTDM_SUCCESS; +} + +static ftdm_status_t ftdm_call_clear_call_id(ftdm_caller_data_t *caller_data) +{ + ftdm_assert_return((caller_data->call_id && caller_data->call_id <= MAX_CALLIDS), FTDM_FAIL, "Clearing call with invalid call-id\n"); + ftdm_mutex_lock(globals.call_id_mutex); + if (globals.call_ids[caller_data->call_id]) { + caller_data->call_id = 0; + globals.call_ids[caller_data->call_id] = NULL; + } else { + ftdm_log(FTDM_LOG_CRIT, "call-id did not exist %u\n", caller_data->call_id); + } + ftdm_mutex_unlock(globals.call_id_mutex); + return FTDM_SUCCESS; +} + + + /* For Emacs: * Local Variables: diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index e95a74bc25..9d94c6d088 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -515,13 +515,20 @@ static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, cons ftdm_r2_data_t *r2data = ftdmchan->span->signal_data; ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Call offered with ANI = %s, DNIS = %s, Category = (%d)\n", ani, dnis, category); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); /* nothing went wrong during call setup, MF has ended, we can and must disable the MF dump */ if (r2data->mf_dump_size) { ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_INPUT_DUMP, NULL); ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_OUTPUT_DUMP, NULL); } + + /* check if this is a collect call and if we should accept it */ + if (!r2data->allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Rejecting collect call\n"); + openr2_chan_disconnect_call(r2chan, OR2_CAUSE_COLLECT_CALL_REJECTED); + } else { + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); + } } /* @@ -900,7 +907,7 @@ static int ftdm_r2_io_write(openr2_chan_t *r2chan, const void *buf, int size) if (FTDM_FAIL == status) { return -1; } - return outsize; + return (int)outsize; } static int ftdm_r2_io_read(openr2_chan_t *r2chan, const void *buf, int size) @@ -911,7 +918,7 @@ static int ftdm_r2_io_read(openr2_chan_t *r2chan, const void *buf, int size) if (FTDM_FAIL == status) { return -1; } - return outsize; + return (int)outsize; } static int ftdm_r2_io_wait(openr2_chan_t *r2chan, int *flags, int block) @@ -993,6 +1000,10 @@ static int ftdm_r2_io_get_oob_event(openr2_chan_t *r2chan, openr2_oob_event_t *e return -1; } + if (fevent->e_type != FTDM_EVENT_OOB) { + return 0; + } + switch (fevent->enum_id) { case FTDM_OOB_CAS_BITS_CHANGE: { @@ -1598,6 +1609,13 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) } break; + /* INDICATE_RINGING doesn't apply to MFC/R2. maybe we could generate a tone */ + case FTDM_CHANNEL_STATE_RINGING: + { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RINGING indicated, ignoring it as it doesn't apply to MFC/R2\n"); + } + break; + default: { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Unhandled channel state change: %s\n", ftdm_channel_state2str(ftdmchan->state)); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c index 304e9d6ce3..5c171a9f6b 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c @@ -502,6 +502,8 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /**************************************************************************/ case FTDM_CHANNEL_STATE_COLLECT: /* IAM received but wating on digits */ + isup_intf = &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId]; + if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); break; @@ -521,8 +523,8 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /*now go to the RING state */ ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING); - } else if (i >= g_ftdm_sngss7_data.min_digits) { - SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, g_ftdm_sngss7_data.min_digits); + } else if (i >= isup_intf->min_digits) { + SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, isup_intf->min_digits); /*now go to the RING state */ ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING); @@ -532,7 +534,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) if (ftdmchan->last_state != FTDM_CHANNEL_STATE_IDLE) { SS7_INFO_CHAN(ftdmchan,"Received %d out of %d so far: %s...starting T35\n", i, - g_ftdm_sngss7_data.min_digits, + isup_intf->min_digits, ftdmchan->caller_data.dnis.digits); /* start ISUP t35 */ @@ -1520,9 +1522,6 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init) /* initalize the global gen_config flag */ g_ftdm_sngss7_data.gen_config = 0; - /* min. number of digitis to wait for */ - g_ftdm_sngss7_data.min_digits = 7; - /* function trace initizalation */ g_ftdm_sngss7_data.function_trace = 1; g_ftdm_sngss7_data.function_trace_level = 7; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h index 378b50e0ad..fe4b6f45c4 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h @@ -50,7 +50,7 @@ /******************************************************************************/ /* DEFINES ********************************************************************/ -#define MAX_NAME_LEN 10 +#define MAX_NAME_LEN 25 #define MAX_PATH 255 #define MAX_CIC_LENGTH 5 @@ -224,6 +224,7 @@ typedef struct sng_isup_intf { uint32_t isap; uint32_t clg_nadi; uint32_t cld_nadi; + uint32_t min_digits; uint16_t t4; uint32_t t10; uint32_t t11; @@ -326,7 +327,6 @@ typedef struct sng_ss7_cfg { typedef struct ftdm_sngss7_data { sng_ss7_cfg_t cfg; int gen_config; - int min_digits; int function_trace; int function_trace_level; int message_trace; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c index 8a24f971ed..d4fd1ca9b3 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c @@ -142,7 +142,7 @@ int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *spa if (!strcasecmp(var, "ch_map")) { /**********************************************************************/ - strcpy(isupCkt.ch_map, val); + strncpy(isupCkt.ch_map, val, MAX_CIC_MAP_LENGTH-1); SS7_DEBUG("\tFound channel map \"%s\"\n", isupCkt.ch_map); /**********************************************************************/ } else if (!strcasecmp(var, "typeCntrl")) { @@ -393,7 +393,7 @@ static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset) for (i = 0; i < num_parms; i++) { /**********************************************************************/ if (!strcasecmp(parm->var, "name")) { - strcpy((char *)mtpLinkSet.name, parm->val); + strncpy((char *)mtpLinkSet.name, parm->val, MAX_NAME_LEN-1); SS7_DEBUG("\tFound an \"mtp_linkset\" named = %s\n", mtpLinkSet.name); /**********************************************************************/ } else if (!strcasecmp(parm->var, "apc")) { @@ -508,7 +508,7 @@ static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp_link_t * /* try to match the parameter to what we expect */ /**********************************************************************/ if (!strcasecmp(parm->var, "name")) { - strcpy((char *)mtpLink->name, parm->val); + strncpy((char *)mtpLink->name, parm->val, MAX_NAME_LEN-1); SS7_DEBUG("\tFound an \"mtp_link\" named = %s\n", mtpLink->name); /**********************************************************************/ } else if (!strcasecmp(parm->var, "span")) { @@ -827,7 +827,7 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route) /* try to match the parameter to what we expect */ /**********************************************************************/ if (!strcasecmp(parm->var, "name")) { - strcpy((char *)mtpRoute.name, parm->val); + strncpy((char *)mtpRoute.name, parm->val, MAX_NAME_LEN-1); SS7_DEBUG("\tFound an \"mtp_route\" named = %s\n", mtpRoute.name); /**********************************************************************/ } else if (!strcasecmp(parm->var, "dpc")) { @@ -999,7 +999,7 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface) /* try to match the parameter to what we expect */ /**********************************************************************/ if (!strcasecmp(parm->var, "name")) { - strcpy((char *)sng_isup.name, parm->val); + strncpy((char *)sng_isup.name, parm->val, MAX_NAME_LEN-1); SS7_DEBUG("\tFound an \"isup_interface\" named = %s\n", sng_isup.name); /**********************************************************************/ } else if (!strcasecmp(parm->var, "spc")) { @@ -1047,6 +1047,11 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface) SS7_DEBUG("\tFound MTP3 Route = %s\n", parm->val); } /**********************************************************************/ + } else if (!strcasecmp(parm->var, "min_digits")) { + sng_isup.min_digits = atoi(parm->val); + + SS7_DEBUG("\tFound min_digits = %d\n", sng_isup.min_digits); + /**********************************************************************/ } else if (!strcasecmp(parm->var, "ssf")) { if (!strcasecmp(parm->val, "nat")) { sng_isup.ssf = SSF_NAT; @@ -1067,8 +1072,8 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface) /**********************************************************************/ } else if (!strcasecmp(parm->var, "license")) { /**********************************************************************/ - strcpy(g_ftdm_sngss7_data.cfg.license, parm->val); - strcpy(g_ftdm_sngss7_data.cfg.signature, parm->val); + strncpy(g_ftdm_sngss7_data.cfg.license, parm->val, MAX_PATH-1); + strncpy(g_ftdm_sngss7_data.cfg.signature, parm->val, MAX_PATH-1); strcat(g_ftdm_sngss7_data.cfg.signature, ".sig"); SS7_DEBUG("\tFound license file = %s\n", g_ftdm_sngss7_data.cfg.license); SS7_DEBUG("\tFound signature file = %s\n", g_ftdm_sngss7_data.cfg.signature); @@ -1304,6 +1309,13 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface) sng_isup.clg_nadi = 0x03; } + /* check if the user requested min_digits value */ + if (sng_isup.min_digits == 0) { + /* default to 7 */ + sng_isup.min_digits = 7; + } + + /* trickle down the SPC to all sub entities */ linkSetId = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].linkSetId; @@ -1359,7 +1371,7 @@ static int ftmod_ss7_fill_in_mtpLink(sng_mtp_link_t *mtpLink) } /* fill in the information */ - strcpy((char *)g_ftdm_sngss7_data.cfg.mtpLink[i].name, (char *)mtpLink->name); + strncpy((char *)g_ftdm_sngss7_data.cfg.mtpLink[i].name, (char *)mtpLink->name, MAX_NAME_LEN-1); g_ftdm_sngss7_data.cfg.mtpLink[i].id = mtpLink->id; @@ -1521,7 +1533,7 @@ static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet) { int i = mtpLinkSet->id; - strcpy((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (char *)mtpLinkSet->name); + strncpy((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (char *)mtpLinkSet->name, MAX_NAME_LEN-1); g_ftdm_sngss7_data.cfg.mtpLinkSet[i].id = mtpLinkSet->id; g_ftdm_sngss7_data.cfg.mtpLinkSet[i].apc = mtpLinkSet->apc; @@ -1559,7 +1571,7 @@ static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route) SS7_DEBUG("found existing mtp3_route, id is = %d\n", mtp3_route->id); } - strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, (char *)mtp3_route->name); + strncpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, (char *)mtp3_route->name, MAX_NAME_LEN-1); g_ftdm_sngss7_data.cfg.mtpRoute[i].id = mtp3_route->id; g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc = mtp3_route->dpc; @@ -1693,7 +1705,7 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup) SS7_DEBUG("found existing isup interface, id is = %d\n", sng_isup->id); } - strcpy((char *)g_ftdm_sngss7_data.cfg.isupIntf[i].name, (char *)sng_isup->name); + strncpy((char *)g_ftdm_sngss7_data.cfg.isupIntf[i].name, (char *)sng_isup->name, MAX_NAME_LEN-1); g_ftdm_sngss7_data.cfg.isupIntf[i].id = sng_isup->id; g_ftdm_sngss7_data.cfg.isupIntf[i].mtpRouteId = sng_isup->mtpRouteId; @@ -1705,6 +1717,7 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup) g_ftdm_sngss7_data.cfg.isupIntf[i].isap = sng_isup->isap; g_ftdm_sngss7_data.cfg.isupIntf[i].cld_nadi = sng_isup->cld_nadi; g_ftdm_sngss7_data.cfg.isupIntf[i].clg_nadi = sng_isup->clg_nadi; + g_ftdm_sngss7_data.cfg.isupIntf[i].min_digits = sng_isup->min_digits; g_ftdm_sngss7_data.cfg.isupIntf[i].options = sng_isup->options; if (sng_isup->t4 != 0) { g_ftdm_sngss7_data.cfg.isupIntf[i].t4 = sng_isup->t4; @@ -1976,7 +1989,7 @@ static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, i return FTDM_FAIL; } - strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[0].name, "self-rt"); + strncpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[0].name, "self-route", MAX_NAME_LEN-1); g_ftdm_sngss7_data.cfg.mtpRoute[0].id = 0; g_ftdm_sngss7_data.cfg.mtpRoute[0].dpc = spc; @@ -2230,7 +2243,7 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot) int lower; int upper; char tmp[5]; /*KONRAD FIX ME*/ - char new_ch_map[MAX_CIC_LENGTH]; + char new_ch_map[MAX_CIC_MAP_LENGTH]; memset(&tmp[0], '\0', sizeof(tmp)); memset(&new_ch_map[0], '\0', sizeof(new_ch_map)); @@ -2337,7 +2350,9 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot) /* the the rest of ch_map to new_ch_map */ strncat(new_ch_map, &ch_map[x], strlen(&ch_map[x])); + /* set the new cic map to ch_map*/ + memset(ch_map, '\0', sizeof(ch_map)); strcpy(ch_map, new_ch_map); } else if (ch_map[x] == ',') { @@ -2345,16 +2360,21 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot) x++; /* copy the rest of the list to new_ch_map */ + memset(new_ch_map, '\0', sizeof(new_ch_map)); strcpy(new_ch_map, &ch_map[x]); /* copy the new_ch_map over the old one */ + memset(ch_map, '\0', sizeof(ch_map)); strcpy(ch_map, new_ch_map); } else if (ch_map[x] == '\0') { + /* we're at the end of the string...copy the rest of the list to new_ch_map */ + memset(new_ch_map, '\0', sizeof(new_ch_map)); strcpy(new_ch_map, &ch_map[x]); /* set the new cic map to ch_map*/ + memset(ch_map, '\0', sizeof(ch_map)); strcpy(ch_map, new_ch_map); } else { /* nothing to do */ diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 4ee6ff5f52..cc32d66bdd 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -295,6 +295,11 @@ typedef struct ftdm_caller_data { /* user information layer 1 protocol */ ftdm_user_layer1_prot_t bearer_layer1; ftdm_variable_container_t variables; /*! #endif - #include "freetdm.h" diff --git a/libs/spandsp/src/spandsp.h.in b/libs/spandsp/src/spandsp.h.in index 9167c1c2cc..eaed548c97 100644 --- a/libs/spandsp/src/spandsp.h.in +++ b/libs/spandsp/src/spandsp.h.in @@ -39,8 +39,9 @@ #include #include @INSERT_MATH_HEADER@ +#if !defined(SPANDSP_NO_TIFF) #include - +#endif #include #include #include diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c index 0422cd2081..fce968c990 100644 --- a/libs/stfu/stfu.c +++ b/libs/stfu/stfu.c @@ -27,6 +27,7 @@ */ #include "stfu.h" +//#define DB_JB 1 #ifdef _MSC_VER /* warning C4706: assignment within conditional expression*/ #pragma warning(disable: 4706) @@ -35,9 +36,12 @@ struct stfu_queue { struct stfu_frame *array; struct stfu_frame int_frame; + uint32_t real_array_size; uint32_t array_size; uint32_t array_len; uint32_t wr_len; + uint32_t last_index; + int32_t last_jitter; }; typedef struct stfu_queue stfu_queue_t; @@ -48,27 +52,72 @@ struct stfu_instance { struct stfu_queue *out_queue; struct stfu_frame *last_frame; uint32_t cur_ts; + uint32_t cur_seq; uint32_t last_wr_ts; + uint32_t last_wr_seq; uint32_t last_rd_ts; - uint32_t interval; + uint32_t samples_per_packet; + uint32_t samples_per_second; uint32_t miss_count; uint32_t max_plc; + uint32_t qlen; + uint32_t max_qlen; + uint32_t orig_qlen; + uint32_t packet_count; + uint32_t consecutive_good_count; + uint32_t consecutive_bad_count; + uint32_t period_good_count; + uint32_t period_bad_count; + uint32_t period_packet_in_count; + uint32_t period_packet_out_count; + uint32_t period_missing_count; + uint32_t period_need_range; + uint32_t period_need_range_avg; + uint32_t period_clean_count; + + uint32_t session_clean_count; + uint32_t session_missing_count; + + uint32_t session_packet_in_count; + uint32_t session_packet_out_count; + + uint32_t sync; + + + int32_t ts_diff; + int32_t last_ts_diff; + int32_t same_ts; + + uint32_t last_seq; + + uint32_t period_time; + uint32_t decrement_time; + + uint32_t plc_len; + + stfu_n_call_me_t callback; + void *udata; }; +static void stfu_n_reset_counters(stfu_instance_t *i); static stfu_status_t stfu_n_resize_aqueue(stfu_queue_t *queue, uint32_t qlen) { unsigned char *m; - if (qlen <= queue->array_size) { - return STFU_IT_FAILED;; + if (qlen <= queue->real_array_size) { + queue->array_size = qlen; + if (queue->array_len > qlen) { + queue->array_len = qlen; + } + } else { + m = realloc(queue->array, qlen * sizeof(struct stfu_frame)); + assert(m); + memset(m + queue->array_size * sizeof(struct stfu_frame), 0, (qlen * sizeof(struct stfu_frame)) - (queue->array_size * sizeof(struct stfu_frame))); + queue->array = (struct stfu_frame *) m; + queue->real_array_size = queue->array_size = qlen; } - m = realloc(queue->array, qlen * sizeof(struct stfu_frame)); - assert(m); - memset(m + queue->array_size, 0, qlen * sizeof(struct stfu_frame) - queue->array_size); - queue->array = (struct stfu_frame *) m; - queue->array_size = qlen; return STFU_IT_WORKED; } @@ -77,8 +126,16 @@ static void stfu_n_init_aqueue(stfu_queue_t *queue, uint32_t qlen) queue->array = calloc(qlen, sizeof(struct stfu_frame)); assert(queue->array != NULL); memset(queue->array, 0, sizeof(struct stfu_frame) * qlen); - queue->array_size = qlen; + queue->real_array_size = queue->array_size = qlen; queue->int_frame.plc = 1; + memset(queue->int_frame.data, 255, sizeof(queue->int_frame.data)); +} + + +void stfu_n_call_me(stfu_instance_t *i, stfu_n_call_me_t callback, void *udata) +{ + i->callback = callback; + i->udata = udata; } void stfu_n_destroy(stfu_instance_t **i) @@ -97,24 +154,40 @@ void stfu_n_destroy(stfu_instance_t **i) void stfu_n_report(stfu_instance_t *i, stfu_report_t *r) { assert(i); - r->in_len = i->in_queue->array_len; - r->in_size = i->in_queue->array_size; - r->out_len = i->out_queue->array_len; - r->out_size = i->out_queue->array_size; + r->qlen = i->qlen; + r->packet_in_count = i->period_packet_in_count; + r->clean_count = i->period_clean_count; + r->consecutive_good_count = i->consecutive_good_count; + r->consecutive_bad_count = i->consecutive_bad_count; } stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen) { stfu_status_t s; + if (i->qlen == i->max_qlen) { + return STFU_IT_FAILED; + } + + if (i->max_qlen && qlen > i->max_qlen) { + if (i->qlen < i->max_qlen) { + qlen = i->max_qlen; + } else { + return STFU_IT_FAILED; + } + } + if ((s = stfu_n_resize_aqueue(&i->a_queue, qlen)) == STFU_IT_WORKED) { s = stfu_n_resize_aqueue(&i->b_queue, qlen); + i->qlen = qlen; + i->max_plc = 5; + i->last_frame = NULL; } return s; } -stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_plc) +stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_per_packet, uint32_t samples_per_second) { struct stfu_instance *i; @@ -123,82 +196,172 @@ stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_plc) return NULL; } memset(i, 0, sizeof(*i)); + i->qlen = qlen; + i->max_qlen = max_qlen; + i->orig_qlen = qlen; + i->samples_per_packet = samples_per_packet; + stfu_n_init_aqueue(&i->a_queue, qlen); stfu_n_init_aqueue(&i->b_queue, qlen); i->in_queue = &i->a_queue; i->out_queue = &i->b_queue; + + i->max_plc = i->qlen / 2; - if (max_plc) { - i->max_plc = max_plc; - } else { - i->max_plc = qlen / 2; - } + i->samples_per_second = samples_per_second ? samples_per_second : 8000; + + i->period_time = ((i->samples_per_second * 20) / i->samples_per_packet); + i->decrement_time = ((i->samples_per_second * 15) / i->samples_per_packet); return i; } +static void stfu_n_reset_counters(stfu_instance_t *i) +{ +#ifdef DB_JB + printf("COUNTER RESET........\n"); +#endif + + if (i->callback) { + i->callback(i, i->udata); + } + + i->consecutive_good_count = 0; + i->consecutive_bad_count = 0; + i->period_good_count = 0; + i->period_clean_count = 0; + i->period_bad_count = 0; + i->period_packet_in_count = 0; + i->period_packet_out_count = 0; + i->period_missing_count = 0; + i->period_need_range = 0; + i->period_need_range_avg = 0; +} + void stfu_n_reset(stfu_instance_t *i) { +#ifdef DB_JB + printf("RESET\n"); +#endif i->in_queue = &i->a_queue; i->out_queue = &i->b_queue; i->in_queue->array_len = 0; i->out_queue->array_len = 0; i->out_queue->wr_len = 0; i->last_frame = NULL; - i->miss_count = 0; + + i->in_queue->last_jitter = 0; + i->out_queue->last_jitter = 0; + + stfu_n_reset_counters(i); + + i->last_seq = 0; + + i->cur_ts = 0; + i->cur_seq = 0; i->last_wr_ts = 0; - i->miss_count = 0; - i->interval = 0; + i->last_wr_seq = 0; + i->last_rd_ts = 0; + i->miss_count = 0; + i->packet_count = 0; } -static int32_t stfu_n_measure_interval(stfu_queue_t *queue) +stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets) { - uint32_t index; - int32_t d, most = 0, last = 0, this, track[STFU_MAX_TRACK] = {0}; - for(index = 0; index < queue->array_len; index++) { - this = queue->array[index].ts; - if (last) { + if (packets > i->qlen) { + stfu_n_reset(i); + } else { + i->sync = packets; + } - if ((d = this - last) > 0 && d / 10 < STFU_MAX_TRACK) { - track[(d/10)]++; - } - } - - last = this; - } - - for(index = 0; index < STFU_MAX_TRACK; index++) { - if (track[index] > track[most]) { - most = index; - } - } - - return most * 10; + return STFU_IT_WORKED; } -static int16_t stfu_n_process(stfu_instance_t *i, stfu_queue_t *queue) -{ - if (!i->interval && !(i->interval = stfu_n_measure_interval(queue))) { - return -1; - } - return 0; -} - -stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, int last) +stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uint32_t pt, void *data, size_t datalen, int last) { uint32_t index; stfu_frame_t *frame; size_t cplen = 0; + int good_seq = 0, good_ts = 0; + + if (!i->samples_per_packet && ts && i->last_rd_ts) { + i->ts_diff = ts - i->last_rd_ts; + + if (i->last_ts_diff == i->ts_diff) { + if (++i->same_ts == 5) { + i->samples_per_packet = i->ts_diff; + } + } else { + i->same_ts = 0; + } + + i->last_ts_diff = i->ts_diff; + + if (!i->samples_per_packet) { + i->last_rd_ts = ts; + return STFU_IT_FAILED; + } + } + + if (seq && seq == i->last_seq + 1) { + good_seq = 1; + } + + if (ts && ts == i->last_rd_ts + i->samples_per_packet) { + good_ts = 1; + } + + + if (good_seq || good_ts) { + i->period_clean_count++; + i->session_clean_count++; + } + + i->period_packet_in_count++; + i->session_packet_in_count++; + + if (i->session_packet_in_count == 150) { + return STFU_IT_WORKED; + } + + i->period_need_range_avg = i->period_need_range / (i->period_missing_count || 1); + + if (i->period_missing_count > i->qlen * 2) { + stfu_n_resize(i, i->qlen + 1); + stfu_n_reset_counters(i); + } + + if (i->qlen > i->orig_qlen && (i->consecutive_good_count > i->decrement_time || i->period_clean_count > i->decrement_time)) { + stfu_n_resize(i, i->qlen - 1); + stfu_n_reset_counters(i); + stfu_n_sync(i, i->qlen); + } + + if ((i->period_packet_in_count > i->period_time)) { + i->period_packet_in_count = 0; + + if (i->period_missing_count == 0 && i->qlen > i->orig_qlen) { + stfu_n_resize(i, i->qlen - 1); + stfu_n_sync(i, i->qlen); + } + + stfu_n_reset_counters(i); + } + +#ifdef DB_JB + printf("%u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u/%u - %u %d\n", + i->qlen, i->period_packet_in_count, i->period_time, i->consecutive_good_count, + i->decrement_time, i->period_clean_count, i->decrement_time, i->consecutive_bad_count, + seq, ts, + i->period_missing_count, i->period_need_range_avg); +#endif + if (last || i->in_queue->array_len == i->in_queue->array_size) { stfu_queue_t *other_queue; - if (i->out_queue->wr_len < i->out_queue->array_len) { - return STFU_IT_FAILED; - } - other_queue = i->in_queue; i->in_queue = i->out_queue; i->out_queue = other_queue; @@ -207,57 +370,92 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void i->out_queue->wr_len = 0; i->last_frame = NULL; i->miss_count = 0; - - if (stfu_n_process(i, i->out_queue) < 0) { - if (i->in_queue->array_len == i->in_queue->array_size && i->out_queue->array_len == i->out_queue->array_size) { - stfu_n_resize(i, i->out_queue->array_size * 2); - } - //return STFU_IT_FAILED; - } - for(index = 0; index < i->out_queue->array_len; index++) { - i->out_queue->array[index].was_read = 0; - } - } + i->in_queue->last_index = 0; + i->out_queue->last_index = 0; + i->out_queue->last_jitter = 0; + } if (last) { return STFU_IM_DONE; } - index = i->in_queue->array_len++; + for(index = 0; index < i->out_queue->array_size; index++) { + if (i->in_queue->array[index].was_read) { + break; + } + } + + index = i->in_queue->array_len++; + frame = &i->in_queue->array[index]; if ((cplen = datalen) > sizeof(frame->data)) { cplen = sizeof(frame->data); } + i->last_seq = seq; i->last_rd_ts = ts; + i->packet_count++; memcpy(frame->data, data, cplen); + frame->pt = pt; frame->ts = ts; + frame->seq = seq; frame->dlen = cplen; frame->was_read = 0; return STFU_IT_WORKED; } -static int stfu_n_find_frame(stfu_queue_t *queue, uint32_t ts, stfu_frame_t **r_frame, uint32_t *index) +static int stfu_n_find_any_frame(stfu_instance_t *in, stfu_frame_t **r_frame) +{ + uint32_t i = 0; + stfu_frame_t *frame = NULL; + stfu_queue_t *queue; + + assert(r_frame); + + *r_frame = NULL; + + for (queue = in->out_queue ; queue && queue != in->in_queue ; queue = in->in_queue) { + + for(i = 0; i < queue->real_array_size; i++) { + frame = &queue->array[i]; + if (!frame->was_read) { + *r_frame = frame; + queue->last_index = i; + frame->was_read = 1; + in->period_packet_out_count++; + in->session_packet_out_count++; + return 1; + } + } + + } + + return 0; +} + + +static int stfu_n_find_frame(stfu_instance_t *in, stfu_queue_t *queue, uint32_t ts, uint32_t seq, stfu_frame_t **r_frame) { uint32_t i = 0; stfu_frame_t *frame = NULL; assert(r_frame); - assert(index); *r_frame = NULL; - for(i = 0; i < queue->array_len; i++) { + for(i = 0; i < queue->real_array_size; i++) { frame = &queue->array[i]; - if (frame->ts == ts) { + if ((seq && frame->seq == seq) || frame->ts == ts) { *r_frame = frame; - *index = i; + queue->last_index = i; frame->was_read = 1; + in->period_packet_out_count++; + in->session_packet_out_count++; return 1; } } @@ -267,40 +465,139 @@ static int stfu_n_find_frame(stfu_queue_t *queue, uint32_t ts, stfu_frame_t **r_ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i) { - uint32_t index; stfu_frame_t *rframe = NULL; - - if (((i->out_queue->wr_len == i->out_queue->array_len) || !i->out_queue->array_len)) { + int found = 0; + + if (!i->samples_per_packet || ((i->out_queue->wr_len == i->out_queue->array_len) || !i->out_queue->array_len)) { return NULL; } if (i->cur_ts == 0) { i->cur_ts = i->out_queue->array[0].ts; } else { - i->cur_ts += i->interval; + i->cur_ts += i->samples_per_packet; } + if (i->cur_seq == 0) { + i->cur_seq = i->out_queue->array[0].seq; + } else { + i->cur_seq++; + } - if (stfu_n_find_frame(i->out_queue, i->cur_ts, &rframe, &index) || stfu_n_find_frame(i->in_queue, i->cur_ts, &rframe, &index)) { + if (!(found = stfu_n_find_frame(i, i->out_queue, i->cur_ts, i->cur_seq, &rframe))) { + found = stfu_n_find_frame(i, i->in_queue, i->cur_ts, i->cur_seq, &rframe); + } + + if (!found && i->sync) { +#ifdef DB_JB + printf("SYNC %u\n", i->sync); +#endif + if ((found = stfu_n_find_any_frame(i, &rframe))) { + i->cur_seq = rframe->seq; + i->cur_ts = rframe->ts; + } + i->sync--; + } + + + if (!found && i->samples_per_packet) { +#ifdef DB_JB + int y; + stfu_frame_t *frame = NULL; +#endif + int32_t delay = i->last_rd_ts - i->cur_ts; + uint32_t need = abs(i->last_rd_ts - i->cur_ts) / i->samples_per_packet; + + + i->period_missing_count++; + i->session_missing_count++; + i->period_need_range += need; + +#ifdef DB_JB + printf("MISSING %u %u %u %u %d %u %d\n", i->cur_seq, i->cur_ts, i->packet_count, i->last_rd_ts, delay, i->qlen, need); +#endif + + if (i->packet_count > i->orig_qlen * 100 && delay > 0 && need > i->qlen && need < (i->qlen + 5)) { + i->packet_count = 0; + } + +#ifdef DB_JB + for(y = 0; y < i->out_queue->array_size; y++) { + if ((y % 5) == 0) printf("\n"); + frame = &i->out_queue->array[y]; + printf("%u:%u\t", frame->seq, frame->ts); + } + printf("\n\n"); + + + for(y = 0; y < i->in_queue->array_size; y++) { + if ((y % 5) == 0) printf("\n"); + frame = &i->in_queue->array[y]; + printf("%u:%u\t", frame->seq, frame->ts); + } + printf("\n\n"); +#endif + + if (delay < 0) { + stfu_n_reset(i); + return NULL; + } + } + +#ifdef DB_JB + if (found) { + printf("O: %u:%u %u\n", rframe->seq, rframe->seq, rframe->plc); + assert(found && rframe->seq); + } else { + printf("DATA: %u %u %d %s %d\n", i->packet_count, i->consecutive_good_count, i->out_queue->last_jitter, found ? "found" : "not found", i->qlen); + } +#endif + + + if (found) { + i->consecutive_good_count++; + i->period_good_count++; + i->consecutive_bad_count = 0; + } else { + i->consecutive_bad_count++; + i->period_bad_count++; + i->consecutive_good_count = 0; + } + + if (found) { i->last_frame = rframe; i->out_queue->wr_len++; i->last_wr_ts = rframe->ts; + i->last_wr_seq = rframe->seq; i->miss_count = 0; + if (rframe->dlen) { + i->plc_len = rframe->dlen; + } } else { i->last_wr_ts = i->cur_ts; + i->last_wr_seq = i->cur_seq; rframe = &i->out_queue->int_frame; - - if (i->last_frame && i->last_frame != rframe) { - rframe->dlen = i->last_frame->dlen; + rframe->dlen = i->plc_len; + + if (i->last_frame) { /* poor man's plc.. Copy the last frame, but we flag it so you can use a better one if you wish */ - memcpy(rframe->data, i->last_frame->data, rframe->dlen); + if (i->miss_count) { + memset(rframe->data, 255, rframe->dlen); + } else { + memcpy(rframe->data, i->last_frame->data, rframe->dlen); + } } rframe->ts = i->cur_ts; - if (++i->miss_count > i->max_plc) { - i->out_queue->wr_len = i->out_queue->array_size; - i->cur_ts = 0; + i->miss_count++; + +#ifdef DB_JB + printf("PLC %d %d %ld %u %u\n", i->miss_count, rframe->plc, rframe->dlen, rframe->seq, rframe->ts); +#endif + + if (i->miss_count > i->max_plc) { + stfu_n_reset(i); rframe = NULL; } } diff --git a/libs/stfu/stfu.h b/libs/stfu/stfu.h index 900db6f9ac..d2760b27bc 100644 --- a/libs/stfu/stfu.h +++ b/libs/stfu/stfu.h @@ -75,6 +75,7 @@ typedef enum { struct stfu_frame { uint32_t ts; uint32_t pt; + uint32_t seq; uint8_t data[STFU_DATALEN]; size_t dlen; uint8_t was_read; @@ -86,24 +87,27 @@ struct stfu_instance; typedef struct stfu_instance stfu_instance_t; typedef struct { - uint32_t in_len; - uint32_t in_size; - uint32_t out_len; - uint32_t out_size; - + uint32_t qlen; + uint32_t packet_in_count; + uint32_t clean_count; + uint32_t consecutive_good_count; + uint32_t consecutive_bad_count; } stfu_report_t; +typedef void (*stfu_n_call_me_t)(stfu_instance_t *i, void *); void stfu_n_report(stfu_instance_t *i, stfu_report_t *r); void stfu_n_destroy(stfu_instance_t **i); -stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_plc); +stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_per_packet, uint32_t samples_per_second); stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen); -stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, int last); +stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uint32_t pt, void *data, size_t datalen, int last); stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i); void stfu_n_reset(stfu_instance_t *i); +stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets); +void stfu_n_call_me(stfu_instance_t *i, stfu_n_call_me_t callback, void *udata); #define stfu_im_done(i) stfu_n_add_data(i, 0, NULL, 0, 1) -#define stfu_n_eat(i,t,p,d,l) stfu_n_add_data(i, t, p, d, l, 0) +#define stfu_n_eat(i,t,s,p,d,l) stfu_n_add_data(i, t, s, p, d, l, 0) #ifdef __cplusplus } diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index 13410a00ae..422d5f2930 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -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 { diff --git a/src/include/switch_apr.h b/src/include/switch_apr.h index dc81d1a522..d89a13bb30 100644 --- a/src/include/switch_apr.h +++ b/src/include/switch_apr.h @@ -1110,6 +1110,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. diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h index 7269a2b8d9..e3e9f665a3 100644 --- a/src/include/switch_rtp.h +++ b/src/include/switch_rtp.h @@ -229,7 +229,12 @@ 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_deactivate_jitter_buffer(switch_rtp_t *rtp_session); /*! \brief Set an RTP Flag diff --git a/src/include/switch_types.h b/src/include/switch_types.h index c01638089f..d020775d48 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -790,6 +790,7 @@ typedef enum { SWITCH_MESSAGE_INDICATE_T38_DESCRIPTION, SWITCH_MESSAGE_INDICATE_UDPTL_MODE, SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS, + SWITCH_MESSAGE_INDICATE_JITTER_BUFFER, SWITCH_MESSAGE_INVALID } switch_core_session_message_types_t; @@ -1093,6 +1094,7 @@ typedef enum { CF_PASSTHRU_PTIME_MISMATCH, CF_BRIDGE_NOWRITE, CF_RECOVERED, + CF_JITTERBUFFER, /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ CF_FLAG_MAX } switch_channel_flag_t; diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index eacde59949..dba86e3103 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -2542,6 +2542,60 @@ SWITCH_STANDARD_API(uuid_simplify_function) } +#define JITTERBUFFER_SYNTAX " [0|[:]]" +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 "" SWITCH_STANDARD_API(uuid_phone_event_function) { @@ -4278,21 +4332,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 +4781,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, " [format string]"); + SWITCH_ADD_API(commands_api_interface, "strftime_tz", "strftime_tz", strftime_tz_api_function, " [|][format string]"); SWITCH_ADD_API(commands_api_interface, "stun", "stun", stun_function, "[: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, " [count]"); @@ -4758,6 +4824,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 |
]"); SWITCH_ADD_API(commands_api_interface, "xml_wrap", "Wrap another api command in xml", xml_wrap_api_function, " "); switch_console_set_complete("add alias add"); @@ -4854,6 +4922,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"); diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 4fd6a676ea..e508486380 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -269,7 +269,7 @@ SWITCH_STANDARD_APP(bind_digit_action_function) } -#define DETECT_SPEECH_SYNTAX " [] OR grammar [] OR pause OR resume" +#define DETECT_SPEECH_SYNTAX " [] OR grammar [] OR nogrammar OR pause OR resume OR stop OR param " 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 }; @@ -1303,13 +1314,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 { @@ -3513,6 +3533,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "ivr", "Run an ivr menu", "Run an ivr menu.", ivr_application_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "redirect", "Send session redirect", "Send a redirect message to a session.", redirect_function, "", SAF_SUPPORT_NOMEDIA); + SWITCH_ADD_APP(app_interface, "jitterbuffer", "Send session jitterbuffer", "Send a jitterbuffer message to a session.", + jitterbuffer_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "send_display", "Send session a new display", "Send session a new display.", display_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "respond", "Send session respond", "Send a respond message to a session.", respond_function, "", diff --git a/src/mod/endpoints/mod_skypopen/oss/Makefile b/src/mod/endpoints/mod_skypopen/oss/Makefile new file mode 100644 index 0000000000..91cc61ba1e --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/oss/Makefile @@ -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 -DSCULL_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 + +scull-objs := main.o + +obj-m := scull.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 diff --git a/src/mod/endpoints/mod_skypopen/oss/main.c b/src/mod/endpoints/mod_skypopen/oss/main.c new file mode 100644 index 0000000000..4d36ac00d5 --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/oss/main.c @@ -0,0 +1,335 @@ +/* + * main.c -- the bare scull 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 +#include +#include + +#include /* printk() */ +#include /* kmalloc() */ +#include /* everything... */ +#include /* error codes */ +#include /* size_t */ +#include +#include /* O_ACCMODE */ +#include +#include + +#include /* cli(), *_flags */ +#include /* copy_*_user */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scull.h" /* local definitions */ + +/* + * Our parameters which can be set at load time. + */ + +int scull_major = SCULL_MAJOR; +int scull_minor = 3; +int scull_nr_devs = SCULL_NR_DEVS; /* number of bare scull devices */ + +module_param(scull_major, int, S_IRUGO); +module_param(scull_minor, int, S_IRUGO); +module_param(scull_nr_devs, int, S_IRUGO); + +MODULE_AUTHOR("Original: Alessandro Rubini, Jonathan Corbet. Heavy modified by: Giovanni Maruzzelli"); +MODULE_LICENSE("Dual BSD/GPL"); + +static struct scull_dev *scull_devices; /* allocated in scull_init_module */ + +#define GIOVA_BLK 3840 +#define GIOVA_SLEEP 40000 + +void my_timer_callback_inq( unsigned long data ) +{ + struct scull_dev *dev = (void *)data; + + wake_up_interruptible(&dev->inq); + mod_timer( &dev->timer_inq, jiffies + msecs_to_jiffies(GIOVA_SLEEP/1000) ); + +} + +void my_timer_callback_outq( unsigned long data ) +{ + struct scull_dev *dev = (void *)data; + + wake_up_interruptible(&dev->outq); + mod_timer( &dev->timer_outq, jiffies + msecs_to_jiffies(GIOVA_SLEEP/1000) ); +} + +/* The clone-specific data structure includes a key field */ + +struct scull_listitem { + struct scull_dev device; + dev_t key; + struct list_head list; + +}; + +/* The list of devices, and a lock to protect it */ +static LIST_HEAD(scull_c_list); +static spinlock_t scull_c_lock = SPIN_LOCK_UNLOCKED; + +/* Look for a device or create one if missing */ +static struct scull_dev *scull_c_lookfor_device(dev_t key) +{ + struct scull_listitem *lptr; + + list_for_each_entry(lptr, &scull_c_list, list) { + if (lptr->key == key) + return &(lptr->device); + } + + /* not found */ + lptr = kmalloc(sizeof(struct scull_listitem), GFP_KERNEL); + if (!lptr) + return NULL; + + /* initialize the device */ + memset(lptr, 0, sizeof(struct scull_listitem)); + lptr->key = key; + + init_waitqueue_head(&lptr->device.inq); + init_waitqueue_head(&lptr->device.outq); + printk(" Timer installing\n"); + 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 timer to fire in %dms (%ld)\n", GIOVA_SLEEP/1000, jiffies ); + mod_timer( &lptr->device.timer_inq, jiffies + msecs_to_jiffies(GIOVA_SLEEP/1000) ); + mod_timer( &lptr->device.timer_outq, jiffies + msecs_to_jiffies(GIOVA_SLEEP/1000) ); + /* place it in the list */ + list_add(&lptr->list, &scull_c_list); + + return &(lptr->device); +} +static int scull_c_open(struct inode *inode, struct file *filp) +{ + struct scull_dev *dev; + dev_t key; + + if (!current->pid) { + printk("Process \"%s\" has no pid\n", current->comm); + return -EINVAL; + } + key = current->pid; + + /* look for a scullc device in the list */ + spin_lock(&scull_c_lock); + dev = scull_c_lookfor_device(key); + spin_unlock(&scull_c_lock); + + if (!dev) + return -ENOMEM; + + /* then, everything else is copied from the bare scull device */ + filp->private_data = dev; + return 0; /* success */ +} + +static int scull_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; +} + + + +/*************************************************************/ +/* + * Open and close + */ + +ssize_t scull_read(struct file *filp, char __user *buf, size_t count, + loff_t *f_pos) +{ + struct scull_dev *dev = filp->private_data; + + DEFINE_WAIT(wait); + prepare_to_wait(&dev->inq, &wait, TASK_INTERRUPTIBLE); + schedule(); + finish_wait(&dev->inq, &wait); + return count; + +} + +ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, + loff_t *f_pos) +{ + struct scull_dev *dev = filp->private_data; + DEFINE_WAIT(wait); + prepare_to_wait(&dev->outq, &wait, TASK_INTERRUPTIBLE); + schedule(); + finish_wait(&dev->outq, &wait); + + return count; + +} +/* + * The ioctl() implementation + */ + +int scull_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(GIOVA_BLK, p); + case SNDCTL_DSP_GETFMTS: + return put_user(28731, p); + + default: + return 0; + } + +} + +struct file_operations scull_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = scull_read, + .write = scull_write, + .ioctl = scull_ioctl, + .open = scull_c_open, + .release = scull_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 scull_cleanup_module(void) +{ + int i; + int ret; + struct scull_listitem *lptr, *next; + dev_t devno = MKDEV(scull_major, scull_minor); + + /* Get rid of our char dev entries */ + if (scull_devices) { + for (i = 0; i < scull_nr_devs; i++) { + cdev_del(&scull_devices[i].cdev); + } + kfree(scull_devices); + } + + + /* And all the cloned devices */ + list_for_each_entry_safe(lptr, next, &scull_c_list, list) { + ret= del_timer( &lptr->device.timer_inq ); + if (ret) printk("The inq timer was still in use...\n"); + ret= del_timer( &lptr->device.timer_outq ); + if (ret) printk("The outq timer was still in use...\n"); + list_del(&lptr->list); + kfree(lptr); + } + printk("Timer uninstalling\n"); + /* cleanup_module is never called if registering failed */ + unregister_chrdev_region(devno, scull_nr_devs); + +} + + +/* + * Set up the char_dev structure for this device. + */ +static void scull_setup_cdev(struct scull_dev *dev, int index) +{ + int err, devno = MKDEV(scull_major, scull_minor + index); + + cdev_init(&dev->cdev, &scull_fops); + dev->cdev.owner = THIS_MODULE; + dev->cdev.ops = &scull_fops; + err = cdev_add (&dev->cdev, devno, 1); + /* Fail gracefully if need be */ + if (err) + printk(KERN_NOTICE "Error %d adding scull%d", err, index); +} + + + +int scull_init_module(void) +{ + int result, i; + dev_t dev = 0; + + /* + * Get a range of minor numbers to work with, asking for a dynamic + * major unless directed otherwise at load time. + */ + if (scull_major) { + dev = MKDEV(scull_major, scull_minor); + result = register_chrdev_region(dev, scull_nr_devs, "dsp"); + } else { + result = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs, + "dsp"); + scull_major = MAJOR(dev); + } + if (result < 0) { + printk(KERN_WARNING "scull: can't get major %d\n", scull_major); + return result; + } + + /* + * allocate the devices -- we can't have them static, as the number + * can be specified at load time + */ + scull_devices = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL); + if (!scull_devices) { + result = -ENOMEM; + goto fail; /* Make this more graceful */ + } + memset(scull_devices, 0, scull_nr_devs * sizeof(struct scull_dev)); + + /* Initialize each device. */ + for (i = 0; i < scull_nr_devs; i++) { + scull_setup_cdev(&scull_devices[i], i); + } + + /* At this point call the init function for any friend device */ + dev = MKDEV(scull_major, scull_minor + scull_nr_devs); + return 0; /* succeed */ + +fail: + scull_cleanup_module(); + return result; +} + +module_init(scull_init_module); +module_exit(scull_cleanup_module); diff --git a/src/mod/endpoints/mod_skypopen/oss/scull.h b/src/mod/endpoints/mod_skypopen/oss/scull.h new file mode 100644 index 0000000000..e86281bd94 --- /dev/null +++ b/src/mod/endpoints/mod_skypopen/oss/scull.h @@ -0,0 +1,64 @@ +/* + * scull.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: scull.h,v 1.15 2004/11/04 17:51:18 rubini Exp $ + */ + +#ifndef _SCULL_H_ +#define _SCULL_H_ + +#include /* needed for the _IOW etc stuff used later */ + +#ifndef SCULL_MAJOR +#define SCULL_MAJOR 14 /* dynamic major by default */ +#endif + +#ifndef SCULL_NR_DEVS +#define SCULL_NR_DEVS 1 /* scull0 through scull3 */ +#endif + +struct scull_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 */ + struct timer_list timer_inq; + struct timer_list timer_outq; + //unsigned long read_howmany; + //unsigned long write_howmany; + //unsigned long read_sleeped_acc; + //unsigned long write_sleeped_acc; + //double read_delay; /* how much delay last time */ + //double write_delay; /* how much delay last time */ +}; + + +/* + * The different configurable parameters + */ +extern int scull_major; /* main.c */ +extern int scull_nr_devs; + + +/* + * Prototypes for shared functions + */ + +ssize_t scull_read(struct file *filp, char __user *buf, size_t count, + loff_t *f_pos); +ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, + loff_t *f_pos); +int scull_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + +#endif /* _SCULL_H_ */ diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 74c4c0897e..0e64d54a0a 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -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) { @@ -1332,6 +1332,49 @@ 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; + + 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])) { diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 6970a7ab05..61d165753c 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -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; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 2e13b544d0..e34d7aef9d 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -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) { @@ -3673,6 +3675,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); + } } } diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 6416778ab0..74f5d3d764 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -3153,18 +3153,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 = 50; + char *p; - if (len < 100 || len > 1000) { + if ((p = strchr(val, ':'))) { + p++; + maxlen = atoi(val); + } + + 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 = 0; + 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); + } + } } diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 143666ceb8..5d666f03ee 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -90,6 +90,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co char *user_via = NULL; char *contact_str = NULL; char *dup_dest = NULL; + char *remote_host = NULL; if (!to) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing To: header.\n"); @@ -185,11 +186,9 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co /* sofia_glue is running sofia_overcome_sip_uri_weakness we do not, not sure if it matters */ - remote_ip = malloc(sizeof(80)); dup_dest = strdup(dst->contact); if (switch_stristr("fs_path", dst->contact)) { - char *remote_host = NULL; const char *s; if ((s = switch_stristr("fs_path=", dst->contact))) { @@ -202,7 +201,6 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co if (!zstr(remote_host)) { switch_split_user_domain(remote_host, NULL, &remote_ip); } - switch_safe_free(remote_host); } if (zstr(remote_ip)) { @@ -236,7 +234,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co } switch_safe_free(dup_dest); - free(remote_ip); + switch_safe_free(remote_host); status = SWITCH_STATUS_SUCCESS; diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx index 8033a8faa5..1ad1b16b9a 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx @@ -28290,15 +28290,33 @@ 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_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; } diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index a65d82d9cb..1d3c5d60ce 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -28993,15 +28993,33 @@ 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_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; } diff --git a/src/mod/languages/mod_managed/managed/swig.2010.cs b/src/mod/languages/mod_managed/managed/swig.2010.cs index 4d14f10879..4b9ce71e60 100644 --- a/src/mod/languages/mod_managed/managed/swig.2010.cs +++ b/src/mod/languages/mod_managed/managed/swig.2010.cs @@ -4640,8 +4640,13 @@ 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_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; } @@ -12448,7 +12453,10 @@ 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_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 +21562,7 @@ public enum switch_channel_flag_t { CF_PASSTHRU_PTIME_MISMATCH, CF_BRIDGE_NOWRITE, CF_RECOVERED, + CF_JITTERBUFFER, CF_FLAG_MAX } @@ -23243,6 +23252,7 @@ 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_INVALID } diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index e024c586f8..9decf74045 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -4630,8 +4630,13 @@ 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_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; } @@ -12434,7 +12439,10 @@ 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_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); @@ -21500,6 +21508,7 @@ public enum switch_channel_flag_t { CF_PASSTHRU_PTIME_MISMATCH, CF_BRIDGE_NOWRITE, CF_RECOVERED, + CF_JITTERBUFFER, CF_FLAG_MAX } @@ -23167,6 +23176,7 @@ 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_INVALID } diff --git a/src/mod/languages/mod_perl/mod_perl_wrap.cpp b/src/mod/languages/mod_perl/mod_perl_wrap.cpp index 2efbdf1abc..370c88bc99 100644 --- a/src/mod/languages/mod_perl/mod_perl_wrap.cpp +++ b/src/mod/languages/mod_perl/mod_perl_wrap.cpp @@ -9732,17 +9732,17 @@ XS(SWIG_init) { SWIG_TypeClientData(SWIGTYPE_p_IVRMenu, (void*) "freeswitch::IVRMenu"); SWIG_TypeClientData(SWIGTYPE_p_API, (void*) "freeswitch::API"); SWIG_TypeClientData(SWIGTYPE_p_input_callback_state, (void*) "freeswitch::input_callback_state_t"); - /*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { + /*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { SV *sv = get_sv((char*) SWIG_prefix "S_HUP", TRUE | 0x2 | GV_ADDMULTI); sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_HUP))); SvREADONLY_on(sv); } while(0) /*@SWIG@*/; - /*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { + /*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { SV *sv = get_sv((char*) SWIG_prefix "S_FREE", TRUE | 0x2 | GV_ADDMULTI); sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_FREE))); SvREADONLY_on(sv); } while(0) /*@SWIG@*/; - /*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { + /*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { SV *sv = get_sv((char*) SWIG_prefix "S_RDLOCK", TRUE | 0x2 | GV_ADDMULTI); sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_RDLOCK))); SvREADONLY_on(sv); diff --git a/src/switch_apr.c b/src/switch_apr.c index dccc37be96..7c027f8c68 100644 --- a/src/switch_apr.c +++ b/src/switch_apr.c @@ -729,6 +729,18 @@ 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; + + new_sa = apr_pcalloc(pool, sizeof(apr_sockaddr_t)); + switch_assert(new_sa); + new_sa->pool = pool; + memset(new_sa, 0, sizeof(new_sa)); + *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) { diff --git a/src/switch_core_io.c b/src/switch_core_io.c index 6f3e65a9f4..a2df79d1bc 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -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; @@ -326,6 +332,23 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi 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) && !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 +384,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 +410,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 +494,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 +512,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 +840,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: diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 2567d17712..c2766170a8 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -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); diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 4364ff2844..b561ebe775 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -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; } diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 46ba4e6659..6e2aeaf637 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -2290,7 +2290,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 +2300,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, 0, read_frame->payload, read_frame->data, read_frame->datalen); ts += interval; if ((jb_frame = stfu_n_read_a_frame(jb))) { diff --git a/src/switch_rtp.c b/src/switch_rtp.c index ee1c4acf5e..772c2508a0 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -1367,9 +1367,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,12 +1619,65 @@ 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; +} + +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) { - rtp_session->jb = stfu_n_init(queue_frames, 0); + if (!switch_rtp_ready(rtp_session)) { + return SWITCH_STATUS_FALSE; + } - return SWITCH_STATUS_SUCCESS; + 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 || 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) @@ -2016,14 +2070,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 +2105,16 @@ 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++; + + if (rtp_session->jb) { + stfu_n_eat(rtp_session->jb, ntohl(rtp_session->recv_msg.header.ts), + ntohs((uint16_t) rtp_session->recv_msg.header.seq), + rtp_session->recv_msg.header.pt, + rtp_session->recv_msg.body, bytes - rtp_header_len); + } + rtp_session->stats.inbound.raw_bytes += bytes; rtp_session->stats.inbound.flush_packet_count++; rtp_session->stats.inbound.packet_count++; @@ -2056,6 +2124,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); @@ -2104,7 +2176,9 @@ 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, + stfu_n_eat(rtp_session->jb, ntohl(rtp_session->recv_msg.header.ts), + ntohs((uint16_t) rtp_session->recv_msg.header.seq), + rtp_session->recv_msg.header.pt, rtp_session->recv_msg.body, *bytes - rtp_header_len); *bytes = 0; status = SWITCH_STATUS_FALSE; @@ -2114,14 +2188,14 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t 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; - + rtp_session->recv_msg.header.seq = htons((uint16_t)jb_frame->seq); status = SWITCH_STATUS_SUCCESS; } } @@ -2824,7 +2898,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ if ((poll_status = switch_poll(rtp_session->read_pollfd, 1, &fdr, 0)) == SWITCH_STATUS_SUCCESS) { goto recvfrom; } - + memset(data, 0, 2); data[0] = 65; rtp_session->recv_msg.header.pt = (uint32_t) rtp_session->cng_pt ? rtp_session->cng_pt : SWITCH_RTP_CNG_PAYLOAD; @@ -3053,6 +3127,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); diff --git a/w32/Console/FreeSwitchConsole.2008.vcproj b/w32/Console/FreeSwitchConsole.2008.vcproj index 80f062abe0..7fc1784d14 100644 --- a/w32/Console/FreeSwitchConsole.2008.vcproj +++ b/w32/Console/FreeSwitchConsole.2008.vcproj @@ -46,7 +46,7 @@ Disabled - %(RootDir)%(Directory)include;%(RootDir)%(Directory)..\libs\include;%(AdditionalIncludeDirectories) + %(RootDir)%(Directory)include;..\..\libs\spandsp\src\msvc;..\..\libs\spandsp\src;..\..\libs\tiff-3.8.2\libtiff;%(RootDir)%(Directory)..\libs\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks @@ -109,7 +109,7 @@ Disabled - %(RootDir)%(Directory)include;%(RootDir)%(Directory)..\libs\include;%(AdditionalIncludeDirectories) + %(RootDir)%(Directory)include;..\..\libs\spandsp\src\msvc;..\..\libs\spandsp\src;..\..\libs\tiff-3.8.2\libtiff;%(RootDir)%(Directory)..\libs\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks @@ -134,7 +134,7 @@ - %(RootDir)%(Directory)include;%(RootDir)%(Directory)..\libs\include;%(AdditionalIncludeDirectories) + %(RootDir)%(Directory)include;..\..\libs\spandsp\src\msvc;..\..\libs\spandsp\src;..\..\libs\tiff-3.8.2\libtiff;%(RootDir)%(Directory)..\libs\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreadedDLL @@ -161,7 +161,7 @@ X64 - %(RootDir)%(Directory)include;%(RootDir)%(Directory)..\libs\include;%(AdditionalIncludeDirectories) + %(RootDir)%(Directory)include;..\..\libs\spandsp\src\msvc;..\..\libs\spandsp\src;..\..\libs\tiff-3.8.2\libtiff;%(RootDir)%(Directory)..\libs\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreadedDLL diff --git a/w32/Library/FreeSwitchCore.2008.vcproj b/w32/Library/FreeSwitchCore.2008.vcproj index ca15da8b52..6ba5b95959 100644 --- a/w32/Library/FreeSwitchCore.2008.vcproj +++ b/w32/Library/FreeSwitchCore.2008.vcproj @@ -47,7 +47,7 @@ Disabled - ..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;%(AdditionalIncludeDirectories) + ..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;..\..\libs\spandsp\src\msvc;..\..\libs\spandsp\src;..\..\libs\tiff-3.8.2\libtiff;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;FREESWITCHCORE_EXPORTS;PCRE_STATIC;STATICLIB;%(PreprocessorDefinitions) true EnableFastChecks @@ -147,7 +147,7 @@ if not exist "$(OutDir)htdocs" xcopy "$(SolutionDir)htdocs\*.*" "$(OutDir)htdocs Disabled - ..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;%(AdditionalIncludeDirectories) + ..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;..\..\libs\spandsp\src\msvc;..\..\libs\spandsp\src;..\..\libs\tiff-3.8.2\libtiff;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;FREESWITCHCORE_EXPORTS;PCRE_STATIC;STATICLIB;%(PreprocessorDefinitions) true EnableFastChecks @@ -199,7 +199,7 @@ if not exist "$(OutDir)htdocs" xcopy "$(SolutionDir)htdocs\*.*" "$(OutDir)htdocs Disabled - ..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;%(AdditionalIncludeDirectories) + ..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;..\..\libs\spandsp\src\msvc;..\..\libs\spandsp\src;..\..\libs\tiff-3.8.2\libtiff;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;FREESWITCHCORE_EXPORTS;STATICLIB;CRASH_PROT;PCRE_STATIC;%(PreprocessorDefinitions) MultiThreadedDLL Use @@ -248,7 +248,7 @@ if not exist "$(OutDir)htdocs" xcopy "$(SolutionDir)htdocs\*.*" "$(OutDir)htdocs Disabled - ..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;%(AdditionalIncludeDirectories) + ..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;..\..\libs\spandsp\src\msvc;..\..\libs\spandsp\src;..\..\libs\tiff-3.8.2\libtiff;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;FREESWITCHCORE_EXPORTS;STATICLIB;CRASH_PROT;PCRE_STATIC;%(PreprocessorDefinitions) MultiThreadedDLL Use @@ -766,6 +766,9 @@ if not exist "$(OutDir)htdocs" xcopy "$(SolutionDir)htdocs\*.*" "$(OutDir)htdocs {89385c74-5860-4174-9caf-a39e7c48909c} false + + {1cbb0077-18c5-455f-801c-0a0ce7b0bbf5} + {03207781-0d1c-4db3-a71d-45c608f28dbd} false