forked from Mirrors/freeswitch
Merge remote branch 'fsorig/master'
This commit is contained in:
commit
28494cae6a
23
.gitignore
vendored
23
.gitignore
vendored
@ -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
|
||||
|
@ -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
35
conf/README_IMPORTANT.txt
Normal 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!
|
@ -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"/>
|
||||
|
77
conf/dialplan/default/00_ladspa.xml
Normal file
77
conf/dialplan/default/00_ladspa.xml
Normal 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>
|
@ -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>
|
||||
|
2
debian/freeswitch-python.install
vendored
2
debian/freeswitch-python.install
vendored
@ -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
1
debian/rules
vendored
@ -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.
|
||||
|
@ -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
22
libs/.gitignore
vendored
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
|
5
libs/freetdm/.gitignore
vendored
5
libs/freetdm/.gitignore
vendored
@ -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/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -118,7 +118,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""C:\Program Files\sangoma\sng_isdn\include";../../include;"C:\Program Files\Sangoma\include""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="2"
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -1 +1 @@
|
||||
Wed Nov 3 13:53:34 EDT 2010
|
||||
Tue Mar 8 12:40:45 CST 2011
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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($$) {
|
||||
|
@ -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);
|
||||
|
||||
/*!
|
||||
|
@ -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
1
src/mod/.gitignore
vendored
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
5
src/mod/applications/mod_ladspa/Makefile
Normal file
5
src/mod/applications/mod_ladspa/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
BASE=../../../..
|
||||
|
||||
LOCAL_OBJS += load.o
|
||||
include $(BASE)/build/modmake.rules
|
||||
|
173
src/mod/applications/mod_ladspa/load.c
Normal file
173
src/mod/applications/mod_ladspa/load.c
Normal 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 */
|
674
src/mod/applications/mod_ladspa/mod_ladspa.c
Normal file
674
src/mod/applications/mod_ladspa/mod_ladspa.c
Normal 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
|
||||
*/
|
72
src/mod/applications/mod_ladspa/utils.h
Normal file
72
src/mod/applications/mod_ladspa/utils.h
Normal 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 */
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
include $(top_srcdir)/build/modmake.rulesam
|
||||
|
||||
MODNAME=mod_com_g729
|
||||
VERSION=193
|
||||
VERSION=194
|
||||
|
||||
if ISLINUX
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 ;
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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++;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
201
src/switch_rtp.c
201
src/switch_rtp.c
@ -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();
|
||||
|
@ -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? "
|
||||
|
143
src/switch_xml.c
143
src/switch_xml.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user