Merge remote branch 'fsorig/master'

This commit is contained in:
Moises Silva 2011-03-21 16:09:49 -04:00
commit 28494cae6a
67 changed files with 2222 additions and 467 deletions

23
.gitignore vendored
View File

@ -42,6 +42,12 @@ configure.lineno
config.log
config.status
core.*
*.2010.log
*.Build.CppClean.log
*.tlog
*.unsuccessfulbuild
*.cache
*.lastbuildstate
/w32/Library/lastversion
/w32/Library/tmpVersion.Bat
@ -83,6 +89,7 @@ core.*
/build/config/missing
/build/freeswitch.pc
/build/getlib.sh
/build/getg729.sh
/build/getsounds.sh
/build/Makefile
/build/Makefile.in
@ -104,6 +111,7 @@ core.*
/libs/freetdm/testtones
/libs/fsg729-*-installer
/libs/g729/
/libs/libcodec2/compile
/libs/libcodec2/config.guess
/libs/libcodec2/config.sub
/libs/libcodec2/configure
@ -118,6 +126,7 @@ core.*
/libs/libcodec2/src/Makefile.in
/libs/libcodec2/unittest/Makefile
/libs/libcodec2/unittest/Makefile.in
/libs/mpg123-1.13.2/
/scripts/fsxs
/scripts/gentls_cert
@ -147,3 +156,17 @@ core.*
/src/mod/say/mod_say_th/Makefile
/src/mod/say/mod_say_zh/Makefile
BuildLog.htm
/w32/Console/Debug/
/w32/Console/Release/
/w32/Library/Debug/
/w32/Library/Release/
Freeswitch.2010.sdf
/Win32/
/x64/
src/mod/codecs/mod_celt/*/*/mod_celt.log
src/mod/endpoints/mod_skinny/*/*/mod_skinny_2010.log
src/mod/formats/mod_shout/*/*/mod_shout.log

View File

@ -36,6 +36,7 @@ applications/mod_valet_parking
#applications/mod_snipe_hunt
#applications/mod_callcenter
#applications/mod_fsk
#applications/mod_ladspa
codecs/mod_g723_1
codecs/mod_amr
#codecs/mod_amrwb

35
conf/README_IMPORTANT.txt Normal file
View File

@ -0,0 +1,35 @@
-= PLEASE READ THIS BEFORE YOU PUT A FreeSWITCH BOX INTO PRODUCTION =-
This configuration, generally known as the "default configuration" for FreeSWITCH, is *NOT* designed to be put into a production environment without some important modifications. Please keep in mind that the default configuration is designed to demonstrate what FreeSWITCH *can* do, not what it *should* do in your specific scenario.
*** SECURING YOUR SERVER ***
By default, FreeSWITCH starts up and does a NATPMP and UPnP request to your router. If your router supports either of these protocols then FreeSWITCH does two things:
#1 - It gets the external IP address, which it uses for SIP communications
#2 - It causes there to be a "pinhole" opened up in the router allowing inbound communications to your FreeSWITCH server
Please re-read #2. Now, please re-read #2 again. If you do not want a pinhole coming through your router then DO NOT USE the "auto-nat" tools. The way to disable the auto-nat (that is, UPnP/NATPMP) checking is to start FreeSWITCH with the "-nonat" flag. Easy enough.
If you are planning on putting a system into production then you had better pay attention to security in other areas as well. If you are behind a firewall then make sure your firewall is actually protecting you. If you have your server on a public-facing Internet connection then we recommend a few things:
#1 - Consider using iptables (Linux/Unix)
#2 - Consider using fail2ban (see http://wiki.freeswitch.org/wiki/Fail2ban)
*** SECURING YOUR USERS ***
By default, the static XML files have 20 "directory users" in conf/directory/10xx.xml, numbered 1000-1019. Also, the default dialplan has routing for calls to those same extension numbers. (NOTE: the directory and the dialplan are 100% separate concepts. Check out chapters 3-5 of the awesome FreeSWITCH book for details.)
The default users all have *very* simple passwords for SIP credentials and voicemail. If you put those into a production system then you are either brave, ignorant, or stupid. Please don't be any of those three things! You have a few choices for handling your users:
#1 - Delete the static XML files and use mod_xml_curl for dynamic users from a back-end database
#2 - Manually edit the static XML user directory files and modify the passwords
#3 - Run the handy randomize-passwords.pl script found in scripts/perl/ subdirectory under the main FreeSWITCH source directory
*** GETTING HELP ***
FreeSWITCH has a thriving on-line community - we welcome you to join us!
IRC: #freeswitch on irc.freenode.net
Mailing List: freeswitch-users on lists.freeswitch.org
You can also get professional FreeSWITCH assistance by visiting http://www.freeswitchsolutions.com or sending an email to consulting@freeswitch.org.
Happy FreeSWITCHing!

View File

@ -64,6 +64,9 @@
<!-- SNOM Module -->
<!--<load module="mod_snom"/>-->
<!-- This one only works on Linux for now -->
<!--<load module="mod_ladspa"/>-->
<!-- Dialplan Interfaces -->
<!-- <load module="mod_dialplan_directory"/> -->
<load module="mod_dialplan_xml"/>

View File

@ -0,0 +1,77 @@
<include>
<X-PRE-PROCESS cmd="set" data="AT_EPENT1=0 0 0 -1 -1 0 -1 0 -1 -1 0 -1"/>
<X-PRE-PROCESS cmd="set" data="AT_EPENT2=1 1 1 -1 -1 1 -1 1 -1 -1 1 -1"/>
<X-PRE-PROCESS cmd="set" data="AT_CPENT1=0 -1 -1 0 -1 0 0 0 -1 -1 0 -1"/>
<X-PRE-PROCESS cmd="set" data="AT_CPENT2=1 -1 -1 1 -1 1 1 1 -1 -1 1 -1"/>
<X-PRE-PROCESS cmd="set" data="AT_CMAJ1=0 -1 0 0 -1 0 -1 0 0 -1 0 -1"/>
<X-PRE-PROCESS cmd="set" data="AT_CMAJ2=1 -1 1 1 -1 1 -1 1 1 -1 1 -1"/>
<X-PRE-PROCESS cmd="set" data="AT_BBLUES=1 -1 1 -1 -1 1 -1 1 1 1 -1 -1"/>
<X-PRE-PROCESS cmd="set" data="ATGPENT2=-1 1 -1 1 -1 1 -1 -1 1 -1 1 -1"/>
<extension name="101">
<condition field="destination_number" expression="^101$">
<!-- AUTOTALENT DEFAULTS -->
<!--
<action application="set" data="AT_TUNE=440"/>
<action application="set" data="AT_FIXED=0"/>
<action application="set" data="AT_PULL=0"/>
<action application="set" data="AT_A=0"/>
<action application="set" data="AT_Bb=-1"/>
<action application="set" data="AT_B=0"/>
<action application="set" data="AT_C=0"/>
<action application="set" data="AT_Db=-1"/>
<action application="set" data="AT_D=0"/>
<action application="set" data="AT_Eb=-1"/>
<action application="set" data="AT_E=0"/>
<action application="set" data="AT_F=0"/>
<action application="set" data="AT_Gb=-1"/>
<action application="set" data="AT_G=0"/>
<action application="set" data="AT_Ab=-1"/>
<action application="set" data="AT_AMOUNT=1"/>
<action application="set" data="AT_SMOOTH=0"/>
<action application="set" data="AT_SHIFT=0"/>
<action application="set" data="AT_OUTSCALE=0"/>
<action application="set" data="AT_LFODEPTH=0"/>
<action application="set" data="AT_LFORATE=5"/>
<action application="set" data="AT_LFOSHAPE=0"/>
<action application="set" data="AT_LFOSYMM=0"/>
<action application="set" data="AT_LFOQUANT=0"/>
<action application="set" data="AT_FCORR=0"/>
<action application="set" data="AT_FWARP=0"/>
<action application="set" data="AT_MIX=1"/>
-->
<action application="set" data="AT_TUNE=440"/>
<action application="set" data="AT_FIXED=0"/>
<action application="set" data="AT_PULL=0"/>
<action application="set" data="AT_AMOUNT=1"/>
<action application="set" data="AT_SMOOTH=0"/>
<action application="set" data="AT_SHIFT=1"/>
<action application="set" data="AT_OUTSCALE=0"/>
<action application="set" data="AT_LFODEPTH=0"/>
<action application="set" data="AT_LFORATE=5"/>
<action application="set" data="AT_LFOSHAPE=0"/>
<action application="set" data="AT_LFOSYMM=0"/>
<action application="set" data="AT_LFOQUANT=0"/>
<action application="set" data="AT_FCORR=0"/>
<action application="set" data="AT_FWARP=0"/>
<action application="set" data="AT_MIX=1"/>
<!-- you have to download the ladspa package and the desired plugins from their desired site -->
<action application="set"><![CDATA[ladspa_params=${AT_TUNE} ${AT_FIXED} ${AT_PULL} ${AT_EPENT2} ${AT_AMOUNT} ${AT_SMOOTH} ${AT_SHIFT} ${AT_OUTSCALE} ${AT_LFODEPTH} ${AT_LFORATE} ${AT_LFOSHAPE} ${AT_LFOSYMM} ${AT_LFOQUANT} ${AT_FCORR} ${AT_FWARP} ${AT_MIX}]]></action>
<action application="ladspa_run" data="r|autotalent||${ladspa_params}"/>
<action application="ladspa_run" data="r|tap_chorusflanger||"/>
<action application="ladspa_run" data="r|phasers_1217.so|autoPhaser|"/>
<action application="bridge" data="sofia/internal/888@conference.freeswitch.org"/>
</condition>
</extension>
</include>

View File

@ -342,6 +342,13 @@
<!-- Turn on a jitterbuffer for every call -->
<!-- <param name="auto-jitterbuffer-msec" value="60"/> -->
<!-- By default mod_sofia will ignore the codecs in the sdp for hold/unhold operations
Set this to true if you want to actually parse the sdp and re-negotiate the codec during hold/unhold.
It's probably not what you want so stick with the default unless you really need to change this.
-->
<!--<param name="renegotiate-codec-on-hold" value="true"/>-->
</settings>
</profile>

View File

@ -1,3 +1,5 @@
opt/freeswitch/conf/autoload_configs/python.conf.xml
opt/freeswitch/mod/mod_python.so*
usr/lib/python2.*/*-packages/freeswitch.py*
usr/lib/python2.*/*-packages/ESL.py*
usr/lib/python2.*/*-packages/_ESL.so*

1
debian/rules vendored
View File

@ -208,6 +208,7 @@ install: build
dh_installdirs -A
VERBOSE=1 $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
cd libs/esl && VERBOSE=1 $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install && cd -
# Build architecture-independent files here.

View File

@ -428,6 +428,7 @@
<!-- The following phrases still need to be recorded -->
<prompt phrase="You are caller number one. Of course, *every* caller is number one in our book so you may be waiting a while." filename="ivr-youre_number_one.wav"/>
<prompt phrase="...has called emergency services" filename="ivr-has_called_emergency_services.wav"/>
</ivr>
<misc>
<prompt phrase="This call has been secured" filename="call_secured.wav"/>

22
libs/.gitignore vendored
View File

@ -1104,3 +1104,25 @@
/tiff-3.8.2/a.out.dSYM/
/tiff-3.8.2/tiff-Makefile.tgz
/unimrcp/a.out.dSYM/
/esl/fs_cli.dSYM/
/esl/ivrd.dSYM/
/esl/testclient.dSYM/
/esl/testserver.dSYM/
/openssl-1.0.0a/
/esl/Debug/
/esl/Release/
/freetdm/msvc/Release/
/freetdm/msvc/Debug/
/spandsp/src/msvc/All/BuildLog make_at_dictionary.htm
/spandsp/src/msvc/All/BuildLog make_modem_filter.htm
BuildLog*.htm
/win32/tmp*.bat
/speex/win32/VS2008/libspeex/*/*/libspeex.log
/speex/win32/VS2008/libspeexdsp/*/*/libspeexdsp.log
/win32/celt/*/*/libcelt.log
/win32/libg722_1/*/*/libg722_1.log
/win32/libshout/*/*/libshout.log

View File

@ -16,7 +16,9 @@ SOLINK=-shared -Xlinker -x
# comment the next line to disable c++ (no swig mods for you then)
OBJS += src/esl_oop.o
all: $(MYLIB) fs_cli testclient testserver ivrd
all: $(MYLIB) fs_cli testclient testserver ivrd pymod
install: pymod-install
$(MYLIB): $(OBJS) $(HEADERS) $(SRC)
ar rcs $(MYLIB) $(OBJS)
@ -92,6 +94,9 @@ javamod: $(MYLIB)
managedmod: $(MYLIB)
$(MAKE) MYLIB="../$(MYLIB)" SOLINK="$(SOLINK)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CXX_CFLAGS="$(CXX_CFLAGS)" -C managed
perlmod-install: perlmod
$(MAKE) -C perl install
phpmod-install: phpmod
$(MAKE) -C php install

View File

@ -577,7 +577,7 @@ static int usage(char *name){
printf(" -P, --port=port Port to connect (1 - 65535)\n");
printf(" -u, --user=user@domain user@domain\n");
printf(" -p, --password=password Password\n");
printf(" -i, --interrupt Allow Control-c to interrupt");
printf(" -i, --interrupt Allow Control-c to interrupt\n");
printf(" -x, --execute=command Execute Command and Exit\n");
printf(" -l, --loglevel=command Log Level\n");
printf(" -q, --quiet Disable logging\n");

View File

@ -1,4 +1,5 @@
PERL=$(shell which perl)
PERL_SITEDIR=$(shell perl -MConfig -e 'print $$Config{sitelibexp}')
PERL_LIBDIR=-L$(shell perl -MConfig -e 'print $$Config{archlib}')/CORE
PERL_LIBS=$(shell perl -MConfig -e 'print $$Config{libs}')
LOCAL_CFLAGS=-w -DMULTIPLICITY $(shell $(PERL) -MExtUtils::Embed -e ccopts) -DEMBED_PERL
@ -30,3 +31,8 @@ swigclean:
reswig: swigclean esl_wrap.cpp perlxsi.c
install: ESL.so
install -m 755 ESL.so $(PERL_SITEDIR)
install -m 755 ESL.pm $(PERL_SITEDIR)
install -d -m 755 ESL $(PERL_SITEDIR)/ESL
install -m 755 ESL/* $(PERL_SITEDIR)/ESL

View File

@ -934,7 +934,6 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
goto fail;
}
esl_event_safe_destroy(&handle->last_event);
esl_event_safe_destroy(&handle->last_ievent);
if (check_q && handle->race_event) {
@ -1053,6 +1052,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
*save_event = revent;
revent = NULL;
} else {
esl_event_safe_destroy(&handle->last_event);
handle->last_event = revent;
}

View File

@ -29,3 +29,8 @@ testtones
!/sample/boost/Makefile
!/sample/dso/Makefile
freetdm.2010.sdf
/mod_freetdm/Win32/
/msvc/Win32/
/src/ftmod/*/Win32/
/src/ftmod/*/x64/

View File

@ -20,6 +20,9 @@ cpu_reset_alarm_threshold => 70
; cpu_alarm_action => warn,reject
cpu_alarm_action => warn
; Where to dump DTMF debug files (see per span debugdtmf=yes option)
debugdtmf_directory=/full/path/to/dtmf/directory
; spans are defined with [span <span type> <span name>]
; the span type can either be zt, wanpipe or pika
; the span name can be any unique string

View File

@ -1,4 +1,13 @@
[defaults]
; User space interval at which data will be delivered
codec_ms => 20
; wink and flash interval
wink_ms => 150
flash_ms => 750
; size of the driver queue of elements of MTU size
; typical case is 10 elements of 80 bytes each (10ms of ulaw/alaw)
; don't mess with this if you don't know what you're doing
; txqueue_size => 10
; rxqueue_size => 10

View File

@ -3621,8 +3621,9 @@ void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *
"ftdm trace <path> <span_id|span_name> [<chan_id>]\n" \
"ftdm notrace <span_id|span_name> [<chan_id>]\n" \
"ftdm q931_pcap <span_id> on|off [pcapfilename without suffix]\n" \
"ftdm gains <txgain> <rxgain> <span_id> [<chan_id>]\n" \
"ftdm gains <rxgain> <txgain> <span_id> [<chan_id>]\n" \
"ftdm dtmf on|off <span_id> [<chan_id>]\n" \
"ftdm queuesize <rxsize> <txsize> <span_id> [<chan_id>]\n" \
"--------------------------------------------------------------------------------\n"
SWITCH_STANDARD_API(ft_function)
{
@ -4059,7 +4060,7 @@ SWITCH_STANDARD_API(ft_function)
ftdm_channel_t *chan;
ftdm_span_t *span = NULL;
if (argc < 4) {
stream->write_function(stream, "-ERR Usage: ft gains <txgain> <rxgain> <span_id> [<chan_id>]\n");
stream->write_function(stream, "-ERR Usage: ftdm gains <rxgain> <txgain> <span_id> [<chan_id>]\n");
goto end;
}
ftdm_span_find_by_name(argv[3], &span);
@ -4094,6 +4095,50 @@ SWITCH_STANDARD_API(ft_function)
}
}
stream->write_function(stream, "+OK gains set to Rx %f and Tx %f\n", rxgain, txgain);
} else if (!strcasecmp(argv[0], "queuesize")) {
unsigned int i = 0;
uint32_t rxsize = 10;
uint32_t txsize = 10;
uint32_t chan_id = 0;
uint32_t ccount = 0;
ftdm_channel_t *chan;
ftdm_span_t *span = NULL;
if (argc < 4) {
stream->write_function(stream, "-ERR Usage: ftdm queuesize <rxsize> <txsize> <span_id> [<chan_id>]\n");
goto end;
}
ftdm_span_find_by_name(argv[3], &span);
if (!span) {
stream->write_function(stream, "-ERR invalid span\n");
goto end;
}
if (argc > 4) {
chan_id = atoi(argv[4]);
if (chan_id > ftdm_span_get_chan_count(span)) {
stream->write_function(stream, "-ERR invalid chan\n");
goto end;
}
}
i = sscanf(argv[1], "%u", &rxsize);
i += sscanf(argv[2], "%u", &txsize);
if (i != 2) {
stream->write_function(stream, "-ERR invalid queue sizes provided\n");
goto end;
}
if (chan_id) {
chan = ftdm_span_get_channel(span, chan_id);
ftdm_channel_command(chan, FTDM_COMMAND_SET_RX_QUEUE_SIZE, &rxsize);
ftdm_channel_command(chan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &txsize);
} else {
ccount = ftdm_span_get_chan_count(span);
for (i = 1; i < ccount; i++) {
chan = ftdm_span_get_channel(span, i);
ftdm_channel_command(chan, FTDM_COMMAND_SET_RX_QUEUE_SIZE, &rxsize);
ftdm_channel_command(chan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &txsize);
}
}
stream->write_function(stream, "+OK queue sizes set to Rx %d and Tx %d\n", rxsize, txsize);
} else if (!strcasecmp(argv[0], "restart")) {
uint32_t chan_id = 0;
ftdm_channel_t *chan;
@ -4243,6 +4288,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load)
switch_console_set_complete("add ftdm notrace");
switch_console_set_complete("add ftdm q931_pcap");
switch_console_set_complete("add ftdm gains");
switch_console_set_complete("add ftdm queuesize");
switch_console_set_complete("add ftdm dtmf on");
switch_console_set_complete("add ftdm dtmf off");
switch_console_set_complete("add ftdm core state");

View File

@ -244,6 +244,7 @@ static struct {
ftdm_caller_data_t *call_ids[MAX_CALLIDS+1];
ftdm_mutex_t *call_id_mutex;
uint32_t last_call_id;
char dtmfdebug_directory[1024];
} globals;
enum ftdm_enum_cpu_alarm_action_flags
@ -3458,7 +3459,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, cons
if (!ftdmchan->dtmfdbg.file) {
struct tm currtime;
time_t currsec;
char dfile[512];
char dfile[1024];
currsec = time(NULL);
@ -3469,10 +3470,18 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, cons
localtime_r(&currsec, &currtime);
#endif
snprintf(dfile, sizeof(dfile), "dtmf-s%dc%d-20%d-%d-%d-%d:%d:%d.%s",
ftdmchan->span_id, ftdmchan->chan_id,
currtime.tm_year-100, currtime.tm_mon+1, currtime.tm_mday,
currtime.tm_hour, currtime.tm_min, currtime.tm_sec, ftdmchan->native_codec == FTDM_CODEC_ULAW ? "ulaw" : ftdmchan->native_codec == FTDM_CODEC_ALAW ? "alaw" : "sln");
if (ftdm_strlen_zero(globals.dtmfdebug_directory)) {
snprintf(dfile, sizeof(dfile), "dtmf-s%dc%d-20%d-%d-%d-%d:%d:%d.%s",
ftdmchan->span_id, ftdmchan->chan_id,
currtime.tm_year-100, currtime.tm_mon+1, currtime.tm_mday,
currtime.tm_hour, currtime.tm_min, currtime.tm_sec, ftdmchan->native_codec == FTDM_CODEC_ULAW ? "ulaw" : ftdmchan->native_codec == FTDM_CODEC_ALAW ? "alaw" : "sln");
} else {
snprintf(dfile, sizeof(dfile), "%s/dtmf-s%dc%d-20%d-%d-%d-%d:%d:%d.%s",
globals.dtmfdebug_directory,
ftdmchan->span_id, ftdmchan->chan_id,
currtime.tm_year-100, currtime.tm_mon+1, currtime.tm_mday,
currtime.tm_hour, currtime.tm_min, currtime.tm_sec, ftdmchan->native_codec == FTDM_CODEC_ULAW ? "ulaw" : ftdmchan->native_codec == FTDM_CODEC_ALAW ? "alaw" : "sln");
}
ftdmchan->dtmfdbg.file = fopen(dfile, "wb");
if (!ftdmchan->dtmfdbg.file) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "failed to open debug dtmf file %s\n", dfile);
@ -4686,6 +4695,9 @@ static ftdm_status_t load_config(void)
globals.cpu_monitor.alarm_action_flags |= FTDM_CPU_ALARM_ACTION_WARN;
}
}
} else if (!strncasecmp(var, "debugdtmf_directory", sizeof("debugdtmf_directory")-1)) {
ftdm_set_string(globals.dtmfdebug_directory, val);
ftdm_log(FTDM_LOG_DEBUG, "Debug DTMF directory set to '%s'\n", globals.dtmfdebug_directory);
} else if (!strncasecmp(var, "cpu_monitoring_interval", sizeof("cpu_monitoring_interval")-1)) {
if (atoi(val) > 0) {
globals.cpu_monitor.interval = atoi(val);

View File

@ -943,12 +943,12 @@ static int on_proceeding(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_
if (chan) {
/* Open channel if inband information is available */
if ((pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) && !ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n",
if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, B-Channel %d:%d\n",
ftdm_channel_get_span_id(chan),
ftdm_channel_get_id(chan));
if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN) && (ftdm_channel_open_chan(chan) != FTDM_SUCCESS)) {
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n",
@ -985,12 +985,12 @@ static int on_progress(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev
if (chan) {
/* Open channel if inband information is available */
if ((pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) && !ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n",
if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, B-Channel %d:%d\n",
ftdm_channel_get_span_id(chan),
ftdm_channel_get_id(chan));
if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN) && (ftdm_channel_open_chan(chan) != FTDM_SUCCESS)) {
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n",
@ -1028,8 +1028,6 @@ static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->ringing.channel);
if (chan) {
ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d\n", ftdm_span_get_id(span), pevent->ringing.channel);
/* we may get on_ringing even when we're already in FTDM_CHANNEL_STATE_PROGRESS_MEDIA */
// if (ftdm_channel_get_state(chan) == FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
// /* dont try to move to STATE_PROGRESS to avoid annoying veto warning */
@ -1037,12 +1035,12 @@ static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
// }
/* Open channel if inband information is available */
if ((pevent->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) && !ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n",
if ((pevent->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, B-Channel %d:%d\n",
ftdm_channel_get_span_id(chan),
ftdm_channel_get_id(chan));
if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN) && (ftdm_channel_open_chan(chan) != FTDM_SUCCESS)) {
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n",
@ -1053,9 +1051,13 @@ static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING);
goto out;
}
ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d with media\n", ftdm_span_get_id(span), pevent->proceeding.channel);
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} else {
// ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS);
ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d\n", ftdm_span_get_id(span), pevent->proceeding.channel);
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RINGING);
}
// ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS);
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RINGING);
} else {
ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d but it's not in the span?\n",
ftdm_span_get_id(span), pevent->ringing.channel);

View File

@ -118,7 +118,7 @@
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;C:\Program Files\sangoma\sng_isdn\include&quot;;../../include;&quot;C:\Program Files\Sangoma\include&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="2"

View File

@ -134,7 +134,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@ -157,7 +157,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>

View File

@ -333,7 +333,8 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
parse_yesno(var, val, &signal_data->setup_arb);
} else if (!strcasecmp(var, "facility")) {
parse_yesno(var, val, &signal_data->facility);
} else if (!strcasecmp(var, "min_digits")) {
} else if (!strcasecmp(var, "min-digits") ||
!strcasecmp(var, "min_digits")) {
signal_data->min_digits = atoi(val);
} else if (!strcasecmp(var, "outbound-called-ton")) {
ftdm_set_ton(val, &span->default_caller_data.dnis.type);
@ -347,11 +348,11 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
ftdm_set_ton(val, &span->default_caller_data.rdnis.type);
} else if (!strcasecmp(var, "outbound-rdnis-npi")) {
ftdm_set_npi(val, &span->default_caller_data.rdnis.plan);
} else if (!strcasecmp(var, "outbound-bearer_cap") ||
!strcasecmp(var, "outbound-bc-transfer-cap")) {
} else if (!strcasecmp(var, "outbound-bc-transfer-cap") ||
!strcasecmp(var, "outbound-bearer_cap")) {
ftdm_set_bearer_capability(val, (uint8_t*)&span->default_caller_data.bearer_capability);
} else if (!strcasecmp(var, "outbound-bearer_layer1") ||
!strcasecmp(var, "outbound-bc-user-layer1")) {
} else if (!strcasecmp(var, "outbound-bc-user-layer1") ||
!strcasecmp(var, "outbound-bearer_layer1")) {
ftdm_set_bearer_layer1(val, (uint8_t*)&span->default_caller_data.bearer_layer1);
} else if (!strcasecmp(var, "channel-restart-on-link-up")) {
parse_yesno(var, val, &signal_data->restart_opt);

View File

@ -677,20 +677,20 @@ void sngisdn_rcv_q921_ind(BdMngmt *status)
}
switch (status->t.usta.alarm.category) {
case (LCM_CATEGORY_INTERFACE):
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
ftdmspan->name,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
case (LCM_CATEGORY_PROTOCOL):
ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
ftdmspan->name,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
break;
default:
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
ftdmspan->name,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
ftdmspan->name,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
switch (status->t.usta.alarm.event) {
case ENTR_CONG: /* Entering Congestion */
ftdm_log(FTDM_LOG_WARNING, "s%d: Entering Congestion\n", ftdmspan->span_id);

View File

@ -114,7 +114,7 @@ void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace
{
char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
sngisdn_decode_q921(data_str, data, data_len);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] s%d FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
ftdm_safe_free(data_str);
}

View File

@ -91,6 +91,8 @@ typedef enum {
*/
static struct {
uint32_t codec_ms;
uint32_t rxqueue_size;
uint32_t txqueue_size;
uint32_t wink_ms;
uint32_t flash_ms;
uint32_t ring_on_ms;
@ -406,6 +408,20 @@ static FIO_CONFIGURE_FUNCTION(wanpipe_configure)
} else {
wp_globals.codec_ms = num;
}
} else if (!strcasecmp(var, "rxqueue_size")) {
num = atoi(val);
if (num < 1 || num > 1000) {
ftdm_log(FTDM_LOG_WARNING, "invalid rx queue size at line %d\n", lineno);
} else {
wp_globals.rxqueue_size = num;
}
} else if (!strcasecmp(var, "txqueue_size")) {
num = atoi(val);
if (num < 1 || num > 1000) {
ftdm_log(FTDM_LOG_WARNING, "invalid tx queue size at line %d\n", lineno);
} else {
wp_globals.txqueue_size = num;
}
} else if (!strcasecmp(var, "wink_ms")) {
num = atoi(val);
if (num < 50 || num > 3000) {
@ -544,6 +560,13 @@ static FIO_OPEN_FUNCTION(wanpipe_open)
ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL);
ftdmchan->effective_interval = ftdmchan->native_interval = wp_globals.codec_ms;
ftdmchan->packet_len = ftdmchan->native_interval * 8;
if (wp_globals.txqueue_size > 0) {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &wp_globals.txqueue_size);
}
if (wp_globals.rxqueue_size > 0) {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_RX_QUEUE_SIZE, &wp_globals.rxqueue_size);
}
}
return FTDM_SUCCESS;
@ -1315,14 +1338,12 @@ static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fc
status = FTDM_BREAK;
} else {
ftdm_status_t status;
wanpipe_tdm_api_t onhook_tdm_api;
memset(&onhook_tdm_api, 0, sizeof(onhook_tdm_api));
status = sangoma_tdm_txsig_onhook(fchan->sockfd, &onhook_tdm_api);
status = sangoma_tdm_txsig_onhook(fchan->sockfd, tdm_api);
if (status) {
snprintf(fchan->last_error, sizeof(fchan->last_error), "ONHOOK Failed");
return FTDM_FAIL;
}
*event_id = onhook_tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_ONHOOK : FTDM_OOB_NOOP;
*event_id = tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_ONHOOK : FTDM_OOB_NOOP;
}
}
break;
@ -1575,6 +1596,9 @@ static FIO_IO_LOAD_FUNCTION(wanpipe_init)
wp_globals.flash_ms = 750;
wp_globals.ring_on_ms = 2000;
wp_globals.ring_off_ms = 4000;
/* 0 for queue size will leave driver defaults */
wp_globals.txqueue_size = 0;
wp_globals.rxqueue_size = 0;
wanpipe_interface.name = "wanpipe";
wanpipe_interface.configure_span = wanpipe_configure_span;
wanpipe_interface.configure = wanpipe_configure;

View File

@ -1064,6 +1064,20 @@ static __inline__ ftdm_status_t zt_channel_process_event(ftdm_channel_t *fchan,
fchan->rx_cas_bits = bits;
}
break;
case ZT_EVENT_BADFCS:
{
ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Bad frame checksum (ZT_EVENT_BADFCS)!\n");
/* What else could we do? */
*event_id = FTDM_OOB_NOOP;
}
break;
case ZT_EVENT_OVERRUN:
{
ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Driver overrun! (ZT_EVENT_OVERRUN)\n");
/* What else could we do? */
*event_id = FTDM_OOB_NOOP;
}
break;
case ZT_EVENT_NONE:
{
ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "No event\n");

View File

@ -384,9 +384,12 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
}
while(xml) {
char *type = xtype ? xtype : iks_find_attrib(xml, "type");
char *type = NULL;
iks *tag;
if (iks_type(xml)!=IKS_CDATA)
type = xtype ? xtype : iks_find_attrib(xml, "type");
if (type) {
if (!strcasecmp(type, "redirect")) {
@ -994,9 +997,9 @@ static int on_commands(void *user_data, ikspak *pak)
uint8_t is_result = strcasecmp(type, "result") ? 0 : 1;
uint8_t is_error = strcasecmp(type, "error") ? 0 : 1;
iks *xml, *xsession, *xerror = NULL, *xredir = NULL;
struct iks_tag* tmp;
xml = iks_child (pak->x);
tmp = (struct iks_tag*) xml;
if (is_error) {
if ((xerror = working_find(xml, "error"))) {
char *code = iks_find_attrib(xerror, "code");

View File

@ -1 +1 @@
Wed Nov 3 13:53:34 EDT 2010
Tue Mar 8 12:40:45 CST 2011

View File

@ -7781,7 +7781,7 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent,
if (tpn) {
/* CANCEL or ACK to [3456]XX */
invalid = tport_name_dup(home, orq->orq_tpn, tpn);
#if HAVE_SOFIA_SRESOLV
#if 0 //HAVE_SOFIA_SRESOLV
/* We send ACK or CANCEL only if original request was really sent */
assert(tport_name_is_resolved(orq->orq_tpn));
#endif

View File

@ -652,6 +652,7 @@ static __inline__ void force_drop_rx_bits(t4_state_t *s, int bits)
static int rx_put_bits(t4_state_t *s, uint32_t bit_string, int quantity)
{
int bits;
int old_a0;
/* We decompress bit by bit, as the data stream is received. We need to
scan continuously for EOLs, so we might as well work this way. */
@ -809,8 +810,23 @@ static int rx_put_bits(t4_state_t *s, uint32_t bit_string, int quantity)
s->t4_t6_rx.a0,
s->t4_t6_rx.b1,
s->t4_t6_rx.run_length);
s->t4_t6_rx.run_length += (s->t4_t6_rx.b1 - s->t4_t6_rx.a0 + t4_2d_table[bits].param);
old_a0 = s->t4_t6_rx.a0;
s->t4_t6_rx.a0 = s->t4_t6_rx.b1 + t4_2d_table[bits].param;
/* We need to check if a bad or malicious image is failing to move forward along the row.
Going back is obviously bad. We also need to avoid a stall on the spot, except for the
special case of the start of the row. Zero movement as the very first element in the
row is perfectly normal. */
if (s->t4_t6_rx.a0 <= old_a0)
{
if (s->t4_t6_rx.a0 < old_a0 || s->t4_t6_rx.b_cursor > 1)
{
/* Undo the update we just started, and carry on as if this code does not exist */
/* TODO: we really should record that something wasn't right at this point. */
s->t4_t6_rx.a0 = old_a0;
break;
}
}
s->t4_t6_rx.run_length += (s->t4_t6_rx.a0 - old_a0);
add_run_to_row(s);
/* We need to move one step in one direction or the other, to change to the
opposite colour */
@ -832,8 +848,9 @@ static int rx_put_bits(t4_state_t *s, uint32_t bit_string, int quantity)
s->ref_runs[s->t4_t6_rx.b_cursor],
s->ref_runs[s->t4_t6_rx.b_cursor + 1]);
s->t4_t6_rx.b1 += s->ref_runs[s->t4_t6_rx.b_cursor++];
s->t4_t6_rx.run_length += (s->t4_t6_rx.b1 - s->t4_t6_rx.a0);
old_a0 = s->t4_t6_rx.a0;
s->t4_t6_rx.a0 = s->t4_t6_rx.b1;
s->t4_t6_rx.run_length += (s->t4_t6_rx.a0 - old_a0);
s->t4_t6_rx.b1 += s->ref_runs[s->t4_t6_rx.b_cursor++];
break;
case S_Ext:

View File

@ -428,6 +428,12 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void
i->ts_drift = ts + (i->ts_offset - timer_ts);
if (i->ts_offset && i->ts_drift > 0) {
i->ts_offset = timer_ts - ts;
i->ts_drift = ts + (i->ts_offset - timer_ts);
}
if (i->max_drift) {
if (i->ts_drift < i->max_drift) {
if (++i->drift_dropped_packets < i->drift_max_dropped) {
@ -518,8 +524,8 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void
if (stfu_log != null_logger && i->debug) {
stfu_log(STFU_LOG_EMERG, "I: %s %u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u:%u - %u %d %u %u %d %d %d/%d\n", i->name,
i->qlen, i->period_packet_in_count, i->period_time, i->consecutive_good_count,
stfu_log(STFU_LOG_EMERG, "I: %s %u/%u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u:%u - %u %d %u %u %d %d %d/%d\n", i->name,
i->qlen, i->max_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,
ts, ts / i->samples_per_packet,
i->period_missing_count, i->period_need_range_avg,

View File

@ -143,7 +143,13 @@ sub sendmsg($$$) {
}
$self->output("\n");
return $self->readhash($to);
for(;;) {
$e = $self->readhash(undef);
last if $e->{socketerror} or $e->{'content-type'} eq 'command/reply';
push @{$self->{events}}, $e;
}
return $e;
}
sub command($$) {

View File

@ -315,6 +315,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_caller_extension_masquerade(switc
*/
SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension);
SWITCH_DECLARE(void) switch_channel_flip_cid(switch_channel_t *channel);
SWITCH_DECLARE(void) switch_channel_sort_cid(switch_channel_t *channel, switch_bool_t in);
/*!

View File

@ -542,7 +542,7 @@ typedef enum {
SWITCH_RTP_FLAG_BREAK = (1 << 10),
SWITCH_RTP_FLAG_UDPTL = (1 << 11),
SWITCH_RTP_FLAG_DATAWAIT = (1 << 12),
SWITCH_RTP_FLAG_BUGGY_2833 = (1 << 13),
SWITCH_RTP_FLAG_BYTESWAP = (1 << 13),
SWITCH_RTP_FLAG_PASS_RFC2833 = (1 << 14),
SWITCH_RTP_FLAG_AUTO_CNG = (1 << 15),
SWITCH_RTP_FLAG_SECURE_SEND_RESET = (1 << 16),
@ -1107,6 +1107,8 @@ typedef enum {
CF_DIALPLAN,
CF_BLOCK_BROADCAST_UNTIL_MEDIA,
CF_CNG_PLC,
CF_ATTENDED_TRANSFER,
CF_LAZY_ATTENDED_TRANSFER,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
CF_FLAG_MAX
} switch_channel_flag_t;

1
src/mod/.gitignore vendored
View File

@ -31,6 +31,7 @@
/endpoints/mod_portaudio/Makefile.in
/endpoints/mod_skinny/Makefile
/endpoints/mod_skinny/Makefile.in
/endpoints/mod_skinny/mod_skinny.log
/endpoints/mod_skypopen/Makefile
/endpoints/mod_skypopen/Makefile.in
/endpoints/mod_sofia/Makefile

View File

@ -160,13 +160,15 @@ struct cc_member_cancel_reason_table {
typedef enum {
CC_MEMBER_CANCEL_REASON_NONE,
CC_MEMBER_CANCEL_REASON_TIMEOUT,
CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT
CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT,
CC_MEMBER_CANCEL_REASON_BREAK_OUT
} cc_member_cancel_reason_t;
static struct cc_member_cancel_reason_table MEMBER_CANCEL_REASON_CHART[] = {
{"NONE", CC_MEMBER_CANCEL_REASON_NONE},
{"TIMEOUT", CC_MEMBER_CANCEL_REASON_TIMEOUT},
{"NO_AGENT_TIMEOUT", CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT},
{"BREAK_OUT", CC_MEMBER_CANCEL_REASON_BREAK_OUT},
{NULL, 0}
};
@ -216,6 +218,7 @@ static char agents_sql[] =
" wrap_up_time INTEGER NOT NULL DEFAULT 0,\n"
" reject_delay_time INTEGER NOT NULL DEFAULT 0,\n"
" busy_delay_time INTEGER NOT NULL DEFAULT 0,\n"
" no_answer_delay_time INTEGER NOT NULL DEFAULT 0,\n"
" last_bridge_start INTEGER NOT NULL DEFAULT 0,\n"
" last_bridge_end INTEGER NOT NULL DEFAULT 0,\n"
" last_offered_call INTEGER NOT NULL DEFAULT 0,\n"
@ -705,6 +708,7 @@ static cc_queue_t *load_queue(const char *queue_name)
switch_cache_db_test_reactive(dbh, "select count(ready_time) from agents", NULL, "alter table agents add ready_time integer not null default 0;"
"alter table agents add reject_delay_time integer not null default 0;"
"alter table agents add busy_delay_time integer not null default 0;");
switch_cache_db_test_reactive(dbh, "select count(no_answer_delay_time) from agents", NULL, "alter table agents add no_answer_delay_time integer not null default 0;");
switch_cache_db_test_reactive(dbh, "select count(ready_time) from agents", "drop table agents", agents_sql);
switch_cache_db_test_reactive(dbh, "select count(queue) from tiers", "drop table tiers" , tiers_sql);
switch_mutex_init(&queue->mutex, SWITCH_MUTEX_NESTED, queue->pool);
@ -768,6 +772,7 @@ struct call_helper {
int max_no_answer;
int reject_delay_time;
int busy_delay_time;
int no_answer_delay_time;
switch_memory_pool_t *pool;
};
@ -1007,6 +1012,12 @@ cc_status_t cc_agent_update(const char *key, const char *value, const char *agen
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
result = CC_STATUS_SUCCESS;
} else if (!strcasecmp(key, "no_answer_delay_time")) {
sql = switch_mprintf("UPDATE agents SET no_answer_delay_time = '%ld', system = 'single_box' WHERE name = '%q'", atol(value), agent);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
result = CC_STATUS_SUCCESS;
} else if (!strcasecmp(key, "type")) {
if (strcasecmp(value, CC_AGENT_TYPE_CALLBACK) && strcasecmp(value, CC_AGENT_TYPE_UUID_STANDBY)) {
@ -1203,6 +1214,7 @@ static switch_status_t load_agent(const char *agent_name)
const char *wrap_up_time = switch_xml_attr(x_agent, "wrap-up-time");
const char *reject_delay_time = switch_xml_attr(x_agent, "reject-delay-time");
const char *busy_delay_time = switch_xml_attr(x_agent, "busy-delay-time");
const char *no_answer_delay_time = switch_xml_attr(x_agent, "no-answer-delay-time");
if (type) {
cc_status_t res = cc_agent_add(agent_name, type);
@ -1225,6 +1237,9 @@ static switch_status_t load_agent(const char *agent_name)
if (busy_delay_time) {
cc_agent_update("busy_delay_time", busy_delay_time, agent_name);
}
if (no_answer_delay_time) {
cc_agent_update("no_answer_delay_time", no_answer_delay_time, agent_name);
}
if (type && res == CC_STATUS_AGENT_ALREADY_EXIST) {
cc_agent_update("type", type, agent_name);
@ -1384,8 +1399,6 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent", "%s", h->agent_name);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent_type", "%s", h->agent_type);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "ignore_early_media", "true");
/* Force loopback to remain live, if not, the loop will detect the actual channel to gone */
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "loopback_bowout", "false");
t_agent_called = switch_epoch_time_now(NULL);
dialstr = switch_mprintf("%s", h->originate_string);
@ -1430,9 +1443,36 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
const char *agent_uuid = switch_core_session_get_uuid(agent_session);
switch_channel_t *member_channel = switch_core_session_get_channel(member_session);
switch_channel_t *agent_channel = switch_core_session_get_channel(agent_session);
const char *other_loopback_leg_uuid = switch_channel_get_variable(agent_channel, "other_loopback_leg_uuid");
switch_channel_set_variable(agent_channel, "cc_member_pre_answer_uuid", NULL);
/* Loopback special case */
if (other_loopback_leg_uuid) {
switch_core_session_t *other_loopback_session = switch_core_session_locate(other_loopback_leg_uuid);
if (other_loopback_session) {
switch_channel_t *other_loopback_channel = switch_core_session_get_channel(other_loopback_session);
const char *real_uuid = switch_channel_get_variable(other_loopback_channel, SWITCH_SIGNAL_BOND_VARIABLE);
switch_channel_set_variable(other_loopback_channel, "cc_member_pre_answer_uuid", NULL);
/* Switch the agent session */
if (real_uuid) {
switch_core_session_rwunlock(agent_session);
agent_uuid = real_uuid;
agent_session = switch_core_session_locate(agent_uuid);
agent_channel = switch_core_session_get_channel(agent_session);
switch_channel_set_variable(agent_channel, "cc_queue", h->queue_name);
switch_channel_set_variable(agent_channel, "cc_agent", h->agent_name);
switch_channel_set_variable(agent_channel, "cc_agent_type", h->agent_type);
switch_channel_set_variable(agent_channel, "cc_member_uuid", h->member_uuid);
}
switch_core_session_rwunlock(other_loopback_session);
}
}
if (!strcasecmp(h->queue_strategy,"ring-all")) {
char res[256];
/* Map the Agent to the member */
@ -1466,6 +1506,9 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-UUID", agent_uuid);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Called-Time", "%ld", (long) t_agent_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answered-Time", "%ld", (long) t_agent_answered);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
@ -1508,15 +1551,20 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
while(switch_channel_up(member_channel) && switch_channel_up(agent_channel) && globals.running) {
switch_yield(100000);
}
tiers_state = CC_TIER_STATE_READY;
tiers_state = CC_TIER_STATE_READY;
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(agent_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "bridge-agent-end");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Hangup-Cause", switch_channel_cause2str(cause));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-UUID", agent_uuid);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Called-Time", "%ld", (long) t_agent_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answered-Time", "%ld", (long) t_agent_answered);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Bridge-Terminated-Time", "%ld", (long) switch_epoch_time_now(NULL));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
@ -1542,23 +1590,25 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_channel_event_set_data(member_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-end");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Hangup-Cause", switch_channel_cause2str(cause));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", "Terminated");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answer-Time", "%ld", (long) (t_agent_answered - t_agent_called));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Wait-Time", "%ld", (long) (t_agent_answered - t_member_called));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Talk-Time", "%ld", (long) (switch_epoch_time_now(NULL) - t_agent_answered));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Total-Time", "%ld", (long) (switch_epoch_time_now(NULL) - t_member_called));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-UUID", agent_uuid);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Called-Time", "%ld", (long) t_agent_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answered-Time", "%ld", (long) t_agent_answered);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Leaving-Time", "%ld", (long) switch_epoch_time_now(NULL));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name",
switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number",
switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
switch_event_fire(&event);
}
} else {
int delay_next_agent_call = 0;
/* Agent didn't answer or originate failed */
int delay_next_agent_call = 0;
sql = switch_mprintf("UPDATE members SET state = '%q', serving_agent = '', serving_system = ''"
" WHERE serving_agent = '%q' AND serving_system = '%q' AND uuid = '%q' AND system = 'single_box'",
cc_member_state2str(CC_MEMBER_STATE_WAITING),
@ -1566,33 +1616,25 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Agent %s Origination Canceled : %s\n",h->agent_name, switch_channel_cause2str(cause));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Agent %s Origination Canceled : %s\n", h->agent_name, switch_channel_cause2str(cause));
switch (cause) {
case SWITCH_CAUSE_USER_NOT_REGISTERED: /* When we are calling a unregistred device */
case SWITCH_CAUSE_USER_BUSY: /* Could be the phone is in Do Not Disturb */
delay_next_agent_call = (h->busy_delay_time > delay_next_agent_call?h->busy_delay_time:delay_next_agent_call);
break;
case SWITCH_CAUSE_CALL_REJECTED: /* User could have press the reject call on their phone */
delay_next_agent_call = (h->reject_delay_time > delay_next_agent_call?h->reject_delay_time:delay_next_agent_call);
break;
default:
break;
}
switch (cause) {
case SWITCH_CAUSE_USER_NOT_REGISTERED: /* When we are calling a unregistred device */
case SWITCH_CAUSE_USER_BUSY: /* Could be the phone is in Do Not Disturb */
case SWITCH_CAUSE_CALL_REJECTED: /* User could have press the reject call on their phone */
/* When we hang-up agents that did not answer in ring-all strategy */
case SWITCH_CAUSE_ORIGINATOR_CANCEL:
if (delay_next_agent_call > 0) {
char ready_epoch[64];
switch_snprintf(ready_epoch, sizeof(ready_epoch), "%" SWITCH_TIME_T_FMT, switch_epoch_time_now(NULL) + delay_next_agent_call); /* Make the time configurable */
cc_agent_update("ready_time", ready_epoch , h->agent_name);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Agent %s Sleeping for %d secondes\n", h->agent_name, delay_next_agent_call);
}
break;
/* Busy: Do Not Disturb, Circuit congestion */
case SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION:
case SWITCH_CAUSE_USER_BUSY:
delay_next_agent_call = (h->busy_delay_time > delay_next_agent_call? h->busy_delay_time : delay_next_agent_call);
break;
/* Reject: User rejected the call */
case SWITCH_CAUSE_CALL_REJECTED:
delay_next_agent_call = (h->reject_delay_time > delay_next_agent_call? h->reject_delay_time : delay_next_agent_call);
break;
/* No answer: Destination does not answer for some other reason */
default:
delay_next_agent_call = (h->no_answer_delay_time > delay_next_agent_call? h->no_answer_delay_time : delay_next_agent_call);
tiers_state = CC_TIER_STATE_NO_ANSWER;
/* Update Agent NO Answer count */
@ -1607,6 +1649,28 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
h->agent_name, h->max_no_answer);
cc_agent_update("status", cc_agent_status2str(CC_AGENT_STATUS_ON_BREAK), h->agent_name);
}
break;
}
/* Put agent to sleep for some time if necessary */
if (delay_next_agent_call > 0) {
char ready_epoch[64];
switch_snprintf(ready_epoch, sizeof(ready_epoch), "%" SWITCH_TIME_T_FMT, switch_epoch_time_now(NULL) + delay_next_agent_call);
cc_agent_update("ready_time", ready_epoch , h->agent_name);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Agent %s sleeping for %d seconds\n", h->agent_name, delay_next_agent_call);
}
/* Fire up event when contact agent fails */
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "bridge-agent-fail");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Hangup-Cause", switch_channel_cause2str(cause));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
switch_event_fire(&event);
}
}
@ -1670,14 +1734,14 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
char *sql = NULL;
char res[256];
char *agent_status = argv[2];
char *agent_tier_state = argv[8];
char *agent_last_bridge_end = argv[9];
char *agent_wrap_up_time = argv[10];
char *agent_state = argv[11];
char *agent_ready_time = argv[12];
char *agent_tier_level = argv[13];
char *agent_type = argv[14];
char *agent_uuid = argv[15];
char *agent_tier_state = argv[9];
char *agent_last_bridge_end = argv[10];
char *agent_wrap_up_time = argv[11];
char *agent_state = argv[12];
char *agent_ready_time = argv[13];
char *agent_tier_level = argv[14];
char *agent_type = argv[15];
char *agent_uuid = argv[16];
switch_bool_t contact_agent = SWITCH_TRUE;
@ -1787,6 +1851,7 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
h->max_no_answer = atoi(argv[5]);
h->reject_delay_time = atoi(argv[6]);
h->busy_delay_time = atoi(argv[7]);
h->no_answer_delay_time = atoi(argv[8]);
cc_agent_update("state", cc_agent_state2str(CC_AGENT_STATE_RECEIVING), h->agent_name);
@ -1895,13 +1960,13 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
switch_safe_free(sql);
sql_order_by = switch_mprintf("level, position");
} else if(!strcasecmp(queue_strategy, "sequentially-by-agent-order")) {
sql_order_by = switch_mprintf("level, position");
sql_order_by = switch_mprintf("level, position, agents.last_offered_call"); /* Default to last_offered_call, let add new strategy if needing it differently */
} else {
/* If the strategy doesn't exist, just fallback to the following */
sql_order_by = switch_mprintf("level, position");
sql_order_by = switch_mprintf("level, position, agents.last_offered_call");
}
sql = switch_mprintf("SELECT system, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time,tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.level, agents.type, agents.uuid FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)"
sql = switch_mprintf("SELECT system, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.level, agents.type, agents.uuid FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)"
" WHERE tiers.queue = '%q'"
" AND (agents.status = '%q' OR agents.status = '%q' OR agents.status = '%q')"
" ORDER BY %q",
@ -2045,7 +2110,7 @@ void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj
switch_channel_set_flag_value(member_channel, CF_BREAK, 2);
}
/* Will drop the caller if no agent was found for more than X secondes */
/* Will drop the caller if no agent was found for more than X seconds */
if (queue->max_wait_time_with_no_agent > 0 && m->t_member_called < queue->last_agent_exist_check - queue->max_wait_time_with_no_agent_time_reached &&
queue->last_agent_exist_check - queue->last_agent_exist >= queue->max_wait_time_with_no_agent) {
m->member_cancel_reason = CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT;
@ -2301,52 +2366,63 @@ SWITCH_STANDARD_APP(callcenter_function)
h->running = 0;
}
/* Hangup any agents been callback */
if (!switch_channel_up(member_channel)) { /* If channel is still up, it mean that the member didn't hangup, so we should leave the agent alone */
switch_core_session_hupall_matching_var("cc_member_uuid", member_uuid, SWITCH_CAUSE_ORIGINATOR_CANCEL);
/* Check if we were removed be cause FS Core(BREAK) asked us too */
if (h->member_cancel_reason == CC_MEMBER_CANCEL_REASON_NONE && !switch_channel_get_variable(member_channel, "cc_agent_uuid")) {
h->member_cancel_reason = CC_MEMBER_CANCEL_REASON_BREAK_OUT;
}
/* Canceled for some reason */
if (!switch_channel_up(member_channel) || h->member_cancel_reason != CC_MEMBER_CANCEL_REASON_NONE) {
/* Update member state */
sql = switch_mprintf("UPDATE members SET state = '%q', uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'",
cc_member_state2str(CC_MEMBER_STATE_ABANDONED), (long) switch_epoch_time_now(NULL), member_uuid);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
/* Generate an Event and update some channel variable */
/* Hangup any callback agents */
switch_core_session_hupall_matching_var("cc_member_uuid", member_uuid, SWITCH_CAUSE_ORIGINATOR_CANCEL);
/* Generate an event */
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(member_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-end");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Wait-Time", "%ld", (long) (switch_epoch_time_now(NULL) - t_member_called));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Member \"%s\" <%s> exit queue %s due to %s\n",
switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")),
switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")),
queue_name, cc_member_cancel_reason2str(h->member_cancel_reason));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", cc_member_cancel_reason2str(h->member_cancel_reason));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Leaving-Time", "%ld", (long) switch_epoch_time_now(NULL));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", "Cancel");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cancel-Reason", cc_member_cancel_reason2str(h->member_cancel_reason));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
switch_event_fire(&event);
}
/* for xml_cdr needs */
/* Update some channel variables for xml_cdr needs */
switch_channel_set_variable_printf(member_channel, "cc_queue_canceled_epoch", "%ld", (long) switch_epoch_time_now(NULL));
switch_channel_set_variable_printf(member_channel, "cc_cause", "%s", cc_member_cancel_reason2str(h->member_cancel_reason));
switch_channel_set_variable_printf(member_channel, "cc_cause", "%s", "cancel");
switch_channel_set_variable_printf(member_channel, "cc_cancel_reason", "%s", cc_member_cancel_reason2str(h->member_cancel_reason));
/* Send Event with queue count */
cc_queue_count(queue_name);
/* Print some debug log information */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Member \"%s\" <%s> exit queue %s due to %s\n",
switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")),
switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")),
queue_name, cc_member_cancel_reason2str(h->member_cancel_reason));
} else {
switch_channel_set_variable_printf(member_channel, "cc_cause", "%s", "answered");
/* Update member state */
sql = switch_mprintf("UPDATE members SET state = '%q', bridge_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'",
cc_member_state2str(CC_MEMBER_STATE_ANSWERED), (long) switch_epoch_time_now(NULL), member_uuid);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
/* Send Event with queue count */
cc_queue_count(queue_name);
/* Update some channel variables for xml_cdr needs */
switch_channel_set_variable_printf(member_channel, "cc_cause", "%s", "answered");
}
/* Send Event with queue count */
cc_queue_count(queue_name);
end:
return;
@ -2394,18 +2470,26 @@ static int list_result_callback(void *pArg, int argc, char **argv, char **column
"callcenter_config agent set ready_time [agent_name] [wait till epoch] | "\
"callcenter_config agent set reject_delay_time [agent_name] [wait second] | "\
"callcenter_config agent set busy_delay_time [agent_name] [wait second] | "\
"callcenter_config agent set no_answer_delay_time [agent_name] [wait second] | "\
"callcenter_config agent get status [agent_name] | " \
"callcenter_config agent list | " \
"callcenter_config tier add [queue_name] [agent_name] [level] [position] | " \
"callcenter_config tier set state [queue_name] [agent_name] [state] | " \
"callcenter_config tier set level [queue_name] [agent_name] [level] | " \
"callcenter_config tier set position [queue_name] [agent_name] [position] | " \
"callcenter_config tier del [queue_name] [agent_name] | " \
"callcenter_config tier list | " \
"callcenter_config queue load [queue_name] | " \
"callcenter_config queue unload [queue_name] | " \
"callcenter_config queue reload [queue_name] | " \
"callcenter_config tier list [queue_name] | " \
"callcenter_config queue list [queue_name] | " \
"callcenter_config queue count [queue_name]"
"callcenter_config queue list | " \
"callcenter_config queue list agents [queue_name] [status] | " \
"callcenter_config queue list members [queue_name] | " \
"callcenter_config queue list tiers [queue_name] | " \
"callcenter_config queue count | " \
"callcenter_config queue count agents [queue_name] [status] | " \
"callcenter_config queue count members [queue_name] | " \
"callcenter_config queue count tiers [queue_name]"
SWITCH_STANDARD_API(cc_config_api_function)
{
@ -2513,6 +2597,7 @@ SWITCH_STANDARD_API(cc_config_api_function)
}
}
} else if (action && !strcasecmp(action, "get")) {
if (argc-initial_argc < 2) {
stream->write_function(stream, "%s", "-ERR Invalid!\n");
@ -2538,6 +2623,7 @@ SWITCH_STANDARD_API(cc_config_api_function)
}
}
} else if (action && !strcasecmp(action, "list")) {
struct list_result cbt;
cbt.row_process = 0;
@ -2616,6 +2702,7 @@ SWITCH_STANDARD_API(cc_config_api_function)
goto done;
}
}
} else if (action && !strcasecmp(action, "del")) {
if (argc-initial_argc < 2) {
stream->write_function(stream, "%s", "-ERR Invalid!\n");
@ -2635,19 +2722,13 @@ SWITCH_STANDARD_API(cc_config_api_function)
}
} else if (action && !strcasecmp(action, "list")) {
if (argc-initial_argc < 1) {
stream->write_function(stream, "%s", "-ERR Invalid!\n");
goto done;
} else {
const char *queue = argv[0 + initial_argc];
struct list_result cbt;
cbt.row_process = 0;
cbt.stream = stream;
sql = switch_mprintf("SELECT * FROM tiers WHERE queue = '%q' ORDER BY level, position", queue);
cc_execute_sql_callback(NULL /* queue */, NULL /* mutex */, sql, list_result_callback, &cbt /* Call back variables */);
switch_safe_free(sql);
stream->write_function(stream, "%s", "+OK\n");
}
struct list_result cbt;
cbt.row_process = 0;
cbt.stream = stream;
sql = switch_mprintf("SELECT * FROM tiers ORDER BY level, position");
cc_execute_sql_callback(NULL /* queue */, NULL /* mutex */, sql, list_result_callback, &cbt /* Call back variables */);
switch_safe_free(sql);
stream->write_function(stream, "%s", "+OK\n");
}
} else if (section && !strcasecmp(section, "queue")) {
if (action && !strcasecmp(action, "load")) {
@ -2664,6 +2745,7 @@ SWITCH_STANDARD_API(cc_config_api_function)
stream->write_function(stream, "%s", "-ERR Invalid Queue not found!\n");
}
}
} else if (action && !strcasecmp(action, "unload")) {
if (argc-initial_argc < 1) {
stream->write_function(stream, "%s", "-ERR Invalid!\n");
@ -2674,6 +2756,7 @@ SWITCH_STANDARD_API(cc_config_api_function)
stream->write_function(stream, "%s", "+OK\n");
}
} else if (action && !strcasecmp(action, "reload")) {
if (argc-initial_argc < 1) {
stream->write_function(stream, "%s", "-ERR Invalid!\n");
@ -2689,7 +2772,9 @@ SWITCH_STANDARD_API(cc_config_api_function)
stream->write_function(stream, "%s", "-ERR Invalid Queue not found!\n");
}
}
} else if (action && !strcasecmp(action, "list")) {
/* queue list */
if (argc-initial_argc < 1) {
switch_hash_index_t *hi;
stream->write_function(stream, "%s", "name|strategy|moh_sound|time_base_score|tier_rules_apply|tier_rule_wait_second|tier_rule_wait_multiply_level|tier_rule_no_agent_no_wait|discard_abandoned_after|abandoned_resume_allowed|max_wait_time|max_wait_time_with_no_agent|max_wait_time_with_no_agent_time_reached|record_template\n");
@ -2708,35 +2793,81 @@ SWITCH_STANDARD_API(cc_config_api_function)
stream->write_function(stream, "%s", "+OK\n");
goto done;
} else {
const char *queue_name = argv[0 + initial_argc];
const char *sub_action = argv[0 + initial_argc];
const char *queue_name = argv[1 + initial_argc];
const char *status = NULL;
struct list_result cbt;
/* queue list agents */
if (sub_action && !strcasecmp(sub_action, "agents")) {
if (argc-initial_argc > 2) {
status = argv[2 + initial_argc];
}
if (status) {
sql = switch_mprintf("SELECT agents.* FROM agents,tiers WHERE tiers.agent = agents.name AND tiers.queue = '%q' AND agents.status = '%q'", queue_name, status);
} else {
sql = switch_mprintf("SELECT agents.* FROM agents,tiers WHERE tiers.agent = agents.name AND tiers.queue = '%q'", queue_name);
}
/* queue list members */
} else if (sub_action && !strcasecmp(sub_action, "members")) {
sql = switch_mprintf("SELECT * FROM members WHERE queue = '%q';", queue_name);
/* queue list tiers */
} else if (sub_action && !strcasecmp(sub_action, "tiers")) {
sql = switch_mprintf("SELECT * FROM tiers WHERE queue = '%q';", queue_name);
} else {
stream->write_function(stream, "%s", "-ERR Invalid!\n");
goto done;
}
cbt.row_process = 0;
cbt.stream = stream;
sql = switch_mprintf("SELECT * FROM members WHERE queue = '%q'", queue_name);
cc_execute_sql_callback(NULL /* queue */, NULL /* mutex */, sql, list_result_callback, &cbt /* Call back variables */);
switch_safe_free(sql);
stream->write_function(stream, "%s", "+OK\n");
}
} else if (action && !strcasecmp(action, "count")) {
/* queue count */
if (argc-initial_argc < 1) {
stream->write_function(stream, "%s", "-ERR Invalid!\n");
switch_hash_index_t *hi;
int queue_count = 0;
switch_mutex_lock(globals.mutex);
for (hi = switch_hash_first(NULL, globals.queue_hash); hi; hi = switch_hash_next(hi)) {
queue_count++;
}
switch_mutex_unlock(globals.mutex);
stream->write_function(stream, "%d\n", queue_count);
goto done;
} else {
const char *queue_name = argv[0 + initial_argc];
const char *sub_action = argv[0 + initial_argc];
const char *queue_name = argv[1 + initial_argc];
const char *status = NULL;
char res[256] = "";
switch_event_t *event;
/* Check to see if agent already exist */
sql = switch_mprintf("SELECT count(*) FROM members WHERE queue = '%q'", queue_name);
/* queue count agents */
if (sub_action && !strcasecmp(sub_action, "agents")) {
if (argc-initial_argc > 2) {
status = argv[2 + initial_argc];
}
if (status) {
sql = switch_mprintf("SELECT count(*) FROM agents,tiers WHERE tiers.agent = agents.name AND tiers.queue = '%q' AND agents.status = '%q'", queue_name, status);
} else {
sql = switch_mprintf("SELECT count(*) FROM agents,tiers WHERE tiers.agent = agents.name AND tiers.queue = '%q'", queue_name);
}
/* queue count members */
} else if (sub_action && !strcasecmp(sub_action, "members")) {
sql = switch_mprintf("SELECT count(*) FROM members WHERE queue = '%q';", queue_name);
/* queue count tiers */
} else if (sub_action && !strcasecmp(sub_action, "tiers")) {
sql = switch_mprintf("SELECT count(*) FROM tiers WHERE queue = '%q';", queue_name);
} else {
stream->write_function(stream, "%s", "-ERR Invalid!\n");
goto done;
}
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
switch_safe_free(sql);
stream->write_function(stream, "%d\n", atoi(res));
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "members-count");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Count", res);
switch_event_fire(&event);
}
}
}
}
@ -2789,10 +2920,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_callcenter_load)
switch_console_set_complete("add callcenter_config agent set ready_time");
switch_console_set_complete("add callcenter_config agent set reject_delay_time");
switch_console_set_complete("add callcenter_config agent set busy_delay_time");
switch_console_set_complete("add callcenter_config agent set no_answer_delay_time");
switch_console_set_complete("add callcenter_config agent get status");
switch_console_set_complete("add callcenter_config agent list");
switch_console_set_complete("add callcenter_config tier add");
switch_console_set_complete("add callcenter_config tier del");
switch_console_set_complete("add callcenter_config tier set state");
@ -2804,7 +2935,13 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_callcenter_load)
switch_console_set_complete("add callcenter_config queue unload");
switch_console_set_complete("add callcenter_config queue reload");
switch_console_set_complete("add callcenter_config queue list");
switch_console_set_complete("add callcenter_config queue list agents");
switch_console_set_complete("add callcenter_config queue list members");
switch_console_set_complete("add callcenter_config queue list tiers");
switch_console_set_complete("add callcenter_config queue count");
switch_console_set_complete("add callcenter_config queue count agents");
switch_console_set_complete("add callcenter_config queue count members");
switch_console_set_complete("add callcenter_config queue count tiers");
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;

View File

@ -37,6 +37,7 @@
*/
#include <switch.h>
#define DEFAULT_AGC_LEVEL 1100
#define CONFERENCE_UUID_VARIABLE "conference_uuid"
SWITCH_MODULE_LOAD_FUNCTION(mod_conference_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_conference_shutdown);
@ -564,7 +565,10 @@ static conference_member_t *conference_member_get(conference_obj_t *conference,
member = NULL;
}
switch_thread_rwlock_rdlock(member->rwlock);
if (member) {
switch_thread_rwlock_rdlock(member->rwlock);
}
switch_mutex_unlock(conference->member_mutex);
return member;
@ -702,6 +706,7 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
channel = switch_core_session_get_channel(member->session);
switch_channel_set_variable_printf(channel, "conference_member_id", "%d", member->id);
switch_channel_set_variable(channel, CONFERENCE_UUID_VARIABLE, conference->uuid_str);
if (conference->count > 1) {
if (conference->moh_sound && !switch_test_flag(conference, CFLAG_WAIT_MOD)) {
@ -4625,6 +4630,7 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc
/* move the member from the old conference to the new one */
lock_member(member);
switch_thread_rwlock_unlock(member->rwlock);
if (conference != new_conference) {
conference_del_member(conference, member);
@ -4660,10 +4666,6 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "transfer");
switch_event_fire(&event);
}
if (member) {
switch_thread_rwlock_unlock(member->rwlock);
}
}
if (new_conference) {

View File

@ -0,0 +1,5 @@
BASE=../../../..
LOCAL_OBJS += load.o
include $(BASE)/build/modmake.rules

View File

@ -0,0 +1,173 @@
/* load.c
Free software by Richard W.E. Furse. Do with as you will. No
warranty. */
/*****************************************************************************/
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*****************************************************************************/
#include "ladspa.h"
#include "utils.h"
#include "inttypes.h"
#include "switch.h"
/*****************************************************************************/
/* This function provides a wrapping of dlopen(). When the filename is
not an absolute path (i.e. does not begin with / character), this
routine will search the LADSPA_PATH for the file. */
static void *dlopenLADSPA(const char *pcFilename, int iFlag)
{
char *pcBuffer;
const char *pcEnd;
const char *pcLADSPAPath;
const char *pcStart;
int iEndsInSO;
int iNeedSlash;
size_t iFilenameLength;
void *pvResult;
iFilenameLength = strlen(pcFilename);
pvResult = NULL;
if (pcFilename[0] == '/') {
/* The filename is absolute. Assume the user knows what he/she is
doing and simply dlopen() it. */
pvResult = dlopen(pcFilename, iFlag);
if (pvResult != NULL)
return pvResult;
} else {
/* If the filename is not absolute then we wish to check along the
LADSPA_PATH path to see if we can find the file there. We do
NOT call dlopen() directly as this would find plugins on the
LD_LIBRARY_PATH, whereas the LADSPA_PATH is the correct place
to search. */
pcLADSPAPath = getenv("LADSPA_PATH");
if (pcLADSPAPath) {
pcStart = pcLADSPAPath;
while (*pcStart != '\0') {
pcEnd = pcStart;
while (*pcEnd != ':' && *pcEnd != '\0')
pcEnd++;
pcBuffer = malloc(iFilenameLength + 2 + (pcEnd - pcStart));
if (pcEnd > pcStart)
strncpy(pcBuffer, pcStart, pcEnd - pcStart);
iNeedSlash = 0;
if (pcEnd > pcStart)
if (*(pcEnd - 1) != '/') {
iNeedSlash = 1;
pcBuffer[pcEnd - pcStart] = '/';
}
strcpy(pcBuffer + iNeedSlash + (pcEnd - pcStart), pcFilename);
pvResult = dlopen(pcBuffer, iFlag);
free(pcBuffer);
if (pvResult != NULL)
return pvResult;
pcStart = pcEnd;
if (*pcStart == ':')
pcStart++;
}
}
}
/* As a last ditch effort, check if filename does not end with
".so". In this case, add this suffix and recurse. */
iEndsInSO = 0;
if (iFilenameLength > 3)
iEndsInSO = (strcmp(pcFilename + iFilenameLength - 3, ".so") == 0);
if (!iEndsInSO) {
pcBuffer = malloc(iFilenameLength + 4);
strcpy(pcBuffer, pcFilename);
strcat(pcBuffer, ".so");
pvResult = dlopenLADSPA(pcBuffer, iFlag);
free(pcBuffer);
}
if (pvResult != NULL)
return pvResult;
/* If nothing has worked, then at least we can make sure we set the
correct error message - and this should correspond to a call to
dlopen() with the actual filename requested. The dlopen() manual
page does not specify whether the first or last error message
will be kept when multiple calls are made to dlopen(). We've
covered the former case - now we can handle the latter by calling
dlopen() again here. */
return dlopen(pcFilename, iFlag);
}
/*****************************************************************************/
void *loadLADSPAPluginLibrary(const char *pcPluginFilename)
{
void *pvPluginHandle;
pvPluginHandle = dlopenLADSPA(pcPluginFilename, RTLD_NOW);
if (!pvPluginHandle) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to load plugin \"%s\": %s\n", pcPluginFilename, dlerror());
}
return pvPluginHandle;
}
/*****************************************************************************/
void unloadLADSPAPluginLibrary(void *pvLADSPAPluginLibrary)
{
dlclose(pvLADSPAPluginLibrary);
}
/*****************************************************************************/
const LADSPA_Descriptor *findLADSPAPluginDescriptor(void *pvLADSPAPluginLibrary, const char *pcPluginLibraryFilename, const char *pcPluginLabel)
{
const LADSPA_Descriptor *psDescriptor;
LADSPA_Descriptor_Function pfDescriptorFunction;
unsigned long lPluginIndex;
dlerror();
pfDescriptorFunction = (LADSPA_Descriptor_Function) (intptr_t)dlsym(pvLADSPAPluginLibrary, "ladspa_descriptor");
if (!pfDescriptorFunction) {
const char *pcError = dlerror();
if (pcError) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Unable to find ladspa_descriptor() function in plugin "
"library file \"%s\": %s.\n" "Are you sure this is a LADSPA plugin file?\n", pcPluginLibraryFilename, pcError);
return NULL;
}
}
for (lPluginIndex = 0;; lPluginIndex++) {
psDescriptor = pfDescriptorFunction(lPluginIndex);
if (psDescriptor == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Unable to find label \"%s\" in plugin library file \"%s\".\n", pcPluginLabel, pcPluginLibraryFilename);
return NULL;
}
if (strcmp(psDescriptor->Label, pcPluginLabel) == 0)
return psDescriptor;
}
}
/*****************************************************************************/
/* EOF */

View File

@ -0,0 +1,674 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
*
* mod_ladspa.c -- LADSPA
*
*/
#include <switch.h>
#include "ladspa.h"
#include "utils.h"
/* Prototypes */
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_ladspa_shutdown);
SWITCH_MODULE_RUNTIME_FUNCTION(mod_ladspa_runtime);
SWITCH_MODULE_LOAD_FUNCTION(mod_ladspa_load);
/* SWITCH_MODULE_DEFINITION(name, load, shutdown, runtime)
* Defines a switch_loadable_module_function_table_t and a static const char[] modname
*/
SWITCH_MODULE_DEFINITION(mod_ladspa, mod_ladspa_load, mod_ladspa_shutdown, NULL);
#define MAX_INDEX 256
typedef struct {
switch_core_session_t *session;
char *plugin_name;
char *label_name;
void *library_handle;
const LADSPA_Descriptor *ldesc;
LADSPA_Handle handle;
LADSPA_Data config[MAX_INDEX];
int num_idx;
char *str_config[MAX_INDEX];
int str_idx;
uint8_t has_config[MAX_INDEX];
int skip;
LADSPA_Data in_buf[SWITCH_RECOMMENDED_BUFFER_SIZE];
LADSPA_Data file_buf[SWITCH_RECOMMENDED_BUFFER_SIZE];
LADSPA_Data out_buf[SWITCH_RECOMMENDED_BUFFER_SIZE];
LADSPA_Data out_ports[MAX_INDEX];
switch_file_handle_t fh;
} switch_ladspa_t;
int check_range(const LADSPA_Descriptor *ldesc, int i, LADSPA_Data val)
{
if (ldesc->PortRangeHints[i].LowerBound && ldesc->PortRangeHints[i].UpperBound &&
(val < ldesc->PortRangeHints[i].LowerBound || val > ldesc->PortRangeHints[i].UpperBound)) {
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR, "Param %f out of bounds %f-%f\n",
val, ldesc->PortRangeHints[i].LowerBound, ldesc->PortRangeHints[i].UpperBound);
return 0;
}
return 1;
}
int find_default(const LADSPA_Descriptor *ldesc, int i, LADSPA_Data *ptr)
{
LADSPA_Data dftval = 0;
int fail = 0;
LADSPA_PortRangeHintDescriptor port_hint = ldesc->PortRangeHints[i].HintDescriptor;
switch (port_hint & LADSPA_HINT_DEFAULT_MASK) {
case LADSPA_HINT_DEFAULT_NONE:
break;
case LADSPA_HINT_DEFAULT_MINIMUM:
dftval = ldesc->PortRangeHints[i].LowerBound;
break;
case LADSPA_HINT_DEFAULT_LOW:
if (LADSPA_IS_HINT_LOGARITHMIC(port_hint)) {
dftval = exp(log(ldesc->PortRangeHints[i].LowerBound)
* 0.75 + log(ldesc->PortRangeHints[i].UpperBound)
* 0.25);
} else {
dftval = (ldesc->PortRangeHints[i].LowerBound * 0.75 + ldesc->PortRangeHints[i].UpperBound * 0.25);
}
break;
case LADSPA_HINT_DEFAULT_MIDDLE:
if (LADSPA_IS_HINT_LOGARITHMIC(port_hint)) {
dftval = sqrt(ldesc->PortRangeHints[i].LowerBound * ldesc->PortRangeHints[i].UpperBound);
} else {
dftval = 0.5 * (ldesc->PortRangeHints[i].LowerBound + ldesc->PortRangeHints[i].UpperBound);
}
break;
case LADSPA_HINT_DEFAULT_HIGH:
if (LADSPA_IS_HINT_LOGARITHMIC(port_hint)) {
dftval = exp(log(ldesc->PortRangeHints[i].LowerBound)
* 0.25 + log(ldesc->PortRangeHints[i].UpperBound)
* 0.75);
} else {
dftval = (ldesc->PortRangeHints[i].LowerBound * 0.25 + ldesc->PortRangeHints[i].UpperBound * 0.75);
}
break;
case LADSPA_HINT_DEFAULT_MAXIMUM:
dftval = ldesc->PortRangeHints[i].UpperBound;
break;
case LADSPA_HINT_DEFAULT_0:
dftval = 0;
break;
case LADSPA_HINT_DEFAULT_1:
dftval = 1;
break;
case LADSPA_HINT_DEFAULT_100:
dftval = 100;
break;
case LADSPA_HINT_DEFAULT_440:
dftval = 440;
break;
default:
fail = 1;
break;
}
if (!fail) {
*ptr = dftval;
}
return !fail;
}
static void dump_info(const LADSPA_Descriptor *ldesc)
{
int i = 0;
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Plugin Name: \"%s\"\n", ldesc->Name);
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Plugin Label: \"%s\"\n", ldesc->Label);
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Plugin Unique ID: %lu\n", ldesc->UniqueID);
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Maker: \"%s\"\n", ldesc->Maker);
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Copyright: \"%s\"\n", ldesc->Copyright);
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Must Run Real-Time: ");
if (LADSPA_IS_REALTIME(ldesc->Properties))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Yes\n");
else
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "No\n");
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Has activate() Function: ");
if (ldesc->activate != NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Yes\n");
else
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "No\n");
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Has deactivate() Function: ");
if (ldesc->deactivate != NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Yes\n");
else
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "No\n");
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Has run_adding() Function: ");
if (ldesc->run_adding != NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Yes\n");
else
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "No\n");
if (ldesc->instantiate == NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS NO INSTANTIATE FUNCTION.\n");
if (ldesc->connect_port == NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS NO CONNECT_PORT FUNCTION.\n");
if (ldesc->run == NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS NO RUN FUNCTION.\n");
if (ldesc->run_adding != NULL && ldesc->set_run_adding_gain == NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS RUN_ADDING FUNCTION BUT " "NOT SET_RUN_ADDING_GAIN.\n");
if (ldesc->run_adding == NULL && ldesc->set_run_adding_gain != NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS SET_RUN_ADDING_GAIN FUNCTION BUT " "NOT RUN_ADDING.\n");
if (ldesc->cleanup == NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS NO CLEANUP FUNCTION.\n");
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Environment: ");
if (LADSPA_IS_HARD_RT_CAPABLE(ldesc->Properties))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Normal or Hard Real-Time\n");
else
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Normal\n");
if (LADSPA_IS_INPLACE_BROKEN(ldesc->Properties))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "This plugin cannot use in-place processing. " "It will not work with all hosts.\n");
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Ports:");
if (ldesc->PortCount == 0)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "\tERROR: PLUGIN HAS NO PORTS.\n");
for (i = 0; i < ldesc->PortCount; i++) {
LADSPA_Data dft = 0.0f;
int found = 0;
if (LADSPA_IS_PORT_CONTROL(ldesc->PortDescriptors[i])) {
found = find_default(ldesc, i, &dft);
}
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "\n \"%s\" ", ldesc->PortNames[i]);
if (LADSPA_IS_PORT_INPUT(ldesc->PortDescriptors[i])
&& LADSPA_IS_PORT_OUTPUT(ldesc->PortDescriptors[i]))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: INPUT AND OUTPUT");
else if (LADSPA_IS_PORT_INPUT(ldesc->PortDescriptors[i]))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "input");
else if (LADSPA_IS_PORT_OUTPUT(ldesc->PortDescriptors[i]))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "output");
else
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: NEITHER INPUT NOR OUTPUT");
if (LADSPA_IS_PORT_CONTROL(ldesc->PortDescriptors[i])
&& LADSPA_IS_PORT_AUDIO(ldesc->PortDescriptors[i]))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, ", ERROR: CONTROL AND AUDIO");
else if (LADSPA_IS_PORT_CONTROL(ldesc->PortDescriptors[i]))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, ", control");
else if (LADSPA_IS_PORT_AUDIO(ldesc->PortDescriptors[i]))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, ", audio");
else
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, ", ERROR: NEITHER CONTROL NOR AUDIO");
if (LADSPA_IS_PORT_CONTROL(ldesc->PortDescriptors[i])) {
if (found) {
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "\n RANGE: %f-%f DEFAULT: %f\n",
ldesc->PortRangeHints[i].LowerBound, ldesc->PortRangeHints[i].UpperBound, dft);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "\n RANGE: %f-%f DEFAULT: none.\n",
ldesc->PortRangeHints[i].LowerBound, ldesc->PortRangeHints[i].UpperBound);
}
}
}
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "\n\n");
}
static switch_bool_t ladspa_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
{
switch_ladspa_t *pvt = (switch_ladspa_t *) user_data;
//switch_frame_t *frame = NULL;
switch_channel_t *channel = switch_core_session_get_channel(pvt->session);
switch (type) {
case SWITCH_ABC_TYPE_INIT:
{
switch_codec_implementation_t read_impl = { 0 };
LADSPA_PortDescriptor port_desc;
int i = 0, j = 0, k = 0, str_idx = 0;
switch_core_session_get_read_impl(pvt->session, &read_impl);
if (!(pvt->library_handle = loadLADSPAPluginLibrary(pvt->plugin_name))) {
return SWITCH_FALSE;
}
if (!(pvt->ldesc = findLADSPAPluginDescriptor(pvt->library_handle, pvt->plugin_name, pvt->label_name))) {
return SWITCH_FALSE;
}
pvt->handle = pvt->ldesc->instantiate(pvt->ldesc, read_impl.actual_samples_per_second);
dump_info(pvt->ldesc);
for (i = 0; i < pvt->ldesc->PortCount; i++) {
port_desc = pvt->ldesc->PortDescriptors[i];
if (LADSPA_IS_PORT_CONTROL(port_desc) && LADSPA_IS_PORT_INPUT(port_desc)) {
LADSPA_Data dft = 0.0f;
int found = find_default(pvt->ldesc, i, &dft);
if (found && !pvt->has_config[j]) {
pvt->config[j] = dft;
pvt->has_config[j] = 1;
}
if (pvt->has_config[j]) {
if (!check_range(pvt->ldesc, i, pvt->config[j])) {
pvt->config[j] = dft;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_WARNING, "FALLING TO DEFAULT PARAM %d [%s] (%f)\n",
j+1,
pvt->ldesc->PortNames[i],
pvt->config[j]);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "ADDING PARAM %d [%s] (%f)\n",
j+1,
pvt->ldesc->PortNames[i],
pvt->config[j]);
pvt->ldesc->connect_port(pvt->handle, i, &pvt->config[j++]);
usleep(10000);
}
}
if (LADSPA_IS_PORT_INPUT(port_desc) && LADSPA_IS_PORT_AUDIO(port_desc)) {
int mapped = 0;
if (pvt->str_idx && !zstr(pvt->str_config[str_idx])) {
if (!strcasecmp(pvt->str_config[str_idx], "none")) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "CONNECT NOTHING to port: %s\n",
pvt->ldesc->PortNames[i]
);
mapped = 1;
} else if (!strncasecmp(pvt->str_config[str_idx], "file:", 5)) {
char *file = pvt->str_config[str_idx] + 5;
if (switch_test_flag((&pvt->fh), SWITCH_FILE_OPEN)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session),
SWITCH_LOG_ERROR, "CAN'T CONNECT FILE [%s] File already mapped\n", file);
} else {
if (switch_core_file_open(&pvt->fh,
file,
read_impl.number_of_channels,
read_impl.actual_samples_per_second,
SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_ERROR, "Cannot open file: %s\n", file);
return SWITCH_FALSE;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "CONNECT FILE [%s] to port: %s\n",
file,
pvt->ldesc->PortNames[i]
);
pvt->ldesc->connect_port(pvt->handle, i, pvt->file_buf);
mapped = 1;
}
}
str_idx++;
}
if (!mapped) {
pvt->ldesc->connect_port(pvt->handle, i, pvt->in_buf);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "CONNECT CHANNEL AUDIO to port: %s\n",
pvt->ldesc->PortNames[i]
);
}
}
if (LADSPA_IS_PORT_OUTPUT(port_desc)) {
if (LADSPA_IS_PORT_AUDIO(port_desc)) {
pvt->ldesc->connect_port(pvt->handle, i, pvt->out_buf);
} else if (k < MAX_INDEX) {
pvt->ldesc->connect_port(pvt->handle, i, &pvt->out_ports[k++]);
}
}
}
}
break;
case SWITCH_ABC_TYPE_CLOSE:
{
if (switch_test_flag((&pvt->fh), SWITCH_FILE_OPEN)) {
switch_core_file_close(&pvt->fh);
}
if (pvt->handle && pvt->ldesc) {
pvt->ldesc->cleanup(pvt->handle);
}
if (pvt->library_handle) {
unloadLADSPAPluginLibrary(pvt->library_handle);
}
}
break;
case SWITCH_ABC_TYPE_WRITE_REPLACE:
case SWITCH_ABC_TYPE_READ_REPLACE:
{
switch_frame_t *rframe;
int16_t *slin, abuf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
switch_size_t olen = 0;
if (type == SWITCH_ABC_TYPE_READ_REPLACE) {
rframe = switch_core_media_bug_get_read_replace_frame(bug);
} else {
rframe = switch_core_media_bug_get_write_replace_frame(bug);
}
slin = rframe->data;
if (switch_channel_media_ready(channel)) {
switch_short_to_float(slin, pvt->in_buf, rframe->samples);
if (switch_test_flag((&pvt->fh), SWITCH_FILE_OPEN)) {
olen = rframe->samples;
if (switch_core_file_read(&pvt->fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
switch_codec_implementation_t read_impl = { 0 };
char *file = switch_core_session_strdup(pvt->session, pvt->fh.file_path);
switch_core_session_get_read_impl(pvt->session, &read_impl);
switch_core_file_close(&pvt->fh);
if (switch_core_file_open(&pvt->fh,
file,
read_impl.number_of_channels,
read_impl.actual_samples_per_second,
SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_ERROR, "Cannot open file: %s\n", file);
return SWITCH_FALSE;
}
olen = rframe->samples;
if (switch_core_file_read(&pvt->fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_ERROR, "Cannot READ file: %s\n", file);
return SWITCH_FALSE;
}
}
switch_short_to_float(abuf, pvt->file_buf, olen);
}
pvt->ldesc->run(pvt->handle, rframe->samples);
switch_float_to_short(pvt->out_buf, slin, rframe->samples);
}
if (type == SWITCH_ABC_TYPE_READ_REPLACE) {
switch_core_media_bug_set_read_replace_frame(bug, rframe);
} else {
switch_core_media_bug_set_write_replace_frame(bug, rframe);
}
if (pvt->skip && !--pvt->skip) {
return SWITCH_FALSE;
}
}
break;
case SWITCH_ABC_TYPE_WRITE:
default:
break;
}
return SWITCH_TRUE;
}
switch_status_t stop_ladspa_session(switch_core_session_t *session)
{
switch_media_bug_t *bug;
switch_channel_t *channel = switch_core_session_get_channel(session);
if ((bug = switch_channel_get_private(channel, "ladspa"))) {
switch_channel_set_private(channel, "ladspa", NULL);
switch_core_media_bug_remove(session, &bug);
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
switch_status_t ladspa_session(switch_core_session_t *session, const char *flags, const char *plugin_name, const char *label, const char *params)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_media_bug_t *bug;
switch_status_t status;
switch_ladspa_t *pvt = { 0 };
switch_codec_implementation_t read_impl = { 0 };
int i, bflags = SMBF_READ_REPLACE | SMBF_ANSWER_REQ;
char *pstr;
int argc;
char *argv[50];
char *dparams = NULL;
if (zstr(plugin_name)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s INVALID PLUGIN\n", switch_channel_get_name(channel));
return SWITCH_STATUS_FALSE;
}
if (zstr(flags)) {
flags = "r";
}
if (strchr(flags, 'w')) {
bflags = SMBF_WRITE_REPLACE;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "FLAGS: %s PLUGIN: %s LABEL: %s PARAMS: %s\n",
flags, plugin_name, label, params);
switch_core_session_get_read_impl(session, &read_impl);
pvt = switch_core_session_alloc(session, sizeof(*pvt));
pvt->session = session;
if (!zstr(label)) {
pvt->label_name = switch_core_session_strdup(session, label);
} else {
char *p;
pvt->label_name = switch_core_session_strdup(session, plugin_name);
if ((p = strrchr(pvt->label_name, '.'))) {
*p = '\0';
}
}
if (strstr(plugin_name, ".so")) {
pvt->plugin_name = switch_core_session_strdup(session, plugin_name);
} else {
pvt->plugin_name = switch_core_session_sprintf(session, "%s.so", plugin_name);
}
dparams = switch_core_session_strdup(session, params);
argc = switch_split(dparams, ' ', argv);
for (i = 0; i < argc; i++) {
if (switch_is_number(argv[i])) {
if (pvt->num_idx < MAX_INDEX) {
pvt->config[pvt->num_idx] = atof(argv[i]);
pvt->has_config[pvt->num_idx] = 1;
pvt->num_idx++;
}
} else {
if (pvt->str_idx < MAX_INDEX) {
pvt->str_config[pvt->str_idx++] = switch_core_session_strdup(session, argv[i]);
}
}
}
if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
}
pstr = switch_core_session_sprintf(session, "%s|%s|%s|%s", flags, plugin_name, label, params);
if ((status = switch_core_media_bug_add(session, "ladspa", pstr,
ladspa_callback, pvt, 0, bflags | SMBF_NO_PAUSE, &bug)) != SWITCH_STATUS_SUCCESS) {
return status;
}
switch_channel_set_private(channel, "ladspa", bug);
return SWITCH_STATUS_SUCCESS;
}
static void ladspa_parse(switch_core_session_t *session, const char *data)
{
char *argv[5] = { 0 };
int argc;
char *lbuf;
if (data) {
lbuf = strdup(data);
argc = switch_separate_string(lbuf, '|', argv, (sizeof(argv) / sizeof(argv[0])));
ladspa_session(session, argv[0], argv[1], argv[2], argv[3]);
free(lbuf);
}
}
#define APP_SYNTAX "<flags>|<plugin>|<label>|<params>"
SWITCH_STANDARD_APP(ladspa_run_function)
{
ladspa_parse(session, data);
}
#define API_SYNTAX "<uuid>|<flags>|<plugin>|<label>|<params>"
SWITCH_STANDARD_API(ladspa_api)
{
char *uuid = NULL;
char *data;
char *p;
switch_core_session_t *ksession = NULL;
if (!cmd) goto err;
data = strdup(cmd);
if ((p = strchr(data, ' '))) {
uuid = data;
*p++ = '\0';
if ((ksession = switch_core_session_locate(uuid))) {
ladspa_parse(ksession, p);
switch_core_session_rwunlock(ksession);
stream->write_function(stream, "+OK\n");
} else {
stream->write_function(stream, "-ERR non-existant UUID\n");
}
} else {
stream->write_function(stream, "-ERR Usage %s\n", API_SYNTAX);
}
free(data);
return SWITCH_STATUS_SUCCESS;
err:
stream->write_function(stream, "-ERR Operation Failed\n");
return SWITCH_STATUS_SUCCESS;
}
/* Macro expands to: switch_status_t mod_ladspa_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
SWITCH_MODULE_LOAD_FUNCTION(mod_ladspa_load)
{
switch_application_interface_t *app_interface;
switch_api_interface_t *api_interface;
char *path = getenv("LADSPA_PATH");
if (zstr(path)) {
if (switch_directory_exists("/usr/lib64/ladspa/", pool) == SWITCH_STATUS_SUCCESS) {
putenv("LADSPA_PATH=/usr/lib64/ladspa/:/usr/local/lib/ladspa");
} else if (switch_directory_exists("/usr/lib/ladspa/", pool) == SWITCH_STATUS_SUCCESS) {
putenv("LADSPA_PATH=/usr/lib/ladspa/:/usr/local/lib/ladspa");
}
}
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_APP(app_interface, "ladspa_run", "ladspa_run", NULL, ladspa_run_function, APP_SYNTAX, SAF_NONE);
SWITCH_ADD_API(api_interface, "uuid_ladspa", "ladspa", ladspa_api, API_SYNTAX);
switch_console_set_complete("add uuid_ladspa ::console::list_uuid");
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
/*
Called when the system shuts down
Macro expands to: switch_status_t mod_ladspa_shutdown() */
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_ladspa_shutdown)
{
/* Cleanup dynamically allocated config settings */
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4
*/

View File

@ -0,0 +1,72 @@
/* utils.h
Free software by Richard W.E. Furse. Do with as you will. No
warranty. */
#ifndef LADSPA_SDK_LOAD_PLUGIN_LIB
#define LADSPA_SDK_LOAD_PLUGIN_LIB
/*****************************************************************************/
#include "ladspa.h"
/*****************************************************************************/
/* Functions in load.c: */
/* This function call takes a plugin library filename, searches for
the library along the LADSPA_PATH, loads it with dlopen() and
returns a plugin handle for use with findPluginDescriptor() or
unloadLADSPAPluginLibrary(). Errors are handled by writing a
message to stderr and calling exit(1). It is alright (although
inefficient) to call this more than once for the same file. */
void * loadLADSPAPluginLibrary(const char * pcPluginFilename);
/* This function unloads a LADSPA plugin library. */
void unloadLADSPAPluginLibrary(void * pvLADSPAPluginLibrary);
/* This function locates a LADSPA plugin within a plugin library
loaded with loadLADSPAPluginLibrary(). Errors are handled by
writing a message to stderr and calling exit(1). Note that the
plugin library filename is only included to help provide
informative error messages. */
const LADSPA_Descriptor *
findLADSPAPluginDescriptor(void * pvLADSPAPluginLibrary,
const char * pcPluginLibraryFilename,
const char * pcPluginLabel);
/*****************************************************************************/
/* Functions in search.c: */
/* Callback function for use with LADSPAPluginSearch(). The callback
function passes the filename (full path), a plugin handle (dlopen()
style) and a LADSPA_DescriptorFunction (from which
LADSPA_Descriptors can be acquired). */
typedef void LADSPAPluginSearchCallbackFunction
(const char * pcFullFilename,
void * pvPluginHandle,
LADSPA_Descriptor_Function fDescriptorFunction);
/* Search through the $(LADSPA_PATH) (or a default path) for any
LADSPA plugin libraries. Each plugin library is tested using
dlopen() and dlsym(,"ladspa_descriptor"). After loading each
library, the callback function is called to process it. This
function leaves items passed to the callback function open. */
void LADSPAPluginSearch(LADSPAPluginSearchCallbackFunction fCallbackFunction);
/*****************************************************************************/
/* Function in default.c: */
/* Find the default value for a port. Return 0 if a default is found
and -1 if not. */
int getLADSPADefault(const LADSPA_PortRangeHint * psPortRangeHint,
const unsigned long lSampleRate,
LADSPA_Data * pfResult);
/*****************************************************************************/
#endif
/* EOF */

View File

@ -2492,6 +2492,7 @@ static switch_status_t deliver_vm(vm_profile_t *profile,
if (copy) {
switch_file_copy(path, file_path, SWITCH_FPROT_FILE_SOURCE_PERMS, pool);
} else {
switch_safe_free(file_path);
file_path = (char *) path;
}

View File

@ -3161,12 +3161,15 @@ static switch_status_t recog_asr_close(switch_asr_handle_t *ah, switch_asr_flag_
if (schannel != NULL && !switch_test_flag(ah, SWITCH_ASR_FLAG_CLOSED)) {
r = (recognizer_data_t *) schannel->data;
speech_channel_stop(schannel);
speech_channel_destroy(schannel);
switch_core_hash_destroy(&r->grammars);
switch_core_hash_destroy(&r->enabled_grammars);
switch_mutex_lock(schannel->mutex);
if (r->dtmf_generator) {
r->dtmf_generator_active = 0;
mpf_dtmf_generator_destroy(r->dtmf_generator);
}
switch_mutex_unlock(schannel->mutex);
speech_channel_destroy(schannel);
}
/* this lets FreeSWITCH's speech_thread know the handle is closed */
switch_set_flag(ah, SWITCH_ASR_FLAG_CLOSED);
@ -3502,13 +3505,15 @@ static apt_bool_t recog_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *fra
}
frame->type |= MEDIA_FRAME_TYPE_AUDIO;
}
switch_mutex_lock(schannel->mutex);
if (r->dtmf_generator_active) {
if (!mpf_dtmf_generator_put_frame(r->dtmf_generator, frame)) {
if (!mpf_dtmf_generator_sending(r->dtmf_generator))
r->dtmf_generator_active = 0;
}
}
switch_mutex_unlock(schannel->mutex);
return TRUE;
}

View File

@ -1,7 +1,7 @@
include $(top_srcdir)/build/modmake.rulesam
MODNAME=mod_com_g729
VERSION=193
VERSION=194
if ISLINUX

View File

@ -1373,6 +1373,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
if ((len = atoi(msg->string_arg))) {
qlen = len / (tech_pvt->read_impl.microseconds_per_packet / 1000);
if (qlen < 1) {
qlen = 3;
}
}
if (qlen) {
@ -1393,6 +1396,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
}
if (qlen) {
if (maxqlen < qlen) {
maxqlen = qlen * 5;
}
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, max_drift) == SWITCH_STATUS_SUCCESS) {
@ -1444,69 +1450,97 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
case SWITCH_MESSAGE_INDICATE_BRIDGE:
{
const char *var = switch_channel_get_variable(tech_pvt->channel, "sip_jitter_buffer_during_bridge");
sofia_glue_tech_track(tech_pvt->profile, session);
sofia_glue_tech_simplify(tech_pvt);
if (switch_false(var) && switch_rtp_ready(tech_pvt->rtp_session)) {
if (switch_rtp_ready(tech_pvt->rtp_session)) {
const char *val;
int ok = 0;
if (switch_channel_test_flag(tech_pvt->channel, CF_JITTERBUFFER) && switch_channel_test_cap_partner(tech_pvt->channel, CC_FS_RTP)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s PAUSE Jitterbuffer\n", switch_channel_get_name(channel));
switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_TRUE);
if (!(val = switch_channel_get_variable(tech_pvt->channel, "sip_jitter_buffer_during_bridge")) || switch_false(val)) {
if (switch_channel_test_flag(tech_pvt->channel, CF_JITTERBUFFER) && switch_channel_test_cap_partner(tech_pvt->channel, CC_FS_RTP)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s PAUSE Jitterbuffer\n", switch_channel_get_name(channel));
switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_TRUE);
sofia_set_flag(tech_pvt, TFLAG_JB_PAUSED);
}
}
if (sofia_test_flag(tech_pvt, TFLAG_PASS_RFC2833) && switch_channel_test_flag_partner(channel, CF_FS_RTP)) {
switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s activate passthru 2833 mode.\n", switch_channel_get_name(channel));
}
if ((val = switch_channel_get_variable(channel, "rtp_autoflush_during_bridge"))) {
if ((val = switch_channel_get_variable(channel, "rtp_notimer_during_bridge"))) {
ok = switch_true(val);
} else {
ok = sofia_test_pflag(tech_pvt->profile, PFLAG_RTP_AUTOFLUSH_DURING_BRIDGE);
ok = sofia_test_pflag(tech_pvt->profile, PFLAG_RTP_NOTIMER_DURING_BRIDGE);
}
if (ok && !switch_rtp_test_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) {
ok = 0;
}
if (ok) {
switch_rtp_clear_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
switch_rtp_clear_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
sofia_set_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE);
}
if (ok && sofia_test_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE)) {
/* these are not compat */
ok = 0;
} else {
if ((val = switch_channel_get_variable(channel, "rtp_autoflush_during_bridge"))) {
ok = switch_true(val);
} else {
ok = sofia_test_pflag(tech_pvt->profile, PFLAG_RTP_AUTOFLUSH_DURING_BRIDGE);
}
}
if (ok) {
rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_STICK);
sofia_set_flag(tech_pvt, TFLAG_AUTOFLUSH_DURING_BRIDGE);
} else {
rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_ONCE);
}
}
}
goto end;
case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
if (switch_rtp_ready(tech_pvt->rtp_session)) {
const char *val;
int ok = 0;
sofia_glue_tech_track(tech_pvt->profile, session);
if (switch_channel_test_flag(tech_pvt->channel, CF_JITTERBUFFER)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s RESUME Jitterbuffer\n", switch_channel_get_name(channel));
switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_FALSE);
if (sofia_test_flag(tech_pvt, TFLAG_JB_PAUSED)) {
sofia_clear_flag(tech_pvt, TFLAG_JB_PAUSED);
if (switch_channel_test_flag(tech_pvt->channel, CF_JITTERBUFFER)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s RESUME Jitterbuffer\n", switch_channel_get_name(channel));
switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_FALSE);
}
}
if (switch_rtp_test_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s deactivate passthru 2833 mode.\n",
switch_channel_get_name(channel));
switch_rtp_clear_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833);
}
if ((val = switch_channel_get_variable(channel, "rtp_autoflush_during_bridge"))) {
ok = switch_true(val);
} else {
ok = sofia_test_pflag(tech_pvt->profile, PFLAG_RTP_AUTOFLUSH_DURING_BRIDGE);
if (sofia_test_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE)) {
switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
sofia_clear_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE);
}
if (ok) {
if (sofia_test_flag(tech_pvt, TFLAG_AUTOFLUSH_DURING_BRIDGE)) {
rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_UNSTICK);
sofia_clear_flag(tech_pvt, TFLAG_AUTOFLUSH_DURING_BRIDGE);
} else {
rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_ONCE);
}
@ -1850,6 +1884,17 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
if (switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote)) {
snprintf(message, sizeof(message), "X-FS-Display-Name: %s\nX-FS-Display-Number: %s\n", name, number);
if (switch_channel_test_flag(tech_pvt->channel, CF_LAZY_ATTENDED_TRANSFER)) {
snprintf(message + strlen(message), sizeof(message) - strlen(message), "X-FS-Lazy-Attended-Transfer: true\n");
switch_channel_clear_flag(tech_pvt->channel, CF_LAZY_ATTENDED_TRANSFER);
switch_channel_clear_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER);
}
if (switch_channel_test_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER)) {
snprintf(message + strlen(message), sizeof(message) - strlen(message), "X-FS-Attended-Transfer: true\n");
switch_channel_clear_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER);
}
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/update_display"),
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END());

View File

@ -230,6 +230,9 @@ typedef enum {
PFLAG_PRESENCE_ON_REGISTER,
PFLAG_PRESENCE_ON_FIRST_REGISTER,
PFLAG_NO_CONNECTION_REUSE,
PFLAG_RENEG_ON_HOLD,
PFLAG_RENEG_ON_REINVITE,
PFLAG_RTP_NOTIMER_DURING_BRIDGE,
/* No new flags below this line */
PFLAG_MAX
} PFLAGS;
@ -288,6 +291,9 @@ typedef enum {
TFLAG_RECOVERING_BRIDGE,
TFLAG_T38_PASSTHRU,
TFLAG_RECOVERED,
TFLAG_AUTOFLUSH_DURING_BRIDGE,
TFLAG_NOTIMER_DURING_BRIDGE,
TFLAG_JB_PAUSED,
/* No new flags below this line */
TFLAG_MAX
} TFLAGS;
@ -598,6 +604,8 @@ struct private_object {
int codec_order_last;
const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS];
int num_codecs;
const switch_codec_implementation_t *negotiated_codecs[SWITCH_MAX_CODECS];
int num_negotiated_codecs;
switch_codec_t read_codec;
switch_codec_t write_codec;
uint32_t codec_ms;
@ -984,7 +992,7 @@ void sofia_glue_del_every_gateway(sofia_profile_t *profile);
void sofia_reg_send_reboot(sofia_profile_t *profile, const char *user, const char *host, const char *contact, const char *user_agent,
const char *network_ip);
void sofia_glue_restart_all_profiles(void);
void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly);
int sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly);
const char *sofia_state_string(int state);
switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force);
void sofia_wait_for_reply(struct private_object *tech_pvt, nua_event_t event, uint32_t timeout);

View File

@ -637,7 +637,7 @@ void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *pro
char *dup = NULL;
switch_event_t *event;
const char *val;
int fs = 0;
int fs = 0, lazy = 0, att = 0;
if (switch_true(switch_channel_get_variable(channel, SWITCH_IGNORE_DISPLAY_UPDATES_VARIABLE))) {
return;
@ -656,6 +656,16 @@ void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *pro
name = (char *) val;
fs++;
}
if ((val = sofia_glue_get_unknown_header(sip, "X-FS-Lazy-Attended-Transfer"))) {
lazy = switch_true(val);
fs++;
}
if ((val = sofia_glue_get_unknown_header(sip, "X-FS-Attended-Transfer"))) {
att = switch_true(val);
fs++;
}
if (!fs) {
if ((passerted = sip_p_asserted_identity(sip))) {
@ -727,6 +737,10 @@ void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *pro
caller_profile->callee_id_name = switch_sanitize_number(switch_core_strdup(caller_profile->pool, name));
caller_profile->callee_id_number = switch_sanitize_number(switch_core_strdup(caller_profile->pool, number));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Update Callee ID to \"%s\" <%s>\n", switch_channel_get_name(channel), name, number);
if (lazy || (att && !switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
switch_channel_flip_cid(channel);
}
}
if (send) {
@ -2436,6 +2450,18 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
} else {
sofia_clear_pflag(profile, PFLAG_IGNORE_183NOSDP);
}
} else if (!strcasecmp(var, "renegotiate-codec-on-hold")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_RENEG_ON_HOLD);
} else {
sofia_clear_pflag(profile, PFLAG_RENEG_ON_HOLD);
}
} else if (!strcasecmp(var, "renegotiate-codec-on-reinvite")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_RENEG_ON_REINVITE);
} else {
sofia_clear_pflag(profile, PFLAG_RENEG_ON_REINVITE);
}
} else if (!strcasecmp(var, "presence-probe-on-register")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER);
@ -2519,6 +2545,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
} else {
sofia_clear_pflag(profile, PFLAG_RTP_AUTOFLUSH_DURING_BRIDGE);
}
} else if (!strcasecmp(var, "rtp-notimer-during-bridge")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_RTP_NOTIMER_DURING_BRIDGE);
} else {
sofia_clear_pflag(profile, PFLAG_RTP_NOTIMER_DURING_BRIDGE);
}
} else if (!strcasecmp(var, "manual-redirect")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_MANUAL_REDIRECT);
@ -3119,6 +3151,18 @@ switch_status_t config_sofia(int reload, char *profile_name)
} else {
sofia_clear_pflag(profile, PFLAG_IGNORE_183NOSDP);
}
} else if (!strcasecmp(var, "renegotiate-codec-on-hold")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_RENEG_ON_HOLD);
} else {
sofia_clear_pflag(profile, PFLAG_RENEG_ON_HOLD);
}
} else if (!strcasecmp(var, "renegotiate-codec-on-reinvite")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_RENEG_ON_REINVITE);
} else {
sofia_clear_pflag(profile, PFLAG_RENEG_ON_REINVITE);
}
} else if (!strcasecmp(var, "presence-probe-on-register")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER);
@ -3190,6 +3234,12 @@ switch_status_t config_sofia(int reload, char *profile_name)
} else {
sofia_clear_pflag(profile, PFLAG_RTP_AUTOFLUSH_DURING_BRIDGE);
}
} else if (!strcasecmp(var, "rtp-notimer-during-bridge")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_RTP_NOTIMER_DURING_BRIDGE);
} else {
sofia_clear_pflag(profile, PFLAG_RTP_NOTIMER_DURING_BRIDGE);
}
} else if (!strcasecmp(var, "manual-redirect")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_MANUAL_REDIRECT);
@ -4372,10 +4422,15 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing %d %s to other leg\n", status, phrase);
if (status == 200 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && has_t38) {
if (sip->sip_payload && sip->sip_payload->pl_data) {
switch_t38_options_t *t38_options = sofia_glue_extract_t38_options(session, sip->sip_payload->pl_data);
if (status == 200 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && has_t38 && sip->sip_payload && sip->sip_payload->pl_data) {
switch_t38_options_t *t38_options = sofia_glue_extract_t38_options(session, sip->sip_payload->pl_data);
if (!t38_options) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_WARNING, "%s Error parsing SDP:\n%s\n",
switch_channel_get_name(tech_pvt->channel), sip->sip_payload->pl_data);
goto end;
} else {
char *remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session);
switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session);
char tmp[32] = "";
@ -5681,9 +5736,14 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Attended Transfer [%s][%s]\n",
switch_str_nil(br_a), switch_str_nil(br_b));
if ((profile->media_options & MEDIA_OPT_BYPASS_AFTER_ATT_XFER) && (tmp = switch_core_session_locate(br_b))) {
if ((tmp = switch_core_session_locate(br_b))) {
switch_channel_t *tchannel = switch_core_session_get_channel(tmp);
switch_channel_set_flag(tchannel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
if ((profile->media_options & MEDIA_OPT_BYPASS_AFTER_ATT_XFER)) {
switch_channel_set_flag(tchannel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
}
switch_channel_set_flag(tchannel, CF_ATTENDED_TRANSFER);
switch_core_session_rwunlock(tmp);
}

View File

@ -2965,6 +2965,17 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
flags |= SWITCH_RTP_FLAG_AUTO_CNG;
}
#if __BYTE_ORDER == __LITTLE_ENDIAN
if (!strcasecmp(tech_pvt->read_impl.iananame, "L16")) {
flags |= SWITCH_RTP_FLAG_BYTESWAP;
}
#endif
if ((flags & SWITCH_RTP_FLAG_BYTESWAP) && (val = switch_channel_get_variable(tech_pvt->channel, "rtp_disable_byteswap")) && switch_true(val)) {
flags &= ~SWITCH_RTP_FLAG_BYTESWAP;
}
if (tech_pvt->rtp_session && sofia_test_flag(tech_pvt, TFLAG_REINVITE)) {
//const char *ip = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
//const char *port = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
@ -2996,6 +3007,16 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
if (switch_rtp_ready(tech_pvt->rtp_session)) {
switch_rtp_set_default_payload(tech_pvt->rtp_session, tech_pvt->agreed_pt);
if (tech_pvt->audio_recv_pt != tech_pvt->agreed_pt) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
"%s Set audio receive payload to %u\n", switch_channel_get_name(tech_pvt->channel), tech_pvt->audio_recv_pt);
switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->audio_recv_pt);
} else {
switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->agreed_pt);
}
}
}
@ -3186,10 +3207,17 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
qlen = jb_msec / (tech_pvt->read_impl.microseconds_per_packet / 1000);
if (qlen < 1) {
qlen = 3;
}
if (maxlen) {
maxqlen = maxlen / (tech_pvt->read_impl.microseconds_per_packet / 1000);
}
if (maxqlen < qlen) {
maxqlen = qlen * 5;
}
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, max_drift) == SWITCH_STATUS_SUCCESS) {
@ -3749,8 +3777,10 @@ switch_status_t sofia_glue_tech_media(private_object_t *tech_pvt, const char *r_
return SWITCH_STATUS_FALSE;
}
void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly)
int sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly)
{
int changed = 0;
if (sendonly && switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED)) {
if (!sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD)) {
const char *stream;
@ -3769,6 +3799,7 @@ void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly)
switch_channel_set_flag(tech_pvt->channel, CF_LEG_HOLDING);
switch_channel_mark_hold(tech_pvt->channel, SWITCH_TRUE);
switch_channel_presence(tech_pvt->channel, "unknown", msg, NULL);
changed = 1;
if (tech_pvt->max_missed_hold_packets) {
switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_hold_packets);
@ -3795,6 +3826,7 @@ void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly)
sofia_set_flag(tech_pvt, TFLAG_SIP_HOLD);
switch_channel_set_flag(tech_pvt->channel, CF_LEG_HOLDING);
switch_channel_mark_hold(tech_pvt->channel, SWITCH_TRUE);
changed = 1;
}
sofia_clear_flag_locked(tech_pvt, TFLAG_HOLD_LOCK);
@ -3828,8 +3860,11 @@ void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly)
switch_channel_clear_flag(tech_pvt->channel, CF_LEG_HOLDING);
switch_channel_mark_hold(tech_pvt->channel, SWITCH_FALSE);
switch_channel_presence(tech_pvt->channel, "unknown", "unhold", NULL);
changed = 1;
}
}
return changed;
}
void sofia_glue_copy_t38_options(switch_t38_options_t *t38_options, switch_core_session_t *session)
@ -4154,6 +4189,14 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
int scrooge = 0;
sdp_parser_t *parser = NULL;
sdp_session_t *sdp;
int reneg = 1;
const switch_codec_implementation_t **codec_array;
int total_codecs;
codec_array = tech_pvt->codecs;
total_codecs = tech_pvt->num_codecs;
if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
return 0;
@ -4254,10 +4297,30 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
if (!tech_pvt->hold_laps) {
tech_pvt->hold_laps++;
sofia_glue_toggle_hold(tech_pvt, sendonly);
if (sofia_glue_toggle_hold(tech_pvt, sendonly)) {
reneg = sofia_test_pflag(tech_pvt->profile, PFLAG_RENEG_ON_HOLD);
if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_renegotiate_codec_on_hold"))) {
reneg = switch_true(val);
}
}
}
}
if (reneg) {
reneg = sofia_test_pflag(tech_pvt->profile, PFLAG_RENEG_ON_REINVITE);
if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_renegotiate_codec_on_reinvite"))) {
reneg = switch_true(val);
}
}
if (!reneg && tech_pvt->num_negotiated_codecs) {
codec_array = tech_pvt->negotiated_codecs;
total_codecs = tech_pvt->num_negotiated_codecs;
}
for (m = sdp->sdp_media; m; m = m->m_next) {
sdp_connection_t *connection;
switch_core_session_t *other_session;
@ -4351,6 +4414,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
goto done;
} else if (m->m_type == sdp_media_audio && m->m_port && !got_audio) {
sdp_rtpmap_t *map;
for (attr = m->m_attributes; attr; attr = attr->a_next) {
if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value) {
@ -4561,8 +4625,9 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
}
}
for (i = first; i < last && i < tech_pvt->num_codecs; i++) {
const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
for (i = first; i < last && i < total_codecs; i++) {
const switch_codec_implementation_t *imp = codec_array[i];
uint32_t bit_rate = imp->bits_per_second;
uint32_t codec_rate = imp->samples_per_second;
if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
@ -4649,12 +4714,14 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
tech_pvt->rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp);
tech_pvt->remote_sdp_audio_port = (switch_port_t) m->m_port;
tech_pvt->agreed_pt = (switch_payload_t) map->rm_pt;
tech_pvt->num_negotiated_codecs = 0;
tech_pvt->negotiated_codecs[tech_pvt->num_negotiated_codecs++] = mimp;
switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port);
switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip);
switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
tech_pvt->audio_recv_pt = map->rm_pt;
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !sofia_test_flag(tech_pvt, TFLAG_REINVITE)) {
sofia_glue_get_offered_pt(tech_pvt, mimp, &tech_pvt->audio_recv_pt);
}
@ -4690,7 +4757,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
}
if (!match && greedy && mine < tech_pvt->num_codecs) {
if (!match && greedy && mine < total_codecs) {
mine++;
skip = 0;
goto greed;
@ -4729,8 +4796,8 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
rm_encoding = "";
}
for (i = 0; i < tech_pvt->num_codecs; i++) {
const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
for (i = 0; i < total_codecs; i++) {
const switch_codec_implementation_t *imp = codec_array[i];
if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
continue;
@ -4792,8 +4859,9 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
done:
if (parser)
if (parser) {
sdp_parser_free(parser);
}
tech_pvt->cng_pt = cng_pt;
sofia_set_flag_locked(tech_pvt, TFLAG_SDP);

View File

@ -2004,7 +2004,7 @@ static void sync_sla(sofia_profile_t *profile, const char *to_user, const char *
switch_core_hash_init(&sh->hash, sh->pool);
sql = switch_mprintf("select sip_from_user,sip_from_host,call_info,call_info_state,uuid from sip_dialogs "
"where hostname='%q' and ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')",
"where call_info_state is not null and hostname='%q' and ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')",
mod_sofia_globals.hostname, to_user, to_host, to_user, to_host);

View File

@ -1124,8 +1124,8 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
}
}
if ((v_contact_str = switch_event_get_header(*v_event, "sip-force-contact")) || auto_connectile) {
if ((!strcasecmp(v_contact_str, "NDLB-connectile-dysfunction-2.0")) || auto_connectile) {
if (auto_connectile || (v_contact_str = switch_event_get_header(*v_event, "sip-force-contact"))) {
if (auto_connectile || (!strcasecmp(v_contact_str, "NDLB-connectile-dysfunction-2.0"))) {
char *path_encoded;
size_t path_encoded_len;
char my_contact_str[1024];
@ -1914,7 +1914,7 @@ void sofia_reg_handle_sip_r_challenge(int status,
} else if (gateway) {
switch_snprintf(authentication, sizeof(authentication), "%s:%s:%s:%s", scheme, realm, gateway->auth_username, gateway->register_password);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No Matching gateway found\n");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot locate any authentication credentials to complete an authentication request for realm '%s'\n", realm);
goto cancel;
}

View File

@ -305,55 +305,60 @@ static void event_handler(switch_event_t *event)
}
}
if (send && l->filters && l->filters->headers) {
switch_event_header_t *hp;
const char *hval;
send = 0;
if (send) {
switch_mutex_lock(l->filter_mutex);
for (hp = l->filters->headers; hp; hp = hp->next) {
if ((hval = switch_event_get_header(event, hp->name))) {
const char *comp_to = hp->value;
int pos = 1, cmp = 0;
while (comp_to && *comp_to) {
if (*comp_to == '+') {
pos = 1;
} else if (*comp_to == '-') {
pos = 0;
} else if (*comp_to != ' ') {
break;
if (l->filters && l->filters->headers) {
switch_event_header_t *hp;
const char *hval;
send = 0;
for (hp = l->filters->headers; hp; hp = hp->next) {
if ((hval = switch_event_get_header(event, hp->name))) {
const char *comp_to = hp->value;
int pos = 1, cmp = 0;
while (comp_to && *comp_to) {
if (*comp_to == '+') {
pos = 1;
} else if (*comp_to == '-') {
pos = 0;
} else if (*comp_to != ' ') {
break;
}
comp_to++;
}
comp_to++;
}
if (send && pos) {
continue;
}
if (send && pos) {
continue;
}
if (!comp_to) {
continue;
}
if (!comp_to) {
continue;
}
if (*hp->value == '/') {
switch_regex_t *re = NULL;
int ovector[30];
cmp = !!switch_regex_perform(hval, comp_to, &re, ovector, sizeof(ovector) / sizeof(ovector[0]));
switch_regex_safe_free(re);
} else {
cmp = !strcasecmp(hval, comp_to);
}
if (cmp) {
if (pos) {
send = 1;
if (*hp->value == '/') {
switch_regex_t *re = NULL;
int ovector[30];
cmp = !!switch_regex_perform(hval, comp_to, &re, ovector, sizeof(ovector) / sizeof(ovector[0]));
switch_regex_safe_free(re);
} else {
send = 0;
break;
cmp = !strcasecmp(hval, comp_to);
}
if (cmp) {
if (pos) {
send = 1;
} else {
send = 0;
break;
}
}
}
}
}
switch_mutex_unlock(l->filter_mutex);
}

View File

@ -101,7 +101,6 @@ static int next_file(switch_file_handle_t *handle)
handle->seekable = context->fh.seekable;
handle->speed = context->fh.speed;
handle->interval = context->fh.interval;
handle->flags = context->fh.flags;
if (context->index == 0) {
context->samples = (handle->samplerate / 1000) * 250;

View File

@ -3,6 +3,10 @@
#include "freeswitch_lua.h"
using namespace LUA;
extern "C" {
int docall(lua_State * L, int narg, int clear, int perror);
};
Session::Session():CoreSession()
{
cb_function = cb_arg = hangup_func_str = hangup_func_arg = NULL;
@ -137,7 +141,7 @@ void Session::do_hangup_hook()
arg_count++;
}
lua_call(L, arg_count, 1);
docall(L, arg_count, 1, 1);
err = lua_tostring(L, -1);
if (!zstr(err)) {
@ -273,7 +277,8 @@ switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t ityp
arg_count++;
}
lua_call(L, arg_count, 1);
docall(L, arg_count, 0, 1);
ret = lua_tostring(L, -1);
lua_pop(L, 1);
@ -297,7 +302,7 @@ switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t ityp
arg_count++;
}
lua_call(L, arg_count, 1);
docall(L, arg_count, 1, 1);
ret = lua_tostring(L, -1);
lua_pop(L, 1);
@ -374,7 +379,7 @@ int Dbh::query_callback(void *pArg, int argc, char **argv, char **cargv)
lua_settable(lua_fun->L, -3);
}
lua_call(lua_fun->L, 1, 1); /* 1 in, 1 out */
docall(lua_fun->L, 1, 1, 1); /* 1 in, 1 out */
if (lua_isnumber(lua_fun->L, -1)) {
if (lua_tonumber(lua_fun->L, -1) != 0) {

View File

@ -80,7 +80,7 @@ static int traceback(lua_State * L)
return 1;
}
static int docall(lua_State * L, int narg, int clear)
int docall(lua_State * L, int narg, int clear, int perror)
{
int status;
int base = lua_gettop(L) - narg; /* function index */
@ -92,13 +92,22 @@ static int docall(lua_State * L, int narg, int clear)
lua_remove(L, base); /* remove traceback function */
/* force a complete garbage collection in case of errors */
if (status != 0)
if (status != 0) {
lua_gc(L, LUA_GCCOLLECT, 0);
}
if (status && perror) {
const char *err = lua_tostring(L, -1);
if (!zstr(err)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", err);
}
lua_pop(L, 1); /* pop error message from the stack */
}
return status;
}
static lua_State *lua_init(void)
{
lua_State *L = lua_open();
@ -111,7 +120,7 @@ static lua_State *lua_init(void)
luaopen_freeswitch(L);
lua_gc(L, LUA_GCRESTART, 0);
lua_atpanic(L, panic);
error = luaL_loadbuffer(L, buff, strlen(buff), "line") || docall(L, 0, 1);
error = luaL_loadbuffer(L, buff, strlen(buff), "line") || docall(L, 0, 1, 0);
}
return L;
}
@ -128,7 +137,7 @@ static int lua_parse_and_execute(lua_State * L, char *input_code)
if (*input_code == '~') {
char *buff = input_code + 1;
error = luaL_loadbuffer(L, buff, strlen(buff), "line") || docall(L, 0, 1); //lua_pcall(L, 0, 0, 0);
error = luaL_loadbuffer(L, buff, strlen(buff), "line") || docall(L, 0, 1, 0); //lua_pcall(L, 0, 0, 0);
} else {
char *args = strchr(input_code, ' ');
if (args) {
@ -152,14 +161,14 @@ static int lua_parse_and_execute(lua_State * L, char *input_code)
}
if (code) {
error = luaL_loadbuffer(L, code, strlen(code), "line") || docall(L, 0, 1);
error = luaL_loadbuffer(L, code, strlen(code), "line") || docall(L, 0, 1, 0);
switch_safe_free(code);
}
} else {
// Force empty argv table
char *code = NULL;
code = switch_mprintf("argv = {[0]='%s'};", input_code);
error = luaL_loadbuffer(L, code, strlen(code), "line") || docall(L, 0, 1);
error = luaL_loadbuffer(L, code, strlen(code), "line") || docall(L, 0, 1, 0);
switch_safe_free(code);
}
@ -171,7 +180,7 @@ static int lua_parse_and_execute(lua_State * L, char *input_code)
switch_assert(fdup);
file = fdup;
}
error = luaL_loadfile(L, file) || docall(L, 0, 1);
error = luaL_loadfile(L, file) || docall(L, 0, 1, 0);
switch_safe_free(fdup);
}
}

View File

@ -23791,6 +23791,14 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_set_caller_extension(void * ja
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_flip_cid(void * jarg1) {
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
arg1 = (switch_channel_t *)jarg1;
switch_channel_flip_cid(arg1);
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_sort_cid(void * jarg1, int jarg2) {
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
switch_bool_t arg2 ;

View File

@ -3405,6 +3405,10 @@ public class freeswitch {
freeswitchPINVOKE.switch_channel_set_caller_extension(SWIGTYPE_p_switch_channel.getCPtr(channel), switch_caller_extension.getCPtr(caller_extension));
}
public static void switch_channel_flip_cid(SWIGTYPE_p_switch_channel channel) {
freeswitchPINVOKE.switch_channel_flip_cid(SWIGTYPE_p_switch_channel.getCPtr(channel));
}
public static void switch_channel_sort_cid(SWIGTYPE_p_switch_channel channel, switch_bool_t arg1) {
freeswitchPINVOKE.switch_channel_sort_cid(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)arg1);
}
@ -11486,6 +11490,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_set_caller_extension")]
public static extern void switch_channel_set_caller_extension(HandleRef jarg1, HandleRef jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_flip_cid")]
public static extern void switch_channel_flip_cid(HandleRef jarg1);
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_sort_cid")]
public static extern void switch_channel_sort_cid(HandleRef jarg1, int jarg2);
@ -21664,6 +21671,8 @@ public enum switch_channel_flag_t {
CF_DIALPLAN,
CF_BLOCK_BROADCAST_UNTIL_MEDIA,
CF_CNG_PLC,
CF_ATTENDED_TRANSFER,
CF_LAZY_ATTENDED_TRANSFER,
CF_FLAG_MAX
}

View File

@ -599,8 +599,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_xml_cdr_load)
}
if (globals.retries && globals.delay <= 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Retries set but delay 0 setting to 5000ms\n");
globals.delay = 5000;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Retries set but delay 0 setting to 5 seconds\n");
globals.delay = 5;
}
globals.retries++;

View File

@ -751,7 +751,7 @@ SWITCH_DECLARE(switch_event_header_t *) switch_channel_variable_first(switch_cha
switch_assert(channel != NULL);
switch_mutex_lock(channel->profile_mutex);
if ((hi = channel->variables->headers)) {
if (channel->variables && (hi = channel->variables->headers)) {
channel->vi = 1;
} else {
switch_mutex_unlock(channel->profile_mutex);
@ -1562,6 +1562,10 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_get_running_state(switch_c
SWITCH_DECLARE(int) switch_channel_state_change_pending(switch_channel_t *channel)
{
if (switch_channel_down(channel) || !switch_core_session_in_thread(channel->session)) {
return 0;
}
return channel->running_state != channel->state;
}
@ -2434,26 +2438,39 @@ SWITCH_DECLARE(switch_status_t) switch_channel_caller_extension_masquerade(switc
return status;
}
SWITCH_DECLARE(void) switch_channel_flip_cid(switch_channel_t *channel)
{
switch_mutex_lock(channel->profile_mutex);
if (channel->caller_profile->callee_id_name) {
switch_channel_set_variable(channel, "pre_transfer_caller_id_name", channel->caller_profile->caller_id_name);
channel->caller_profile->caller_id_name = switch_core_strdup(channel->caller_profile->pool, channel->caller_profile->callee_id_name);
}
channel->caller_profile->callee_id_name = SWITCH_BLANK_STRING;
if (channel->caller_profile->callee_id_number) {
switch_channel_set_variable(channel, "pre_transfer_caller_id_number", channel->caller_profile->caller_id_number);
channel->caller_profile->caller_id_number = switch_core_strdup(channel->caller_profile->pool, channel->caller_profile->callee_id_number);
}
channel->caller_profile->callee_id_number = SWITCH_BLANK_STRING;
switch_mutex_unlock(channel->profile_mutex);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session), SWITCH_LOG_INFO, "%s Flipping CID from \"%s\" <%s> to \"%s\" <%s>\n",
switch_channel_get_name(channel),
switch_channel_get_variable(channel, "pre_transfer_caller_id_name"),
switch_channel_get_variable(channel, "pre_transfer_caller_id_number"),
channel->caller_profile->caller_id_name,
channel->caller_profile->caller_id_number
);
}
SWITCH_DECLARE(void) switch_channel_sort_cid(switch_channel_t *channel, switch_bool_t in)
{
if (in) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !switch_channel_test_flag(channel, CF_DIALPLAN)) {
switch_channel_set_flag(channel, CF_DIALPLAN);
switch_mutex_lock(channel->profile_mutex);
if (channel->caller_profile->callee_id_name) {
switch_channel_set_variable(channel, "pre_transfer_caller_id_name", channel->caller_profile->caller_id_name);
channel->caller_profile->caller_id_name = switch_core_strdup(channel->caller_profile->pool, channel->caller_profile->callee_id_name);
}
channel->caller_profile->callee_id_name = SWITCH_BLANK_STRING;
if (channel->caller_profile->callee_id_number) {
switch_channel_set_variable(channel, "pre_transfer_caller_id_number", channel->caller_profile->caller_id_number);
channel->caller_profile->caller_id_number = switch_core_strdup(channel->caller_profile->pool, channel->caller_profile->callee_id_number);
}
channel->caller_profile->callee_id_number = SWITCH_BLANK_STRING;
switch_mutex_unlock(channel->profile_mutex);
switch_channel_flip_cid(channel);
}
return;
@ -2539,6 +2556,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_chan
if (hangup_cause == SWITCH_CAUSE_LOSE_RACE) {
switch_channel_presence(channel, "unknown", "cancelled", NULL);
switch_channel_set_variable(channel, "presence_call_info", NULL);
}

View File

@ -46,8 +46,10 @@ struct switch_cache_db_handle {
switch_memory_pool_t *pool;
int32_t flags;
unsigned long hash;
unsigned long thread_hash;
char creator[CACHE_DB_LEN];
char last_user[CACHE_DB_LEN];
uint32_t use_count;
struct switch_cache_db_handle *next;
};
@ -71,12 +73,36 @@ static struct {
} sql_manager;
static void add_handle(switch_cache_db_handle_t *dbh)
static switch_cache_db_handle_t *create_handle(switch_cache_db_handle_type_t type)
{
switch_cache_db_handle_t *new_dbh = NULL;
switch_memory_pool_t *pool = NULL;
switch_core_new_memory_pool(&pool);
new_dbh = switch_core_alloc(pool, sizeof(*new_dbh));
new_dbh->pool = pool;
new_dbh->type = type;
switch_mutex_init(&new_dbh->mutex, SWITCH_MUTEX_NESTED, new_dbh->pool);
return new_dbh;
}
static void add_handle(switch_cache_db_handle_t *dbh, const char *db_str, const char *db_callsite_str, const char *thread_str)
{
switch_ssize_t hlen = -1;
switch_mutex_lock(sql_manager.dbh_mutex);
switch_set_flag(dbh, CDF_INUSE);
switch_set_string(dbh->creator, db_callsite_str);
switch_set_string(dbh->name, db_str);
dbh->hash = switch_ci_hashfunc_default(db_str, &hlen);
dbh->thread_hash = switch_ci_hashfunc_default(thread_str, &hlen);
dbh->use_count++;
sql_manager.total_used_handles++;
dbh->next = sql_manager.handle_pool;
sql_manager.handle_pool = dbh;
sql_manager.total_handles++;
switch_mutex_lock(dbh->mutex);
@ -85,48 +111,61 @@ static void add_handle(switch_cache_db_handle_t *dbh)
static void del_handle(switch_cache_db_handle_t *dbh)
{
switch_cache_db_handle_t *dbhp, *last = NULL;
switch_cache_db_handle_t *dbh_ptr, *last = NULL;
switch_mutex_lock(sql_manager.dbh_mutex);
for (dbhp = sql_manager.handle_pool; dbhp; dbhp = dbhp->next) {
if (dbhp == dbh) {
for (dbh_ptr = sql_manager.handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) {
if (dbh_ptr == dbh) {
if (last) {
last->next = dbhp->next;
last->next = dbh_ptr->next;
} else {
sql_manager.handle_pool = dbhp->next;
sql_manager.handle_pool = dbh_ptr->next;
}
sql_manager.total_handles--;
break;
}
last = dbhp;
last = dbh_ptr;
}
switch_mutex_unlock(sql_manager.dbh_mutex);
}
static switch_cache_db_handle_t *get_handle(const char *db_str, const char *user_str)
static switch_cache_db_handle_t *get_handle(const char *db_str, const char *user_str, const char *thread_str)
{
switch_ssize_t hlen = -1;
unsigned long hash = 0;
switch_cache_db_handle_t *dbhp, *r = NULL;
unsigned long hash = 0, thread_hash = 0;
switch_cache_db_handle_t *dbh_ptr, *r = NULL;
hash = switch_ci_hashfunc_default(db_str, &hlen);
thread_hash = switch_ci_hashfunc_default(thread_str, &hlen);
switch_mutex_lock(sql_manager.dbh_mutex);
for (dbhp = sql_manager.handle_pool; dbhp; dbhp = dbhp->next) {
if (dbhp->hash == hash && !switch_test_flag(dbhp, CDF_INUSE) &&
!switch_test_flag(dbhp, CDF_PRUNE) && switch_mutex_trylock(dbhp->mutex) == SWITCH_STATUS_SUCCESS) {
r = dbhp;
switch_set_flag(dbhp, CDF_INUSE);
sql_manager.total_used_handles++;
dbhp->hash = switch_ci_hashfunc_default(db_str, &hlen);
switch_set_string(dbhp->last_user, user_str);
for (dbh_ptr = sql_manager.handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) {
if (dbh_ptr->thread_hash == thread_hash && dbh_ptr->hash == hash &&
!switch_test_flag(dbh_ptr, CDF_PRUNE) && switch_mutex_trylock(dbh_ptr->mutex) == SWITCH_STATUS_SUCCESS) {
r = dbh_ptr;
}
}
if (!r) {
for (dbh_ptr = sql_manager.handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) {
if (dbh_ptr->hash == hash && !dbh_ptr->use_count && !switch_test_flag(dbh_ptr, CDF_PRUNE) &&
switch_mutex_trylock(dbh_ptr->mutex) == SWITCH_STATUS_SUCCESS) {
r = dbh_ptr;
break;
}
}
}
if (r) {
r->use_count++;
sql_manager.total_used_handles++;
r->hash = switch_ci_hashfunc_default(db_str, &hlen);
r->thread_hash = thread_hash;
switch_set_string(r->last_user, user_str);
}
switch_mutex_unlock(sql_manager.dbh_mutex);
return r;
@ -190,7 +229,7 @@ static void sql_close(time_t prune)
diff = (time_t) prune - dbh->last_used;
}
if (prune > 0 && (switch_test_flag(dbh, CDF_INUSE) || (diff < SQL_CACHE_TIMEOUT && !switch_test_flag(dbh, CDF_PRUNE)))) {
if (prune > 0 && (dbh->use_count || (diff < SQL_CACHE_TIMEOUT && !switch_test_flag(dbh, CDF_PRUNE)))) {
continue;
}
@ -249,7 +288,12 @@ SWITCH_DECLARE(void) switch_cache_db_release_db_handle(switch_cache_db_handle_t
if (dbh && *dbh) {
switch_mutex_lock(sql_manager.dbh_mutex);
(*dbh)->last_used = switch_epoch_time_now(NULL);
switch_clear_flag((*dbh), CDF_INUSE);
if ((*dbh)->use_count) {
if (--(*dbh)->use_count == 0) {
(*dbh)->thread_hash = 1;
}
}
switch_mutex_unlock((*dbh)->mutex);
sql_manager.total_used_handles--;
*dbh = NULL;
@ -269,10 +313,11 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h
switch_cache_db_connection_options_t *connection_options,
const char *file, const char *func, int line)
{
switch_thread_id_t self = switch_thread_self();
char thread_str[CACHE_DB_LEN] = "";
char db_str[CACHE_DB_LEN] = "";
char db_callsite_str[CACHE_DB_LEN] = "";
switch_cache_db_handle_t *new_dbh = NULL;
switch_ssize_t hlen = -1;
int waiting = 0;
uint32_t yield_len = 100000, total_yield = 0;
@ -317,15 +362,15 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h
return SWITCH_STATUS_FALSE;
}
snprintf(db_str, sizeof(db_str) - 1, "db=\"%s\";user=\"%s\";pass=\"%s\"", db_name, db_user, db_pass);
snprintf(db_callsite_str, sizeof(db_callsite_str) - 1, "%s:%d", file, line);
snprintf(thread_str, sizeof(thread_str) - 1, "thread=\"%lu\"", (unsigned long) (intptr_t) self);
if ((new_dbh = get_handle(db_str, db_callsite_str))) {
if ((new_dbh = get_handle(db_str, db_callsite_str, thread_str))) {
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG10,
"Reuse Unused Cached DB handle %s [%s]\n", new_dbh->name, switch_cache_db_type_name(new_dbh->type));
} else {
switch_memory_pool_t *pool = NULL;
switch_core_db_t *db = NULL;
switch_odbc_handle_t *odbc_dbh = NULL;
@ -366,12 +411,7 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG10,
"Create Cached DB handle %s [%s] %s:%d\n", new_dbh->name, switch_cache_db_type_name(type), file, line);
switch_core_new_memory_pool(&pool);
new_dbh = switch_core_alloc(pool, sizeof(*new_dbh));
new_dbh->pool = pool;
new_dbh->type = type;
switch_set_string(new_dbh->name, db_str);
new_dbh->hash = switch_ci_hashfunc_default(db_str, &hlen);
new_dbh = create_handle(type);
if (db) {
new_dbh->native_handle.core_db_dbh = db;
@ -379,9 +419,7 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h
new_dbh->native_handle.odbc_dbh = odbc_dbh;
}
switch_mutex_init(&new_dbh->mutex, SWITCH_MUTEX_UNNESTED, new_dbh->pool);
switch_set_string(new_dbh->creator, db_callsite_str);
add_handle(new_dbh);
add_handle(new_dbh, db_str, db_callsite_str, thread_str);
}
end:
@ -1676,7 +1714,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_expire_registration(int force)
switch_cache_db_handle_t *dbh;
char *sql;
switch_time_t now;
time_t now;
if (!switch_test_flag((&runtime), SCF_USE_SQL)) {
return SWITCH_STATUS_FALSE;
@ -1937,17 +1975,17 @@ SWITCH_DECLARE(void) switch_cache_db_status(switch_stream_handle_t *stream)
count++;
if (switch_test_flag(dbh, CDF_INUSE)) {
if (dbh->use_count) {
used++;
}
stream->write_function(stream, "%s\n\tType: %s\n\tLast used: %d\n\tFlags: %s, %s\n"
stream->write_function(stream, "%s\n\tType: %s\n\tLast used: %d\n\tFlags: %s, %s(%d)\n"
"\tCreator: %s\n\tLast User: %s\n",
cleankey_str,
switch_cache_db_type_name(dbh->type),
diff,
locked ? "Locked" : "Unlocked",
switch_test_flag(dbh, CDF_INUSE) ? "Attached" : "Detached", dbh->creator, dbh->last_user);
dbh->use_count ? "Attached" : "Detached", dbh->use_count, dbh->creator, dbh->last_user);
}
stream->write_function(stream, "%d total. %d in use.\n", count, used);

View File

@ -386,6 +386,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
if (send_dtmf) {
switch_core_session_send_dtmf(session_b, &dtmf);
switch_core_session_kill_channel(session_b, SWITCH_SIG_BREAK);
}
}
}

View File

@ -1423,8 +1423,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_enterprise_originate(switch_core_sess
}
}
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "ent_originate_aleg_uuid", switch_core_session_get_uuid(session));
if (session) {
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "ent_originate_aleg_uuid", switch_core_session_get_uuid(session));
}
if (channel) {
switch_channel_process_export(channel, NULL, var_event, SWITCH_EXPORT_VARS_VARIABLE);
}
@ -3262,6 +3264,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
switch_channel_set_variable(switch_core_session_get_channel(holding_session), SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, "true");
switch_core_session_rwunlock(holding_session);
}
switch_channel_set_flag(peer_channel, CF_LAZY_ATTENDED_TRANSFER);
switch_ivr_uuid_bridge(holding, switch_core_session_get_uuid(peer_session));
holding = NULL;
oglobals.idx = IDX_NADA;
@ -3333,6 +3336,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
switch_channel_set_variable(switch_core_session_get_channel(holding_session), SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, "true");
switch_core_session_rwunlock(holding_session);
}
switch_channel_set_flag(originate_status[i].peer_channel, CF_LAZY_ATTENDED_TRANSFER);
switch_ivr_uuid_bridge(holding, switch_core_session_get_uuid(originate_status[i].peer_session));
holding = NULL;
} else {
@ -3609,6 +3613,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
}
if (*bleg) {
switch_channel_t *bchan = switch_core_session_get_channel(*bleg);
if (session && caller_channel) {
switch_caller_profile_t *cloned_profile, *peer_profile = switch_channel_get_caller_profile(switch_core_session_get_channel(*bleg));
@ -3618,6 +3624,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
}
}
}
while(switch_channel_state_change_pending(bchan)) {
switch_cond_next();
}
switch_ivr_sleep(*bleg, 0, SWITCH_TRUE, NULL);
}

View File

@ -374,7 +374,7 @@ SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load)
}
for (; countb > 0; countb--) {
switch_core_codec_add_implementation(pool, codec_interface,
SWITCH_CODEC_TYPE_AUDIO, 10, "L16", NULL, rate, rate, bps,
SWITCH_CODEC_TYPE_AUDIO, 70, "L16", NULL, rate, rate, bps,
mpf * countb, spf * countb, bpf * countb, ebpf * countb, 1, spf * countb,
switch_raw_init, switch_raw_encode, switch_raw_decode, switch_raw_destroy);
}
@ -391,7 +391,7 @@ SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load)
for (x = 0; x < 5; x++) {
switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
10, /* the IANA code number */
70, /* the IANA code number */
"L16", /* the IANA code name */
NULL, /* default fmtp to send (can be overridden by the init function) */
12000, /* samples transferred per second */

View File

@ -267,6 +267,8 @@ typedef enum {
RESULT_GOTO_TIMERCHECK
} handle_rfc2833_result_t;
static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session);
static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_size_t bytes, int *do_cng)
{
#ifdef DEBUG_2833
@ -1917,6 +1919,14 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *
return SWITCH_STATUS_FALSE;
}
if (queue_frames < 1) {
queue_frames = 3;
}
if (max_queue_frames < queue_frames) {
max_queue_frames = queue_frames * 3;
}
READ_INC(rtp_session);
if (rtp_session->jb) {
stfu_n_resize(rtp_session->jb, queue_frames);
@ -2182,7 +2192,10 @@ SWITCH_DECLARE(void) switch_rtp_set_flag(switch_rtp_t *rtp_session, switch_rtp_f
rtp_session->autoadj_window = 20;
rtp_session->autoadj_tally = 0;
rtp_flush_read_buffer(rtp_session, SWITCH_RTP_FLUSH_ONCE);
} else if (flags & SWITCH_RTP_FLAG_NOBLOCK) {
switch_socket_opt_set(rtp_session->sock_input, SWITCH_SO_NONBLOCK, TRUE);
}
}
SWITCH_DECLARE(uint32_t) switch_rtp_test_flag(switch_rtp_t *rtp_session, switch_rtp_flag_t flags)
@ -2193,6 +2206,10 @@ SWITCH_DECLARE(uint32_t) switch_rtp_test_flag(switch_rtp_t *rtp_session, switch_
SWITCH_DECLARE(void) switch_rtp_clear_flag(switch_rtp_t *rtp_session, switch_rtp_flag_t flags)
{
switch_clear_flag_locked(rtp_session, flags);
if (flags & SWITCH_RTP_FLAG_NOBLOCK) {
switch_socket_opt_set(rtp_session->sock_input, SWITCH_SO_NONBLOCK, FALSE);
}
}
static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session)
@ -2202,6 +2219,7 @@ static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session)
if (rtp_session->dtmf_data.out_digit_dur > 0) {
int x, loops = 1;
rtp_session->dtmf_data.out_digit_sofar += samples;
rtp_session->dtmf_data.out_digit_sub_sofar += samples;
@ -2240,7 +2258,7 @@ static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session)
if (loops != 1) {
rtp_session->last_write_ts = rtp_session->dtmf_data.timestamp_dtmf + rtp_session->dtmf_data.out_digit_sub_sofar;
rtp_session->sending_dtmf = 0;
if (rtp_session->timer.interval) {
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) {
rtp_session->last_write_samplecount = rtp_session->timer.samplecount;
rtp_session->next_write_samplecount = rtp_session->timer.samplecount + samples * 5;
}
@ -2251,7 +2269,7 @@ static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session)
if (!rtp_session->dtmf_data.out_digit_dur && rtp_session->dtmf_data.dtmf_queue && switch_queue_size(rtp_session->dtmf_data.dtmf_queue)) {
void *pop;
if (rtp_session->timer.interval) {
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) {
if (rtp_session->timer.samplecount < rtp_session->next_write_samplecount) {
return;
}
@ -2275,7 +2293,7 @@ static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session)
rtp_session->dtmf_data.timestamp_dtmf = rtp_session->last_write_ts + samples;
if (rtp_session->timer.interval) {
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) {
offset = rtp_session->timer.samplecount - rtp_session->last_write_samplecount;
if (offset > 0) {
rtp_session->dtmf_data.timestamp_dtmf = (uint32_t) (rtp_session->dtmf_data.timestamp_dtmf + offset);
@ -2409,9 +2427,9 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, bytes);
ts = ntohl(rtp_session->recv_msg.header.ts);
if (*bytes ) {
if (*bytes) {
uint16_t seq = ntohs((uint16_t) rtp_session->recv_msg.header.seq);
if (rtp_session->last_seq && rtp_session->last_seq+1 != seq) {
#ifdef DEBUG_MISSED_SEQ
switch_size_t flushed_packets_diff = rtp_session->stats.inbound.flush_packet_count - rtp_session->last_flush_packet_count;
@ -2485,16 +2503,92 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
rtp_session->last_read_ts = ts;
if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL)) {
#ifdef ENABLE_ZRTP
/* ZRTP Recv */
if (*bytes) {
unsigned int sbytes = (int) *bytes;
zrtp_status_t stat = 0;
stat = zrtp_process_srtp(rtp_session->zrtp_stream, (void *) &rtp_session->recv_msg, &sbytes);
switch (stat) {
case zrtp_status_ok:
*bytes = sbytes;
break;
case zrtp_status_drop:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection drop with code %d\n", stat);
*bytes = 0;
return SWITCH_STATUS_SUCCESS;
case zrtp_status_fail:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection fail with code %d\n", stat);
return SWITCH_STATUS_FALSE;
default:
break;
}
}
#endif
if (*bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_RECV)) {
int sbytes = (int) *bytes;
err_status_t stat = 0;
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_RECV_RESET)) {
switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_SECURE_RECV_RESET);
srtp_dealloc(rtp_session->recv_ctx);
rtp_session->recv_ctx = NULL;
if ((stat = srtp_create(&rtp_session->recv_ctx, &rtp_session->recv_policy))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error! RE-Activating Secure RTP RECV\n");
return SWITCH_STATUS_FALSE;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "RE-Activating Secure RTP RECV\n");
rtp_session->srtp_errs = 0;
}
}
if (!(*flags & SFF_PLC)) {
stat = srtp_unprotect(rtp_session->recv_ctx, &rtp_session->recv_msg.header, &sbytes);
}
if (stat && rtp_session->recv_msg.header.pt != rtp_session->recv_te && rtp_session->recv_msg.header.pt != rtp_session->cng_pt) {
if (++rtp_session->srtp_errs >= MAX_SRTP_ERRS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Error: SRTP unprotect failed with code %d%s\n", stat,
stat == err_status_replay_fail ? " (replay check failed)" : stat ==
err_status_auth_fail ? " (auth check failed)" : "");
return SWITCH_STATUS_FALSE;
} else {
sbytes = 0;
}
} else {
rtp_session->srtp_errs = 0;
}
*bytes = sbytes;
}
}
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_BYTESWAP) && rtp_session->recv_msg.header.pt == rtp_session->rpayload) {
switch_swap_linear((int16_t *)rtp_session->recv_msg.body, (int) *bytes - rtp_header_len);
}
if (rtp_session->jb && !rtp_session->pause_jb && rtp_session->recv_msg.header.version == 2 && *bytes) {
if (rtp_session->recv_msg.header.m && rtp_session->recv_msg.header.pt != rtp_session->recv_te &&
!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO) && !(rtp_session->rtp_bugs & RTP_BUG_IGNORE_MARK_BIT)) {
stfu_n_reset(rtp_session->jb);
}
if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER) && rtp_session->timer.interval) {
switch_core_timer_sync(&rtp_session->timer);
}
if (stfu_n_eat(rtp_session->jb, rtp_session->last_read_ts,
rtp_session->recv_msg.header.pt,
rtp_session->recv_msg.body, *bytes - rtp_header_len, rtp_session->timer.samplecount) == STFU_ITS_TOO_LATE) {
printf("doh\n");
goto more;
}
@ -2657,7 +2751,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
return -1;
}
if (rtp_session->timer.interval) {
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) {
sleep_mss = rtp_session->timer.interval * 1000;
}
@ -2668,7 +2762,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
int read_pretriggered = 0;
bytes = 0;
if (rtp_session->timer.interval) {
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) {
if ((switch_test_flag(rtp_session, SWITCH_RTP_FLAG_AUTOFLUSH) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_STICKY_FLUSH)) &&
rtp_session->read_pollfd) {
if (switch_poll(rtp_session->read_pollfd, 1, &fdr, 0) == SWITCH_STATUS_SUCCESS) {
@ -2722,11 +2816,14 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
if (!switch_rtp_ready(rtp_session)) {
break;
}
if (!rtp_session->timer.interval && rtp_session->read_pollfd) {
if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER) && rtp_session->read_pollfd) {
int pt = poll_sec * 1000000;
if (rtp_session->dtmf_data.out_digit_dur > 0 || rtp_session->dtmf_data.in_digit_sanity) {
do_2833(rtp_session, session);
if (rtp_session->dtmf_data.out_digit_dur > 0 || rtp_session->dtmf_data.in_digit_sanity || rtp_session->sending_dtmf ||
switch_queue_size(rtp_session->dtmf_data.dtmf_queue) || switch_queue_size(rtp_session->dtmf_data.dtmf_inqueue)) {
pt = 20000;
}
@ -2735,7 +2832,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
}
poll_status = switch_poll(rtp_session->read_pollfd, 1, &fdr, pt);
do_2833(rtp_session, session);
if (rtp_session->dtmf_data.out_digit_dur > 0) {
return_cng_frame();
@ -3037,31 +3133,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
if (check || bytes) {
do_2833(rtp_session, session);
}
#ifdef ENABLE_ZRTP
/* ZRTP Recv */
if (bytes) {
unsigned int sbytes = (int) bytes;
zrtp_status_t stat = 0;
stat = zrtp_process_srtp(rtp_session->zrtp_stream, (void *) &rtp_session->recv_msg, &sbytes);
switch (stat) {
case zrtp_status_ok:
bytes = sbytes;
break;
case zrtp_status_drop:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection drop with code %d\n", stat);
bytes = 0;
goto do_continue;
case zrtp_status_fail:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection fail with code %d\n", stat);
ret = -1;
goto end;
default:
break;
}
}
#endif
if (bytes && rtp_session->recv_msg.header.version != 2) {
uint8_t *data = (uint8_t *) rtp_session->recv_msg.body;
@ -3088,43 +3159,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
goto end;
}
if (bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_RECV)) {
int sbytes = (int) bytes;
err_status_t stat = 0;
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_RECV_RESET)) {
switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_SECURE_RECV_RESET);
srtp_dealloc(rtp_session->recv_ctx);
rtp_session->recv_ctx = NULL;
if ((stat = srtp_create(&rtp_session->recv_ctx, &rtp_session->recv_policy))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error! RE-Activating Secure RTP RECV\n");
ret = -1;
goto end;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "RE-Activating Secure RTP RECV\n");
rtp_session->srtp_errs = 0;
}
}
stat = srtp_unprotect(rtp_session->recv_ctx, &rtp_session->recv_msg.header, &sbytes);
if (stat && rtp_session->recv_msg.header.pt != rtp_session->recv_te && rtp_session->recv_msg.header.pt != rtp_session->cng_pt) {
if (++rtp_session->srtp_errs >= MAX_SRTP_ERRS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Error: SRTP unprotect failed with code %d%s\n", stat,
stat == err_status_replay_fail ? " (replay check failed)" : stat ==
err_status_auth_fail ? " (auth check failed)" : "");
ret = -1;
goto end;
} else {
sbytes = 0;
}
} else {
rtp_session->srtp_errs = 0;
}
bytes = sbytes;
}
/* Handle incoming RFC2833 packets */
switch (handle_rfc2833(rtp_session, bytes, &do_cng)) {
@ -3160,7 +3194,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
goto end;
}
if (check || (bytes && !rtp_session->timer.interval)) {
if (check || (bytes && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER))) {
if (!bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) { /* We're late! We're Late! */
if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK) && status == SWITCH_STATUS_BREAK) {
switch_cond_next();
@ -3186,7 +3221,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
do_continue:
if (!bytes && !rtp_session->timer.interval) {
if (!bytes && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) {
switch_yield(sleep_mss);
}
@ -3522,7 +3557,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
if (rtp_session->ts <= rtp_session->last_write_ts && !(rtp_session->rtp_bugs & RTP_BUG_NEVER_SEND_MARKER)) {
m++;
}
} else if (rtp_session->timer.timer_interface) {
} else if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) {
rtp_session->ts = rtp_session->timer.samplecount;
if (rtp_session->ts <= rtp_session->last_write_ts && rtp_session->ts > 0) {
@ -3540,11 +3575,12 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
m++;
}
if (rtp_session->timer.interval && (rtp_session->timer.samplecount - rtp_session->last_write_samplecount) > rtp_session->samples_per_interval * 10) {
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER) &&
(rtp_session->timer.samplecount - rtp_session->last_write_samplecount) > rtp_session->samples_per_interval * 10) {
m++;
}
if (!rtp_session->timer.interval &&
if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER) &&
((unsigned) ((switch_micro_time_now() - rtp_session->last_write_timestamp))) > (rtp_session->ms_per_packet * 10)) {
m++;
}
@ -3676,6 +3712,11 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
if (send) {
send_msg->header.seq = htons(++rtp_session->seq);
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_BYTESWAP) && send_msg->header.pt == rtp_session->payload) {
switch_swap_linear((int16_t *)send_msg->body, (int) datalen);
}
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND)) {
int sbytes = (int) bytes;
err_status_t stat;
@ -3785,7 +3826,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
rtp_session->stats.outbound.media_bytes += bytes;
}
if (rtp_session->timer.interval) {
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) {
rtp_session->last_write_samplecount = rtp_session->timer.samplecount;
} else {
rtp_session->last_write_timestamp = (uint32_t) switch_micro_time_now();

View File

@ -208,9 +208,6 @@ SWITCH_DECLARE(void) switch_time_calibrate_clock(void)
}
if (res > 1500) {
STEP_MS = res / 1000;
STEP_MIC = res;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Timer resolution of %ld microseconds detected!\n"
"Do you have your kernel timer frequency set to lower than 1,000Hz? "

View File

@ -95,13 +95,6 @@ typedef struct {
int glob(const char *, int, int (*)(const char *, int), glob_t *);
void globfree(glob_t *);
#endif
#undef HAVE_MMAP
#ifdef HAVE_MMAP
#include <sys/mman.h>
#ifdef __sun
extern int madvise(caddr_t, size_t, int);
#endif
#endif
#define SWITCH_XML_WS "\t\r\n " /* whitespace */
@ -114,7 +107,7 @@ struct switch_xml_root { /* additional data for the root tag */
struct switch_xml xml; /* is a super-struct built on top of switch_xml struct */
switch_xml_t cur; /* current xml tree insertion point */
char *m; /* original xml string */
switch_size_t len; /* length of allocated memory for mmap */
switch_size_t len; /* length of allocated memory */
uint8_t dynamic; /* Free the original string when calling switch_xml_free */
char *u; /* UTF-8 conversion of string if original was UTF-16 */
char *s; /* start of work area */
@ -124,6 +117,11 @@ struct switch_xml_root { /* additional data for the root tag */
char ***pi; /* processing instructions */
short standalone; /* non-zero if <?xml standalone="yes"?> */
char err[SWITCH_XML_ERRL]; /* error string */
/*! is_main_xml_root */
switch_bool_t is_main_xml_root;
/*! rwlock */
switch_thread_rwlock_t *rwlock;
};
char *SWITCH_XML_NIL[] = { NULL }; /* empty, null terminated array of strings */
@ -139,11 +137,11 @@ struct switch_xml_binding {
static switch_xml_binding_t *BINDINGS = NULL;
static switch_xml_t MAIN_XML_ROOT = NULL;
static switch_memory_pool_t *XML_MEMORY_POOL = NULL;
static switch_thread_rwlock_t *RWLOCK = NULL;
static switch_thread_rwlock_t *B_RWLOCK = NULL;
static switch_mutex_t *XML_LOCK = NULL;
static switch_thread_rwlock_t *XML_RWLOCK = NULL;
static switch_mutex_t *XML_GEN_LOCK = NULL;
static switch_mutex_t *XML_FREE_LOCK = NULL;
static switch_mutex_t *XML_RWFILE_LOCK = NULL;
struct xml_section_t {
const char *name;
@ -1161,28 +1159,16 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_parse_fd(int fd)
return NULL;
}
#ifdef HAVE_MMAP
l = (st.st_size + sysconf(_SC_PAGESIZE) - 1) & ~(sysconf(_SC_PAGESIZE) - 1);
if ((m = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)) != MAP_FAILED) {
madvise(m, l, MADV_SEQUENTIAL); /* optimize for sequential access */
if (!(root = (switch_xml_root_t) switch_xml_parse_str(m, st.st_size))) {
munmap(m, l);
}
madvise(m, root->len = l, MADV_NORMAL); /* put it back to normal */
} else { /* mmap failed, read file into memory */
#endif /* HAVE_MMAP */
m = malloc(st.st_size);
if (!m)
return NULL;
l = read(fd, m, st.st_size);
if (!l || !(root = (switch_xml_root_t) switch_xml_parse_str((char *) m, l))) {
free(m);
return NULL;
}
root->dynamic = 1; /* so we know to free s in switch_xml_free() */
#ifdef HAVE_MMAP
m = malloc(st.st_size);
if (!m)
return NULL;
l = read(fd, m, st.st_size);
if (!l || !(root = (switch_xml_root_t) switch_xml_parse_str((char *) m, l))) {
free(m);
return NULL;
}
#endif /* HAVE_MMAP */
root->dynamic = 1; /* so we know to free s in switch_xml_free() */
return &root->xml;
}
@ -1542,9 +1528,11 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_parse_file(const char *file)
} else {
abs = file;
}
/* Protection against running this code twice on the same filename */
switch_mutex_lock(XML_RWFILE_LOCK);
if (!(new_file = switch_mprintf("%s%s%s.fsxml", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, abs))) {
return NULL;
goto done;
}
if ((write_fd = open(new_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) < 0) {
@ -1571,6 +1559,7 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_parse_file(const char *file)
if (fd > -1) {
close(fd);
}
switch_mutex_unlock(XML_RWFILE_LOCK);
switch_safe_free(new_file);
return xml;
}
@ -1933,8 +1922,16 @@ SWITCH_DECLARE(switch_status_t) switch_xml_locate_user(const char *key,
SWITCH_DECLARE(switch_xml_t) switch_xml_root(void)
{
switch_thread_rwlock_rdlock(RWLOCK);
return MAIN_XML_ROOT;
switch_xml_root_t root = NULL;
switch_thread_rwlock_rdlock(XML_RWLOCK);
if (MAIN_XML_ROOT) {
root = (switch_xml_root_t) MAIN_XML_ROOT;
switch_thread_rwlock_rdlock(root->rwlock);
}
switch_thread_rwlock_unlock(XML_RWLOCK);
return (switch_xml_t) root;
}
struct destroy_xml {
@ -1978,15 +1975,14 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_open_root(uint8_t reload, const char **e
{
char path_buf[1024];
uint8_t errcnt = 0;
switch_xml_t new_main, r = NULL;
switch_xml_t r = NULL, new_main;
switch_mutex_lock(XML_LOCK);
if (!reload) {
r = switch_xml_root();
}
if (MAIN_XML_ROOT) {
if (!reload) {
r = switch_xml_root();
goto done;
}
if (r) {
goto done;
}
switch_snprintf(path_buf, sizeof(path_buf), "%s%s%s", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR, "freeswitch.xml");
@ -1999,18 +1995,27 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_open_root(uint8_t reload, const char **e
new_main = NULL;
errcnt++;
} else {
switch_xml_t old_root;
switch_xml_t old_root = NULL;
switch_xml_root_t new_main_root = (switch_xml_root_t) new_main;
new_main_root->is_main_xml_root = SWITCH_TRUE;
*err = "Success";
switch_thread_rwlock_wrlock(RWLOCK);
old_root = switch_xml_root();
old_root = MAIN_XML_ROOT;
switch_set_flag(new_main, SWITCH_XML_ROOT);
switch_thread_rwlock_wrlock(XML_RWLOCK);
MAIN_XML_ROOT = new_main;
switch_set_flag(MAIN_XML_ROOT, SWITCH_XML_ROOT);
switch_thread_rwlock_unlock(XML_RWLOCK);
switch_thread_rwlock_unlock(RWLOCK);
if (old_root) {
switch_clear_flag(old_root, SWITCH_XML_ROOT);
}
switch_xml_free(old_root);
/* switch_xml_free_in_thread(old_root); */
}
} else {
@ -2030,8 +2035,6 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_open_root(uint8_t reload, const char **e
done:
switch_mutex_unlock(XML_LOCK);
return r;
}
@ -2053,10 +2056,11 @@ SWITCH_DECLARE(switch_status_t) switch_xml_init(switch_memory_pool_t *pool, cons
XML_MEMORY_POOL = pool;
*err = "Success";
switch_mutex_init(&XML_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL);
switch_mutex_init(&XML_GEN_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL);
switch_thread_rwlock_create(&RWLOCK, XML_MEMORY_POOL);
switch_mutex_init(&XML_FREE_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL);
switch_mutex_init(&XML_RWFILE_LOCK, SWITCH_MUTEX_NESTED, XML_MEMORY_POOL);
switch_thread_rwlock_create(&B_RWLOCK, XML_MEMORY_POOL);
switch_thread_rwlock_create(&XML_RWLOCK, XML_MEMORY_POOL);
assert(pool != NULL);
@ -2071,7 +2075,7 @@ SWITCH_DECLARE(switch_status_t) switch_xml_init(switch_memory_pool_t *pool, cons
SWITCH_DECLARE(switch_status_t) switch_xml_destroy(void)
{
switch_status_t status = SWITCH_STATUS_FALSE;
switch_mutex_lock(XML_LOCK);
switch_thread_rwlock_wrlock(XML_RWLOCK);
if (MAIN_XML_ROOT) {
switch_xml_t xml = MAIN_XML_ROOT;
@ -2080,7 +2084,7 @@ SWITCH_DECLARE(switch_status_t) switch_xml_destroy(void)
status = SWITCH_STATUS_SUCCESS;
}
switch_mutex_unlock(XML_LOCK);
switch_thread_rwlock_unlock(XML_RWLOCK);
return status;
}
@ -2367,14 +2371,34 @@ SWITCH_DECLARE(void) switch_xml_free(switch_xml_t xml)
char **a, *s;
switch_xml_t orig_xml;
tailrecurse:
root = (switch_xml_root_t) xml;
if (!xml) {
return;
}
if (xml == MAIN_XML_ROOT) {
switch_thread_rwlock_unlock(RWLOCK);
/* If xml is currenly the MAIN_XML_ROOT, dont even bother to check to empty it */
if (switch_test_flag(xml, SWITCH_XML_ROOT)) {
switch_thread_rwlock_unlock(root->rwlock);
return;
}
/* This is a trick to find if the struct is still in use or not */
switch_mutex_lock(XML_FREE_LOCK);
if (xml->is_switch_xml_root_t == SWITCH_TRUE && root->is_main_xml_root == SWITCH_TRUE) {
switch_thread_rwlock_unlock(root->rwlock);
if (switch_thread_rwlock_trywrlock(root->rwlock) != SWITCH_STATUS_SUCCESS) {
/* XML Struct is still in used, person who free it will clean it */
switch_mutex_unlock(XML_FREE_LOCK);
return;
}
switch_thread_rwlock_unlock(root->rwlock);
switch_thread_rwlock_destroy(root->rwlock);
}
switch_mutex_unlock(XML_FREE_LOCK);
tailrecurse:
root = (switch_xml_root_t) xml;
if (!xml) {
return;
}
@ -2418,15 +2442,12 @@ SWITCH_DECLARE(void) switch_xml_free(switch_xml_t xml)
if (root->dynamic == 1)
free(root->m); /* malloced xml data */
#ifdef HAVE_MMAP
else if (root->len)
munmap(root->m, root->len); /* mem mapped xml data */
#endif /* HAVE_MMAP */
if (root->u)
free(root->u); /* utf8 conversion */
}
switch_xml_free_attr(xml->attr); /* tag attributes */
if ((xml->flags & SWITCH_XML_TXTM))
free(xml->txt); /* character content */
if ((xml->flags & SWITCH_XML_NAMEM))
@ -2464,6 +2485,8 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_new(const char *name)
root->ent = (char **) memcpy(malloc(sizeof(ent)), ent, sizeof(ent));
root->attr = root->pi = (char ***) (root->xml.attr = SWITCH_XML_NIL);
root->xml.is_switch_xml_root_t = SWITCH_TRUE;
root->is_main_xml_root = SWITCH_FALSE;
switch_thread_rwlock_create(&root->rwlock, XML_MEMORY_POOL);
return &root->xml;
}

View File

@ -82,20 +82,25 @@ echo -n "paste=Send&remember=0&poster=$user&format=none&expiry=f&code2=" > $post
echo "LSB RELEASE:" >> $post_file
echo $line >> $post_file
lsb_release -a >> $post_file
if [ -f /etc/redhat-release ] ; then
cat /etc/redhat-release >> $post_file
else
lsb_release -a >> $post_file
fi
echo "CPU INFO:" >> $post_file
echo $line >> $post_file
cat /proc/cpuinfo >> $post_file
echo "SVN INFO:" >> $post_file
echo "GIT INFO:" >> $post_file
echo $line >> $post_file
echo -n "Revision: " >> $post_file
if [ -d ".svn" ] ; then
svnversion . >> $post_file
svn stat | grep -v \? >> $post_file
if [ -d ".git" ] ; then
git log -1 | cat >> $post_file
printf "\n\n\n" >> $post_file
git status >> $post_file
else
echo "Not run from an svn managed directory." >> $post_file
echo "Not run from an git managed directory." >> $post_file
fi
echo "GDB BACKTRACE:" >> $post_file